home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Games / SprocketInvaders / Source / SoundHandler.c < prev    next >
Encoding:
Text File  |  2000-09-28  |  9.3 KB  |  335 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        SoundHandler.c
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998-1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     File Ownership:
  11.  
  12.         DRI:                Chris De Salvo
  13.  
  14.         Other Contact:        xxx put other contact here xxx
  15.  
  16.         Technology:            Apple Game Sprockets
  17.  
  18.     Writers:
  19.  
  20.         (cjd)    Chris De Salvo
  21.         (cjd)    Chris DeSalvo
  22.  
  23.     Change History (most recent first):
  24.  
  25.       <SP12>      7/1/99    cjd        The camera and the point of interest were set to the same point.
  26.                                     Bad. So we now push in the Z of the POI and pull back the Z of
  27.                                     the camera.
  28.       <SP11>     6/30/99    cjd        The camera and the point of interest were set to the same point.
  29.                                     Bad. So we now push in the Z of the POI and pull back the Z of
  30.                                     the camera.
  31.       <SP10>     1/21/99    cjd        Removing 68K conditional
  32.          <9>      7/1/98    cjd        Added SSp CPU load throttling
  33. */
  34.  
  35. //•    ------------------------------------------------------------------------------------------    •
  36. //•
  37. //•    Copyright © 1996 Apple Computer, Inc., All Rights Reserved
  38. //•
  39. //•
  40. //•        You may incorporate this sample code into your applications without
  41. //•        restriction, though the sample code has been provided "AS IS" and the
  42. //•        responsibility for its operation is 100% yours.  However, what you are
  43. //•        not permitted to do is to redistribute the source as "DSC Sample Code"
  44. //•        after having made changes. If you're going to re-distribute the source,
  45. //•        we require that you make it clear in the source that the code was
  46. //•        descended from Apple Sample Code, but that you've made changes.
  47. //•
  48. //•        Authors:
  49. //•            Chris De Salvo
  50. //•            Tim Carroll
  51. //•
  52. //•    ------------------------------------------------------------------------------------------    •
  53.  
  54. //•    ------------------------------    Includes
  55.  
  56. #include <Resources.h>
  57. #include <Sound.h>
  58. #include <SoundSprocket.h>
  59. #include <SoundComponents.h>
  60. #include <CodeFragments.h>
  61.  
  62. #include "ErrorHandler.h"
  63. #include "EventHandler.h"
  64. #include "MemoryHandler.h"
  65. #include "SIResources.h"
  66. #include "SoundHandler.h"
  67.  
  68. //•    ------------------------------    Private Definitions
  69. //•    ------------------------------    Private Types
  70. //•    ------------------------------    Private Variables
  71.  
  72. static Boolean gSoundHandlerInit = false;
  73. static SndChannelPtr gChannels[soundNumSounds];
  74. static Handle gSounds[soundNumSounds];
  75. static SSpSourceReference gSource[soundNumSounds];
  76. static SSpListenerReference gListener;
  77. static Boolean gSoundSprocket = false;
  78.  
  79. //•    ------------------------------    Private Functions
  80.  
  81. static void SetListenerLocation(const SInt32 inPOI_X, const SInt32 inPOI_Y);
  82.  
  83. //•    ------------------------------    Public Variables
  84.  
  85. Boolean gSoundEffects = true;
  86.  
  87. UInt32    gCPULoadModifier = 0;
  88. UInt32    gCPULoadMax = 0;
  89. UInt32    gCPUCurrentLoad = 0;
  90.  
  91. //•    --------------------    SoundHandlerInit
  92.  
  93. void
  94. SoundHandlerInit(void)
  95. {
  96. UInt32    i;
  97.  
  98.     gSoundSprocket = false;
  99.     
  100.     //•    Allocate the sound channels for playback
  101.     for (i = 0; i < soundNumSounds; i++)
  102.     {
  103.     OSErr    theErr;
  104.  
  105.         theErr = SndNewChannel(&gChannels[i], sampledSynth, initMono, nil);
  106.         if (theErr)
  107.             FatalError("Could not allocate enough sound channels.");
  108.     }
  109.  
  110.     //•    Load the actual sound effects
  111.     for (i = 0; i < soundNumSounds; i++)
  112.     {
  113.         gSounds[i] = GetResource('snd ', kSND_PlayerFire + i);
  114.         if (! gSounds[i])
  115.             FatalError("Could not load a required sound effect.");
  116.             
  117.         DetachResource(gSounds[i]);
  118.     }
  119.  
  120.     gSoundHandlerInit = true;
  121.  
  122.     //•    If SoundSprocket is present then create a listener and set things up
  123.     if ((Ptr) SSpConfigureSpeakerSetup == (Ptr) kUnresolvedCFragSymbolAddress)
  124.     {
  125.         return;  // no sound sprocket
  126.     }
  127.     else    
  128.     {
  129.     OSStatus    theErr = noErr;
  130.     
  131.         theErr = SSpGetCPULoadLimit(&gCPULoadMax);
  132.  
  133.         if (noErr != theErr)
  134.         {
  135.             //•    If we couldn't figure out the number of steps then we'll
  136.             //•    just set the CPU load to zero every time.  This forces maximum quality.
  137.             gCPULoadModifier = 0;
  138.         }
  139.         else
  140.         {
  141.             gCPULoadModifier = 0xFFFFFFFF / (gCPULoadMax + 1);
  142.         }
  143.         
  144.         //•    We have sound sprocket, so now we install the filters and create source and listener objects.
  145.     
  146.         //•    Create the listener
  147.         theErr = SSpListener_New(&gListener);
  148.         if (theErr)
  149.             FatalError("Could not create a sound sprocket listener.");
  150.     
  151.         //•    Define our unit of distance measurement
  152.         theErr = SSpListener_SetMetersPerUnit(gListener, 0.05);
  153.         if (theErr)
  154.             FatalError ("Could not set reference distance for listener.");
  155.     
  156.         //•    Attach the sound localization component to each of the sound
  157.         //•    channels that we'll be playing through.
  158.         for (i = 0; i < soundNumSounds; i++)
  159.         {
  160.         SoundComponentLink    myLink;
  161.             
  162.             //•    Create the source
  163.             theErr = SSpSource_New(&gSource[i]);
  164.             if (theErr)
  165.                 FatalError("Could not create a sound sprocket source.");
  166.             
  167.             //•    Install the filter
  168.             myLink.description.componentType = kSoundEffectsType;
  169.             myLink.description.componentSubType = kSSpLocalizationSubType;
  170.             myLink.description.componentManufacturer = 0;
  171.             myLink.description.componentFlags = 0; 
  172.             myLink.description.componentFlagsMask = 0;
  173.             myLink.mixerID = nil; 
  174.             myLink.linkID = nil;
  175.             
  176.             theErr = SndSetInfo(gChannels[i], siPreMixerSoundComponent, &myLink);
  177.              if (theErr) 
  178.                  FatalError("Could not install the sound sprocket filter into the channel.");
  179.         }
  180.         
  181.         gSoundSprocket = true;
  182.         SetListenerLocation(320, 240);
  183.     }
  184. }
  185.  
  186. //•    --------------------    SoundHandlerReset
  187.  
  188. void
  189. SoundHandlerReset(void)
  190. {
  191. UInt32    i;
  192.  
  193.     if (! gSoundHandlerInit)
  194.         return;
  195.  
  196.     //•    Deallocate the sound channels
  197.     for (i = 0; i < soundNumSounds; i++)
  198.     {
  199.         if (gChannels[i])
  200.         {
  201.             SndDisposeChannel(gChannels[i], true);
  202.             gChannels[i] = nil;
  203.         }
  204.     }
  205.  
  206.     //•    Unload the actual sound effects
  207.     for (i = 0; i < soundNumSounds; i++)
  208.     {
  209.         if (gSounds[i])
  210.             DisposeHandleZ(&gSounds[i]);
  211.     }
  212.  
  213. }
  214.  
  215. //•    --------------------    SoundHandlerPlay
  216.  
  217. void
  218. SoundHandlerPlay(GameSounds theSound, short x, short y)
  219. {
  220. SndCommand    theCommand;
  221. OSStatus    theErr = noErr;
  222.  
  223.     //•    Make sure that sound effects are turned on
  224.     if (! gSoundEffects)
  225.         return;
  226.  
  227.     //•    Make sure we are initialized
  228.     if (! gSoundHandlerInit)
  229.         return;
  230.  
  231.     //•    Make sure the requested sound is within the range of valid effects
  232.     if (theSound < 0 || theSound >= soundNumSounds)
  233.         return;
  234.  
  235.     //•    Stop playback of any sound currently playing on this channel
  236.     theCommand.cmd = quietCmd;
  237.     SndDoImmediate(gChannels[theSound], &theCommand);
  238.  
  239.     //•    Flush out any queued sounds waiting to play on this channel
  240.     theCommand.cmd = flushCmd;
  241.     SndDoImmediate(gChannels[theSound], &theCommand);
  242.  
  243.     //• If we're using SoundSprocket then set up the location parameters
  244.     //•    for the localization filter
  245.     if (gSoundSprocket)
  246.     {
  247.     TQ3CameraPlacement    location;
  248.     SSpLocalizationData    localization;
  249.     
  250.         //•    We want all the sounds to be localized, but when we explode we want to hear it
  251.         //•    all around us.
  252.         if (soundPlayerHit != theSound)
  253.             SSpSource_SetMode(gSource[theSound], kSSpSourceMode_Localized);
  254.         else
  255.             SSpSource_SetMode(gSource[theSound], kSSpSourceMode_Ambient);
  256.  
  257.         //•    Allow the user to dynamically set the CPU usage range for SSp
  258.         SSpSource_SetCPULoad(gSource[theSound], gCPUCurrentLoad);
  259.  
  260.         //•    Make sure that the listener is listening at this sound
  261.         SetListenerLocation(320 - x, 240 - y);
  262.  
  263.         //•    Position the sound in space.
  264.         location.cameraLocation.x = 320 - x;
  265.         location.cameraLocation.y = 240 - y;
  266.         location.cameraLocation.z = 0;
  267.         
  268.         //•    Orient the sound so that it is down directed down towards the listener
  269.         location.pointOfInterest.x = 0;
  270.         location.pointOfInterest.y = -1;
  271.         location.pointOfInterest.z = -1;
  272.     
  273.         location.upVector.x = 0;
  274.         location.upVector.y = 1;
  275.         location.upVector.z = 0;
  276.     
  277.         theErr = SSpSource_SetCameraPlacement (gSource[theSound], &location);
  278.         if (theErr)
  279.             FatalError ("Failed to set the source location");
  280.             
  281.         theErr = SSpSource_CalcLocalization (gSource[theSound], gListener, &localization);
  282.         if (theErr)
  283.             FatalError ("Failed to calculate the localization");
  284.         
  285.         // We don't do doppler, since we only localize the sound at the instant it is played.
  286.         localization.currentLocation.sourceVelocity = 0;
  287.         localization.currentLocation.listenerVelocity = 0;
  288.         
  289.         // We set the reference distance to a reasonable number that seems to get good results
  290.         // We also provide a minimum distance or else we run into really LOUD, really CLIPPED sounds
  291.         localization.referenceDistance = 20.0;
  292.         if (localization.currentLocation.distance < 5.0)
  293.             localization.currentLocation.distance = 5.0;
  294.  
  295.         theErr = SndSetInfo (gChannels[theSound], siSSpLocalization, &localization);
  296.         if (theErr)
  297.             FatalError("Failed to localize the channel");
  298.     }
  299.  
  300.     //•    Play the selected sound immediately
  301.     theErr = SndPlay(gChannels[theSound], (SndListHandle) gSounds[theSound], true);
  302.     if (theErr)
  303.         FatalError("Failed to start sound in SndPlay().");
  304. }
  305.  
  306. //•    --------------------    SetListenerLocation
  307.  
  308. static void
  309. SetListenerLocation(const SInt32 inPOI_X, const SInt32 inPOI_Y)
  310. {
  311. OSStatus            theErr = noErr;
  312. TQ3CameraPlacement    location;
  313.  
  314.     if (! gSoundSprocket)
  315.         return;
  316.  
  317.     //•    Set the listener in the bottom middle of the screen
  318.     location.cameraLocation.x = 320;
  319.     location.cameraLocation.y = 240;
  320.     location.cameraLocation.z = -10;
  321.  
  322.     //•    Focus the listener's attention on the exact middle of the screen
  323.     location.pointOfInterest.x = inPOI_X;
  324.     location.pointOfInterest.y = inPOI_Y;
  325.     location.pointOfInterest.z = 0;
  326.     
  327.     location.upVector.x = 0;
  328.     location.upVector.y = 1;
  329.     location.upVector.z = 0;
  330.     
  331.     theErr = SSpListener_SetCameraPlacement (gListener, &location);
  332.     if (theErr)
  333.         FatalError ("Failed to set the listener location");
  334. }
  335.