audio.c

Go to the documentation of this file.
00001 
00025 #ifdef USE_AUDIO
00026 #include "text.h"
00027 #include <assert.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <math.h>
00031 #include <SDL_mixer.h>
00032 #include "audio.h"
00033 
00034 #ifdef _MSC_VER
00035 // For some reason it seems Microsoft's math.h in Visual Studio 2003 only has
00036 // prototypes for the fabsf and sqrtf functions for C++. Or maybe I did
00037 // something wrong. I can't imagine this wouldn't be a major problem. The
00038 // following macros are a workaround. The problem doesn't exist in Visual
00039 // Studio 2005.
00040 #ifndef fabsf
00041 #define fabsf(x)  (float)fabs(x)
00042 #endif
00043 #ifndef sqrtf
00044 #define sqrtf(x)  (float)sqrt(x)
00045 #endif
00046 #endif
00047 
00048 #ifndef SAMPLE_RATE
00049 
00052 #define SAMPLE_RATE  48000
00053 #endif
00054 
00059 static Bool enabled = FALSE;
00060 
00065 static Mix_Chunk *sounds[SND_MAX] = { 0 };
00066 
00070 static const char * const soundFiles[SND_MAX] = {
00071     "idle.wav",
00072     "move.wav",
00073     "shoot.wav",
00074     "death.wav",
00075 };
00076 
00085 Bool static LoadSound(const char *fname, int index) {
00086     // assure that not too many sounds load
00087     assert(index < SND_MAX);
00088     // attempt to load the sound
00089     if ((sounds[index] = Mix_LoadWAV(fname)) == NULL) {
00090         // failure
00091         return FALSE;
00092     }
00093     return TRUE;
00094 }
00095 
00096 Bool PlaySound(int snd, int chan, int count) {
00097     Mix_Chunk *sound = sounds[snd];
00098     // the sound must be valid
00099     assert(snd < SND_MAX);
00100     // assure this happens on a valid channel
00101     assert((chan >= 0) && (chan < SND_CH_MAX));
00102     // quit now if auido output is not enabled
00103     if (!enabled) return FALSE;
00104     // stop the channel from playing whatever it was doing last
00105     //Mix_HaltChannel(chan);
00106     // assure no effects, like that distance one
00107     Mix_UnregisterAllEffects(chan);
00108     // check for a bad sound (probably didn't load), and if it's good, play
00109     // the sound and check for error
00110     if ((sounds[snd] == NULL) || (((count >= 0) || !Mix_Playing(chan) ||
00111     (Mix_GetChunk(chan) != sound)) &&
00112     ((chan = Mix_PlayChannel(chan, sound, count)) == -1))) {
00113         return FALSE;
00114     }
00115     // success
00116     return TRUE;
00117 }
00118 
00119 Bool PlaySoundDist(int snd, int chan, int distsq, int count) {
00120     Mix_Chunk *sound = sounds[snd];
00121     // distance must be between 0 & MAX_SQ_DIST, inclusive
00122     assert((distsq >= 0) && (distsq <= MAX_SQ_DIST));
00123     // sound and channel must be valid
00124     assert((snd < SND_MAX) && (chan < SND_CH_MAX));
00125     // for infinitely looping sounds, a predetermined channel must be used
00126     assert(((count == -1) && (chan != -1)) || (count != -1));
00127     // quit now if auido output is not enabled
00128     if (!enabled) return FALSE;
00129     // is this a sound that was already playing?
00130     if ((chan != -1) && (count == -1) && Mix_Paused(chan)) {
00131         // resume playback
00132         Mix_Resume(chan);
00133     }
00134     // check for a bad sound (probably didn't load), and if it's good, play
00135     // the sound and check for error
00136     else if ((sounds[snd] == NULL) || (((chan == -1) || !Mix_Playing(chan) ||
00137     (Mix_GetChunk(chan) != sound)) &&
00138     ((chan = Mix_PlayChannel(chan, sound, count)) == -1))) {
00139         return FALSE;
00140     }
00141     // set distance
00142     if (distsq > 0) {
00143         // compute the distance value
00144         distsq = (int)(sqrtf((float)distsq) * (160.0f / 212.0f));
00145         // set it
00146         Mix_SetDistance(chan, distsq);
00147     }
00148     else {
00149         // clear distance
00150         Mix_UnregisterAllEffects(chan);
00151     }
00152     // all good!
00153     return TRUE;
00154 }
00155 
00156 Bool PlayLocalDeath() {
00157     // quit now if auido output is not enabled
00158     if (!enabled) return FALSE;
00159     // stop all other sounds
00160     Mix_HaltChannel(-1);
00161     // if the death sound was loaded, play it now
00162     if ((sounds[SND_DEATH] == NULL) ||
00163     (Mix_PlayChannel(SND_CH_TANK, sounds[SND_DEATH], 0) == -1)) {
00164         return FALSE;
00165     }
00166     return TRUE;
00167 }
00168 
00169 void PauseSound(int chan) {
00170     // assure a valid channel
00171     assert((chan >= 0) && (chan < SND_CH_RESERVE));
00172     // quit now if auido output is not enabled
00173     if (!enabled) return;
00174     // pause it
00175     Mix_Pause(chan);
00176 }
00177 
00178 void StopAllSounds() {
00179     // quit now if auido output is not enabled
00180     if (!enabled) return;
00181     // stop all channels
00182     Mix_HaltChannel(-1);
00183 }
00184 
00185 Bool InitAudio() {
00186     int loop, errs;
00187     // attempt to initalize audio
00188     if (Mix_OpenAudio(SAMPLE_RATE, AUDIO_S16SYS, 1, 1024) != 0) {
00189         // failed to open an audio output device
00190         prnfile(stderr, strings[STRING_ERR_OPENAUDIO], Mix_GetError());
00191         // failed
00192         return FALSE;
00193     }
00194     // get the mixing channels
00195     Mix_AllocateChannels(SND_CH_MAX);
00196     // reserver some
00197     Mix_ReserveChannels(SND_CH_RESERVE);
00198     // becuase this setup always uses the same sounds, load them all
00199     for (errs = 0, loop = 0; loop < SND_MAX; loop++) {
00200         // load and check for error
00201         if (!LoadSound(soundFiles[loop], loop)) {
00202             // faild to load
00203             prnfile(stderr, strings[STRING_ERR_LOADSND], soundFiles[loop]);
00204             errs++;
00205         }
00206     }
00207     // sounds are enabled, even if there is nothing to play
00208     enabled = TRUE;
00209     // did no sounds load?
00210     if (errs == SND_MAX) {
00211         // no sounds!
00212         prnfile(stderr, strings[STRING_ERR_NOSNDS]);
00213         // nothing to play, so signal a failure
00214         return FALSE;
00215     }
00216     // success
00217     return TRUE;
00218 }
00219 
00220 void UninitAudio() {
00221     int loop;
00222     // quit now if auido output is not enabled
00223     if (!enabled) return;
00224     // stop playing all sounds
00225     Mix_HaltChannel(-1);
00226     // free all sounds
00227     for (loop = 0; loop < SND_MAX; loop++) {
00228         // allocated sound?
00229         if (sounds[loop]) {
00230             // deallocate it
00231             Mix_FreeChunk(sounds[loop]);
00232             // mark it as gone
00233             sounds[loop] = NULL;
00234         }
00235     }
00236     // put down SDL_mixer
00237     Mix_CloseAudio();
00238     // audio system is no longer enabled
00239     enabled = FALSE;
00240 }
00241 
00242 #endif

Generated on Mon May 28 04:41:38 2007 for Retro Tank Super Attack by  doxygen 1.5.2