home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / Samples / SprocketExamples / SprocketInvaders / Source / SoundHandler.c < prev    next >
Encoding:
Text File  |  1998-07-14  |  8.9 KB  |  342 lines  |  [TEXT/CWIE]

  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 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     File Ownership:
  11.  
  12.         DRI:                xxx put dri here xxx
  13.  
  14.         Other Contact:        xxx put other contact here xxx
  15.  
  16.         Technology:            xxx put technology here xxx
  17.  
  18.     Writers:
  19.  
  20.         (cjd)    Chris DeSalvo
  21.  
  22.     Change History (most recent first):
  23.  
  24.          <9>      7/1/98    cjd        Added SSp CPU load throttling
  25. */
  26.  
  27. //•    ------------------------------------------------------------------------------------------    •
  28. //•
  29. //•    Copyright © 1996 Apple Computer, Inc., All Rights Reserved
  30. //•
  31. //•
  32. //•        You may incorporate this sample code into your applications without
  33. //•        restriction, though the sample code has been provided "AS IS" and the
  34. //•        responsibility for its operation is 100% yours.  However, what you are
  35. //•        not permitted to do is to redistribute the source as "DSC Sample Code"
  36. //•        after having made changes. If you're going to re-distribute the source,
  37. //•        we require that you make it clear in the source that the code was
  38. //•        descended from Apple Sample Code, but that you've made changes.
  39. //•
  40. //•        Authors:
  41. //•            Chris De Salvo
  42. //•            Tim Carroll
  43. //•
  44. //•    ------------------------------------------------------------------------------------------    •
  45.  
  46. //•    ------------------------------    Includes
  47.  
  48. #include <Resources.h>
  49. #include <Sound.h>
  50. #if GENERATINGPOWERPC
  51. #include <SoundSprocket.h>
  52. #endif
  53. #include <SoundComponents.h>
  54. #include <CodeFragments.h>
  55.  
  56. #include "ErrorHandler.h"
  57. #include "EventHandler.h"
  58. #include "MemoryHandler.h"
  59. #include "SIResources.h"
  60. #include "SoundHandler.h"
  61.  
  62. //•    ------------------------------    Private Definitions
  63. //•    ------------------------------    Private Types
  64. //•    ------------------------------    Private Variables
  65.  
  66. static Boolean gSoundHandlerInit = false;
  67. static SndChannelPtr gChannels[soundNumSounds];
  68. static Handle gSounds[soundNumSounds];
  69. #if GENERATINGPOWERPC
  70. static SSpSourceReference gSource[soundNumSounds];
  71. static SSpListenerReference gListener;
  72. #endif
  73. static Boolean gSoundSprocket = false;
  74.  
  75. //•    ------------------------------    Private Functions
  76.  
  77. #if GENERATINGPOWERPC
  78. static void SetListenerLocation(void);
  79. #endif
  80.  
  81. //•    ------------------------------    Public Variables
  82.  
  83. Boolean gSoundEffects = true;
  84.  
  85. #if GENERATINGPOWERPC
  86. UInt32    gCPULoadModifier = 0;
  87. UInt32    gCPULoadMax = 0;
  88. UInt32    gCPUCurrentLoad = 0;
  89. #endif
  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 GENERATINGPOWERPC
  123.     //•    If SoundSprocket is present then create a listener and set things up
  124.     if ((Ptr) SSpConfigureSpeakerSetup == (Ptr) kUnresolvedCFragSymbolAddress)
  125.     {
  126.         return;  // no sound sprocket
  127.     }
  128.     else    
  129.     {
  130.     OSStatus    theErr = noErr;
  131.     
  132.         theErr = SSpGetCPULoadLimit(&gCPULoadMax);
  133.  
  134.         if (noErr != theErr)
  135.         {
  136.             //•    If we couldn't figure out the number of steps then we'll
  137.             //•    just set the CPU load to zero every time.  This forces maximum quality.
  138.             gCPULoadModifier = 0;
  139.         }
  140.         else
  141.         {
  142.             gCPULoadModifier = 0xFFFFFFFF / (gCPULoadMax + 1);
  143.         }
  144.         
  145.         //•    We have sound sprocket, so now we install the filters and create source and listener objects.
  146.     
  147.         //•    Create the listener
  148.         theErr = SSpListener_New(&gListener);
  149.         if (theErr)
  150.             FatalError("Could not create a sound sprocket listener.");
  151.     
  152.         //•    Define our unit of distance measurement
  153.         theErr = SSpListener_SetMetersPerUnit(gListener, 0.05);
  154.         if (theErr)
  155.             FatalError ("Could not set reference distance for listener.");
  156.     
  157.         //•    Attach the sound localization component to each of the sound
  158.         //•    channels that we'll be playing through.
  159.         for (i = 0; i < soundNumSounds; i++)
  160.         {
  161.         SoundComponentLink    myLink;
  162.             
  163.             //•    Create the source
  164.             theErr = SSpSource_New(&gSource[i]);
  165.             if (theErr)
  166.                 FatalError("Could not create a sound sprocket source.");
  167.             
  168.             //•    Install the filter
  169.             myLink.description.componentType = kSoundEffectsType;
  170.             myLink.description.componentSubType = kSSpLocalizationSubType;
  171.             myLink.description.componentManufacturer = 0;
  172.             myLink.description.componentFlags = 0; 
  173.             myLink.description.componentFlagsMask = 0;
  174.             myLink.mixerID = nil; 
  175.             myLink.linkID = nil;
  176.             
  177.             theErr = SndSetInfo(gChannels[i], siPreMixerSoundComponent, &myLink);
  178.              if (theErr) 
  179.                  FatalError("Could not install the sound sprocket filter into the channel.");
  180.         }
  181.         
  182.         gSoundSprocket = true;
  183.         SetListenerLocation();
  184.     }
  185. #endif
  186. }
  187.  
  188. //•    --------------------    SoundHandlerReset
  189.  
  190. void
  191. SoundHandlerReset(void)
  192. {
  193. UInt32    i;
  194.  
  195.     if (! gSoundHandlerInit)
  196.         return;
  197.  
  198.     //•    Deallocate the sound channels
  199.     for (i = 0; i < soundNumSounds; i++)
  200.     {
  201.         if (gChannels[i])
  202.         {
  203.             SndDisposeChannel(gChannels[i], true);
  204.             gChannels[i] = nil;
  205.         }
  206.     }
  207.  
  208.     //•    Unload the actual sound effects
  209.     for (i = 0; i < soundNumSounds; i++)
  210.     {
  211.         if (gSounds[i])
  212.             DisposeHandleZ(&gSounds[i]);
  213.     }
  214.  
  215. }
  216.  
  217. //•    --------------------    SoundHandlerPlay
  218.  
  219. void
  220. SoundHandlerPlay(GameSounds theSound, short x, short y)
  221. {
  222. SndCommand    theCommand;
  223. OSStatus    theErr = noErr;
  224.  
  225.     //•    Make sure that sound effects are turned on
  226.     if (! gSoundEffects)
  227.         return;
  228.  
  229.     //•    Make sure we are initialized
  230.     if (! gSoundHandlerInit)
  231.         return;
  232.  
  233.     //•    Make sure the requested sound is within the range of valid effects
  234.     if (theSound < 0 || theSound >= soundNumSounds)
  235.         return;
  236.  
  237.     //•    Stop playback of any sound currently playing on this channel
  238.     theCommand.cmd = quietCmd;
  239.     SndDoImmediate(gChannels[theSound], &theCommand);
  240.  
  241.     //•    Flush out any queued sounds waiting to play on this channel
  242.     theCommand.cmd = flushCmd;
  243.     SndDoImmediate(gChannels[theSound], &theCommand);
  244.  
  245. #if GENERATINGPOWERPC
  246.     //• If we're using SoundSprocket then set up the location parameters
  247.     //•    for the localization filter
  248.     if (gSoundSprocket)
  249.     {
  250.     TQ3CameraPlacement    location;
  251.     SSpLocalizationData    localization;
  252.     
  253.         //•    We want all the sounds to be localized, but when we explode we want to hear it
  254.         //•    all around us.
  255.         if (soundPlayerHit != theSound)
  256.             SSpSource_SetMode(gSource[theSound], kSSpSourceMode_Localized);
  257.         else
  258.             SSpSource_SetMode(gSource[theSound], kSSpSourceMode_Ambient);
  259.  
  260.         //•    Allow the user to dynamically set the CPU usage range for SSp
  261.         SSpSource_SetCPULoad(gSource[theSound], gCPUCurrentLoad);
  262.  
  263.         //•    Position the sound in space.
  264.         location.cameraLocation.x = 640 - x;
  265.         location.cameraLocation.y = 480 - 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. #else
  300.     // ref x and y to avoid warnings
  301.     (void *)&x;
  302.     (void *)&y;
  303. #endif
  304.  
  305.     //•    Play the selected sound immediately
  306.     theErr = SndPlay(gChannels[theSound], (SndListHandle) gSounds[theSound], true);
  307.     if (theErr)
  308.         FatalError("Failed to start sound in SndPlay().");
  309. }
  310.  
  311. //•    --------------------    SetListenerLocation
  312.  
  313. #if GENERATINGPOWERPC
  314. static void
  315. SetListenerLocation(void)
  316. {
  317. OSStatus            theErr = noErr;
  318. TQ3CameraPlacement    location;
  319.  
  320.     if (! gSoundSprocket)
  321.         return;
  322.  
  323.     //•    Set the listener in the bottom middle of the screen
  324.     location.cameraLocation.x = 320;
  325.     location.cameraLocation.y = 240;
  326.     location.cameraLocation.z = 0;
  327.  
  328.     //•    Focus the listener's attention on the exact middle of the screen
  329.     location.pointOfInterest.x = 320;
  330.     location.pointOfInterest.y = 240;
  331.     location.pointOfInterest.z = 0;
  332.     
  333.     location.upVector.x = 0;
  334.     location.upVector.y = 1;
  335.     location.upVector.z = 0;
  336.     
  337.     theErr = SSpListener_SetCameraPlacement (gListener, &location);
  338.     if (theErr)
  339.         FatalError ("Failed to set the listener location");
  340. }
  341. #endif
  342.