Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Source/SoundHandler.c
/* |
File: SoundHandler.c |
Contains: xxx put contents here xxx |
Version: xxx put version here xxx |
Copyright: © 1998-1999 by Apple Computer, Inc., all rights reserved. |
File Ownership: |
DRI: Chris De Salvo |
Other Contact: xxx put other contact here xxx |
Technology: Apple Game Sprockets |
Writers: |
(cjd) Chris De Salvo |
(cjd) Chris DeSalvo |
Change History (most recent first): |
<SP12> 7/1/99 cjd The camera and the point of interest were set to the same point. |
Bad. So we now push in the Z of the POI and pull back the Z of |
the camera. |
<SP11> 6/30/99 cjd The camera and the point of interest were set to the same point. |
Bad. So we now push in the Z of the POI and pull back the Z of |
the camera. |
<SP10> 1/21/99 cjd Removing 68K conditional |
<9> 7/1/98 cjd Added SSp CPU load throttling |
*/ |
//¥ ------------------------------------------------------------------------------------------ ¥ |
//¥ |
//¥ Copyright © 1996 Apple Computer, Inc., All Rights Reserved |
//¥ |
//¥ |
//¥ You may incorporate this sample code into your applications without |
//¥ restriction, though the sample code has been provided "AS IS" and the |
//¥ responsibility for its operation is 100% yours. However, what you are |
//¥ not permitted to do is to redistribute the source as "DSC Sample Code" |
//¥ after having made changes. If you're going to re-distribute the source, |
//¥ we require that you make it clear in the source that the code was |
//¥ descended from Apple Sample Code, but that you've made changes. |
//¥ |
//¥ Authors: |
//¥ Chris De Salvo |
//¥ Tim Carroll |
//¥ |
//¥ ------------------------------------------------------------------------------------------ ¥ |
//¥ ------------------------------ Includes |
#include <Resources.h> |
#include <Sound.h> |
#include <SoundSprocket.h> |
#include <SoundComponents.h> |
#include <CodeFragments.h> |
#include "ErrorHandler.h" |
#include "EventHandler.h" |
#include "MemoryHandler.h" |
#include "SIResources.h" |
#include "SoundHandler.h" |
//¥ ------------------------------ Private Definitions |
//¥ ------------------------------ Private Types |
//¥ ------------------------------ Private Variables |
static Boolean gSoundHandlerInit = false; |
static SndChannelPtr gChannels[soundNumSounds]; |
static Handle gSounds[soundNumSounds]; |
static SSpSourceReference gSource[soundNumSounds]; |
static SSpListenerReference gListener; |
static Boolean gSoundSprocket = false; |
//¥ ------------------------------ Private Functions |
static void SetListenerLocation(const SInt32 inPOI_X, const SInt32 inPOI_Y); |
//¥ ------------------------------ Public Variables |
Boolean gSoundEffects = true; |
UInt32 gCPULoadModifier = 0; |
UInt32 gCPULoadMax = 0; |
UInt32 gCPUCurrentLoad = 0; |
//¥ -------------------- SoundHandlerInit |
void |
SoundHandlerInit(void) |
{ |
UInt32 i; |
gSoundSprocket = false; |
//¥ Allocate the sound channels for playback |
for (i = 0; i < soundNumSounds; i++) |
{ |
OSErr theErr; |
theErr = SndNewChannel(&gChannels[i], sampledSynth, initMono, nil); |
if (theErr) |
FatalError("Could not allocate enough sound channels."); |
} |
//¥ Load the actual sound effects |
for (i = 0; i < soundNumSounds; i++) |
{ |
gSounds[i] = GetResource('snd ', kSND_PlayerFire + i); |
if (! gSounds[i]) |
FatalError("Could not load a required sound effect."); |
DetachResource(gSounds[i]); |
} |
gSoundHandlerInit = true; |
//¥ If SoundSprocket is present then create a listener and set things up |
if ((Ptr) SSpConfigureSpeakerSetup == (Ptr) kUnresolvedCFragSymbolAddress) |
{ |
return; // no sound sprocket |
} |
else |
{ |
OSStatus theErr = noErr; |
theErr = SSpGetCPULoadLimit(&gCPULoadMax); |
if (noErr != theErr) |
{ |
//¥ If we couldn't figure out the number of steps then we'll |
//¥ just set the CPU load to zero every time. This forces maximum quality. |
gCPULoadModifier = 0; |
} |
else |
{ |
gCPULoadModifier = 0xFFFFFFFF / (gCPULoadMax + 1); |
} |
//¥ We have sound sprocket, so now we install the filters and create source and listener objects. |
//¥ Create the listener |
theErr = SSpListener_New(&gListener); |
if (theErr) |
FatalError("Could not create a sound sprocket listener."); |
//¥ Define our unit of distance measurement |
theErr = SSpListener_SetMetersPerUnit(gListener, 0.05); |
if (theErr) |
FatalError ("Could not set reference distance for listener."); |
//¥ Attach the sound localization component to each of the sound |
//¥ channels that we'll be playing through. |
for (i = 0; i < soundNumSounds; i++) |
{ |
SoundComponentLink myLink; |
//¥ Create the source |
theErr = SSpSource_New(&gSource[i]); |
if (theErr) |
FatalError("Could not create a sound sprocket source."); |
//¥ Install the filter |
myLink.description.componentType = kSoundEffectsType; |
myLink.description.componentSubType = kSSpLocalizationSubType; |
myLink.description.componentManufacturer = 0; |
myLink.description.componentFlags = 0; |
myLink.description.componentFlagsMask = 0; |
myLink.mixerID = nil; |
myLink.linkID = nil; |
theErr = SndSetInfo(gChannels[i], siPreMixerSoundComponent, &myLink); |
if (theErr) |
FatalError("Could not install the sound sprocket filter into the channel."); |
} |
gSoundSprocket = true; |
SetListenerLocation(320, 240); |
} |
} |
//¥ -------------------- SoundHandlerReset |
void |
SoundHandlerReset(void) |
{ |
UInt32 i; |
if (! gSoundHandlerInit) |
return; |
//¥ Deallocate the sound channels |
for (i = 0; i < soundNumSounds; i++) |
{ |
if (gChannels[i]) |
{ |
SndDisposeChannel(gChannels[i], true); |
gChannels[i] = nil; |
} |
} |
//¥ Unload the actual sound effects |
for (i = 0; i < soundNumSounds; i++) |
{ |
if (gSounds[i]) |
DisposeHandleZ(&gSounds[i]); |
} |
} |
//¥ -------------------- SoundHandlerPlay |
void |
SoundHandlerPlay(GameSounds theSound, short x, short y) |
{ |
SndCommand theCommand; |
OSStatus theErr = noErr; |
//¥ Make sure that sound effects are turned on |
if (! gSoundEffects) |
return; |
//¥ Make sure we are initialized |
if (! gSoundHandlerInit) |
return; |
//¥ Make sure the requested sound is within the range of valid effects |
if (theSound < 0 || theSound >= soundNumSounds) |
return; |
//¥ Stop playback of any sound currently playing on this channel |
theCommand.cmd = quietCmd; |
SndDoImmediate(gChannels[theSound], &theCommand); |
//¥ Flush out any queued sounds waiting to play on this channel |
theCommand.cmd = flushCmd; |
SndDoImmediate(gChannels[theSound], &theCommand); |
//¥ If we're using SoundSprocket then set up the location parameters |
//¥ for the localization filter |
if (gSoundSprocket) |
{ |
TQ3CameraPlacement location; |
SSpLocalizationData localization; |
//¥ We want all the sounds to be localized, but when we explode we want to hear it |
//¥ all around us. |
if (soundPlayerHit != theSound) |
SSpSource_SetMode(gSource[theSound], kSSpSourceMode_Localized); |
else |
SSpSource_SetMode(gSource[theSound], kSSpSourceMode_Ambient); |
//¥ Allow the user to dynamically set the CPU usage range for SSp |
SSpSource_SetCPULoad(gSource[theSound], gCPUCurrentLoad); |
//¥ Make sure that the listener is listening at this sound |
SetListenerLocation(320 - x, 240 - y); |
//¥ Position the sound in space. |
location.cameraLocation.x = 320 - x; |
location.cameraLocation.y = 240 - y; |
location.cameraLocation.z = 0; |
//¥ Orient the sound so that it is down directed down towards the listener |
location.pointOfInterest.x = 0; |
location.pointOfInterest.y = -1; |
location.pointOfInterest.z = -1; |
location.upVector.x = 0; |
location.upVector.y = 1; |
location.upVector.z = 0; |
theErr = SSpSource_SetCameraPlacement (gSource[theSound], &location); |
if (theErr) |
FatalError ("Failed to set the source location"); |
theErr = SSpSource_CalcLocalization (gSource[theSound], gListener, &localization); |
if (theErr) |
FatalError ("Failed to calculate the localization"); |
// We don't do doppler, since we only localize the sound at the instant it is played. |
localization.currentLocation.sourceVelocity = 0; |
localization.currentLocation.listenerVelocity = 0; |
// We set the reference distance to a reasonable number that seems to get good results |
// We also provide a minimum distance or else we run into really LOUD, really CLIPPED sounds |
localization.referenceDistance = 20.0; |
if (localization.currentLocation.distance < 5.0) |
localization.currentLocation.distance = 5.0; |
theErr = SndSetInfo (gChannels[theSound], siSSpLocalization, &localization); |
if (theErr) |
FatalError("Failed to localize the channel"); |
} |
//¥ Play the selected sound immediately |
theErr = SndPlay(gChannels[theSound], (SndListHandle) gSounds[theSound], true); |
if (theErr) |
FatalError("Failed to start sound in SndPlay()."); |
} |
//¥ -------------------- SetListenerLocation |
static void |
SetListenerLocation(const SInt32 inPOI_X, const SInt32 inPOI_Y) |
{ |
OSStatus theErr = noErr; |
TQ3CameraPlacement location; |
if (! gSoundSprocket) |
return; |
//¥ Set the listener in the bottom middle of the screen |
location.cameraLocation.x = 320; |
location.cameraLocation.y = 240; |
location.cameraLocation.z = -10; |
//¥ Focus the listener's attention on the exact middle of the screen |
location.pointOfInterest.x = inPOI_X; |
location.pointOfInterest.y = inPOI_Y; |
location.pointOfInterest.z = 0; |
location.upVector.x = 0; |
location.upVector.y = 1; |
location.upVector.z = 0; |
theErr = SSpListener_SetCameraPlacement (gListener, &location); |
if (theErr) |
FatalError ("Failed to set the listener location"); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-10-14