- /* 
-  * src/syssnd.c 
-  * 
-  * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 
-  * 
-  * The use and distribution terms for this software are contained in the file 
-  * named README, which can be found in the root of this distribution. By 
-  * using this software in any fashion, you are agreeing to be bound by the 
-  * terms of this license. 
-  * 
-  * You must not remove this notice, or any other, from this software. 
-  */ 
-   
- #include <SDL.h> 
- #include <stdlib.h> 
- #include <memory.h> 
-   
- #include "system.h" 
- #include "game.h" 
- #include "syssnd.h" 
-   
-   
- #define ADJVOL(S) (((S) *sndVol) / SDL_MIX_MAXVOLUME) 
-   
-   
- static U8 isAudioActive = FALSE; 
- static channel_t channels[SYSSND_MIXCHANNELS]; 
-   
- static U8 sndVol = SDL_MIX_MAXVOLUME;   /* internal volume */ 
- static U8 sndUVol = SYSSND_MAXVOL;   /* user-selected volume */ 
- static U8 sndMute = FALSE;   /* mute flag */ 
-   
-   
- /* 
-  * prototypes 
-  */ 
- static void end_channel (channel_t *); 
-   
-   
- /* 
-  * Callback -- this is also where all sound mixing is done 
-  * 
-  * Note: it may not be that much a good idea to do all the mixing here ; it 
-  * may be more efficient to mix samples every frame, or maybe everytime a 
-  * new sound is sent to be played. I don't know. 
-  */ 
- void syssnd_callback (void *userdata, U8 *stream, int len) 
- { 
-    channel_t *channel; 
-    U8 channel_index; 
-    S16 final_sample; 
-    U32 i; 
-   
-    //  
-    for (i = 0; i < (U32)len; i += 2) 
-    { 
-       final_sample = 0; 
-   
-       for (channel_index = 0; channel_index < SYSSND_MIXCHANNELS; channel_index++) 
-       { 
-          channel = &channels[channel_index]; // quick access to channel 
-   
-          if (channel->loop == 0) 
-             continue; 
-   
-          // channel is active 
-          if (channel->len > 0) 
-          { 
-             // not ending 
-             final_sample += ADJVOL (*((U16 *) channel->buf)); 
-             channel->buf += 2; 
-             channel->len -= 2; 
-          } 
-          else 
-          { 
-             // ending 
-             if (channel->loop > 0) 
-                channel->loop--; 
-   
-             if (channel->loop) 
-             { 
-                // just loop 
-                channel->buf = channel->snd->buf; 
-                channel->len = channel->snd->len; 
-   
-                final_sample += ADJVOL (*((U16 *) channel->buf)); 
-                channel->buf += 2; 
-                channel->len -= 2; 
-             } 
-             else 
-                end_channel (channel); // end for real 
-          } 
-       } 
-   
-       *((S16 *) &stream[i]) = (sndMute ? 0 : final_sample); 
-    } 
- } 
-   
-   
- static void end_channel (channel_t *channel) 
- { 
-    channel->loop = 0; 
-    if (channel->snd->dispose) 
-       syssnd_free (channel->snd); 
-    channel->snd = NULL; 
- } 
-   
-   
- void syssnd_init (void) 
- { 
-    SDL_AudioSpec desired; 
-    U16 c; 
-   
-    if (SDL_InitSubSystem (SDL_INIT_AUDIO) < 0) 
-       return; 
-   
-    desired.freq = SYSSND_FREQ; 
-    desired.format = AUDIO_S16; 
-    desired.channels = SYSSND_CHANNELS; 
-    desired.samples = SYSSND_MIXSAMPLES; 
-    desired.callback = syssnd_callback; 
-    desired.userdata = NULL; 
-   
-    if (SDL_OpenAudio (&desired, NULL) < 0) 
-       return; 
-   
-    if (sysarg_args_vol != 0) 
-    { 
-       sndUVol = sysarg_args_vol; 
-       sndVol = SDL_MIX_MAXVOLUME * sndUVol / SYSSND_MAXVOL; 
-    } 
-   
-    for (c = 0; c < SYSSND_MIXCHANNELS; c++) 
-       channels[c].loop = 0;   /* deactivate */ 
-   
-    isAudioActive = TRUE; 
-    SDL_PauseAudio (0); 
- } 
-   
-   
- /* 
-  * Shutdown 
-  */ 
- void syssnd_shutdown (void) 
- { 
-    if (!isAudioActive) 
-       return; 
-   
-    SDL_CloseAudio (); 
-    isAudioActive = FALSE; 
- } 
-   
-   
- /* 
-  * Toggle mute 
-  * 
-  * When muted, sounds are still managed but not sent to the dsp, hence 
-  * it is possible to un-mute at any time. 
-  */ 
- void syssnd_toggleMute (void) 
- { 
-    sndMute = !sndMute; 
- } 
-   
-   
- void syssnd_vol (S8 d) 
- { 
-    if ((d < 0 && sndUVol > 0) || (d > 0 && sndUVol < SYSSND_MAXVOL)) 
-    { 
-       sndUVol += d; 
-       sndVol = SDL_MIX_MAXVOLUME * sndUVol / SYSSND_MAXVOL; 
-    } 
- } 
-   
-   
- /* 
-  * Play a sound 
-  * 
-  * loop: number of times the sound should be played, -1 to loop forever 
-  * returns: channel number, or -1 if none was available 
-  * 
-  * NOTE if sound is already playing, simply reset it (i.e. can not have 
-  * twice the same sound playing -- tends to become noisy when too many 
-  * bad guys die at the same time). 
-  */ 
- S8 syssnd_play (sound_t *sound, S8 loop) 
- { 
-    S8 channel_index; 
-   
-    if ((sound == NULL) || !isAudioActive) 
-       return (-1); 
-   
-    for (channel_index = 0; channel_index < SYSSND_MIXCHANNELS; channel_index++) 
-       if ((channels[channel_index].snd == sound) || (channels[channel_index].loop == 0)) 
-          break; // look for a free channel slot 
-    if (channel_index == SYSSND_MIXCHANNELS) 
-       return (-1); 
-   
-    channels[channel_index].loop = loop; 
-    channels[channel_index].snd = sound; 
-    channels[channel_index].buf = sound->buf; 
-    channels[channel_index].len = sound->len; 
-   
-    return (channel_index); 
- } 
-   
-   
- /* 
-  * Pause 
-  * 
-  * pause: TRUE or FALSE 
-  * clear: TRUE to cleanup all sounds and make sure we start from scratch 
-  */ 
- void syssnd_pause (U8 want_pause, U8 want_clear) 
- { 
-    U8 channel_index; 
-   
-    if (!isAudioActive) 
-       return; 
-   
-    if (want_clear) 
-       for (channel_index = 0; channel_index < SYSSND_MIXCHANNELS; channel_index++) 
-          channels[channel_index].loop = 0; 
-   
-    SDL_PauseAudio (want_pause ? 1 : 0); 
- } 
-   
-   
- /* 
-  * Stop a channel 
-  */ 
- void syssnd_stopchan (S8 chan) 
- { 
-    if (chan < 0 || chan > SYSSND_MIXCHANNELS) 
-       return; 
-   
-    if (channels[chan].snd) 
-       end_channel (&channels[chan]); 
- } 
-   
-   
- /* 
-  * Stop a sound 
-  */ 
- void syssnd_stopsound (sound_t *sound) 
- { 
-    U8 i; 
-   
-    if (!sound) 
-       return; 
-   
-    for (i = 0; i < SYSSND_MIXCHANNELS; i++) 
-       if (channels[i].snd == sound) 
-          end_channel (&channels[i]); 
- } 
-   
-   
- /* 
-  * See if a sound is playing 
-  */ 
- int syssnd_isplaying (sound_t *sound) 
- { 
-    U8 i; 
-   
-    for (i = 0; i < SYSSND_MIXCHANNELS; i++) 
-       if (channels[i].snd == sound) 
-          return (1); 
-   
-    return (0); 
- } 
-   
-   
- /* 
-  * Stops all channels. 
-  */ 
- void syssnd_stopall (void) 
- { 
-    U8 i; 
-   
-    for (i = 0; i < SYSSND_MIXCHANNELS; i++) 
-       if (channels[i].snd) 
-          end_channel (&channels[i]); 
- } 
-   
-   
- /* 
-  * Load a sound. 
-  */ 
- sound_t *syssnd_load (char *name) 
- { 
-    char *soundfile_fullpathname; 
-    sound_t *s; 
-    SDL_AudioSpec audiospec; 
-   
-    /* alloc space for sound file's full pathname and build it */ 
-    soundfile_fullpathname  = (char *) malloc (1024);
-    sprintf_s (soundfile_fullpathname, 1024, "%s/%s", sys_getbasepath (), name); 
-   
-    /* alloc sound */ 
-    s  = malloc (sizeof (- sound_t ));
-   
-    /* read */ 
-    /* second param == 1 -> close source once read */ 
-    if (!SDL_LoadWAV_RW (SDL_RWFromFile (soundfile_fullpathname, "rb"), 1, &audiospec, &(s->buf), &(s->len))) 
-    { 
-       return NULL; 
-    } 
-    free (- soundfile_fullpathname );
 
-   
-    s->dispose = FALSE; 
-   
-    return s; 
- } 
-   
-   
- /* 
-  * 
-  */ 
- void syssnd_free (sound_t *s) 
- { 
-    if (!s) 
-       return; 
-   
-    if (s->buf) 
-       SDL_FreeWAV (s->buf); 
-   
-    s->buf = NULL; 
-    s->len = 0; 
- } 
-