Subversion Repositories Kolibri OS

Rev

Rev 342 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. // Emacs style mode select   -*- C++ -*-
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:  none
  20. //
  21. //-----------------------------------------------------------------------------
  22.  
  23.  
  24. static const char
  25. rcsid[] = "$Id: s_sound.c,v 1.6 1997/02/03 22:45:12 b1 Exp $";
  26.  
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30.  
  31. #include "i_system.h"
  32. #include "i_sound.h"
  33. #include "sounds.h"
  34. #include "s_sound.h"
  35.  
  36. #include "z_zone.h"
  37. #include "m_random.h"
  38. #include "w_wad.h"
  39.  
  40. #include "doomdef.h"
  41. #include "p_local.h"
  42. //#include "m_music.h"
  43.  
  44. #include "doomstat.h"
  45.  
  46. //#include "qmus2mid.h"
  47.  
  48.  
  49. #include "kolibri.h"
  50. #include "sound.h"
  51.  
  52. void WriteDebug(char *);
  53.  
  54. // Purpose?
  55. const char snd_prefixen[]
  56. = { 'P', 'P', 'A', 'S', 'S', 'S', 'M', 'M', 'M', 'S', 'S', 'S' };
  57.  
  58. #define S_MAX_VOLUME            127
  59.  
  60. // when to clip out sounds
  61. // Does not fit the large outdoor areas.
  62. #define S_CLIPPING_DIST         (1200*0x10000)
  63.  
  64. // Distance tp origin when sounds should be maxed out.
  65. // This should relate to movement clipping resolution
  66. // (see BLOCKMAP handling).
  67. // Originally: (200*0x10000).
  68. #define S_CLOSE_DIST            (160*0x10000)
  69.  
  70.  
  71. #define S_ATTENUATOR            ((S_CLIPPING_DIST-S_CLOSE_DIST)>>FRACBITS)
  72.  
  73. // Adjustable by menu.
  74. #define NORM_VOLUME             snd_MaxVolume
  75.  
  76. #define NORM_PITCH              128
  77. #define NORM_PRIORITY           64
  78. #define NORM_SEP                128
  79.  
  80. #define S_PITCH_PERTURB         1
  81. #define S_STEREO_SWING          (96*0x10000)
  82.  
  83. // percent attenuation from front to back
  84. #define S_IFRACVOL              30
  85.  
  86. #define NA                      0
  87. //#define S_NUMCHANNELS         2
  88. #define NUM_CHANNELS    16
  89.  
  90. // Current music/sfx card - index useless
  91. //  w/o a reference LUT in a sound module.
  92. extern int snd_MusicDevice;
  93. extern int snd_SfxDevice;
  94. // Config file? Same disclaimer as above.
  95. extern int snd_DesiredMusicDevice;
  96. extern int snd_DesiredSfxDevice;
  97.  
  98.  
  99. typedef struct
  100. {
  101.     // sound information (if null, channel avail.)
  102.     sfxinfo_t*  sfxinfo;
  103.  
  104.     // origin of sound
  105.     void*       origin;
  106.  
  107.     // handle of the sound being played
  108.     int         handle;
  109.    
  110. } channel_t;
  111.  
  112.  
  113. // the set of channels available
  114. static channel_t*       channels;
  115.  
  116. // These are not used, but should be (menu).
  117. // Maximum volume of a sound effect.
  118. // Internal default is max out of 0-15.
  119. int             snd_SfxVolume = 15;
  120.  
  121. // Maximum volume of music. Useless so far.
  122. int             snd_MusicVolume = 15;
  123.  
  124.  
  125.  
  126. // whether songs are mus_paused
  127. static boolean          mus_paused;    
  128.  
  129. // music currently being played
  130. static musicinfo_t*     mus_playing=0;
  131.  
  132. // following is set
  133. //  by the defaults code in M_misc:
  134. // number of channels available
  135. int                     numChannels;    
  136.  
  137. static int              nextcleanup;
  138.  
  139.  
  140.  
  141. //
  142. // Internals.
  143. //
  144. int
  145. S_getChannel
  146. ( void*         origin,
  147.   sfxinfo_t*    sfxinfo,
  148.   int       sfxid );
  149.  
  150.  
  151. int
  152. S_AdjustSoundParams
  153. ( mobj_t*       listener,
  154.   mobj_t*       source,
  155.   int*          vol,
  156.   int*          sep,
  157.   int*          pitch );
  158.  
  159. void S_StopChannel(int cnum);
  160.  
  161.  
  162.  
  163. //
  164. // Initializes sound stuff, including volume
  165. // Sets channels, SFX and music volume,
  166. //  allocates channel buffer, sets S_sfx lookup.
  167. //
  168.  
  169.  
  170. SNDBUF hMixBuff;
  171. volatile int sound_state;
  172. void sound_proc(void);
  173. void I_UpdateSound( void );
  174.  
  175. void S_Init
  176. ( int           sfxVolume,
  177.   int           musicVolume )
  178. {  
  179.   int           i;
  180.   char *thread_stack;
  181.   int ver;
  182.  
  183.   numChannels = NUM_CHANNELS;
  184.  
  185.   // Whatever these did with DMX, these are rather dummies now.
  186.   I_SetChannels();
  187.  
  188.   S_SetSfxVolume(sfxVolume);
  189.   // No music with Linux - another dummy.
  190.   S_SetMusicVolume(musicVolume);
  191.  
  192.   // Allocating the internal channels for mixing
  193.   // (the maximum numer of sounds rendered
  194.   // simultaneously) within zone memory.
  195.   channels =
  196.     (channel_t *) Z_Malloc(numChannels*sizeof(channel_t), PU_STATIC, 0);
  197.  
  198.   // Free all channels for use
  199.   for (i=0 ; i<numChannels ; i++)
  200.     channels[i].sfxinfo = 0;
  201.  
  202.   // no sounds are playing, and they are not mus_paused
  203.   mus_paused = 0;
  204.  
  205.   // Note that sounds have not been cached (yet).
  206.   for (i=1 ; i<NUMSFX ; i++)
  207.     S_sfx[i].lumpnum = S_sfx[i].usefulness = -1;
  208.  
  209.  
  210. /********
  211.   if((ver = InitSound())< SOUND_VERSION )
  212.   {  
  213.      printf("Sound service version mismatch\n\r");
  214.      printf("Installed version: %d, required version %d\n\r",
  215.              ver, SOUND_VERSION);
  216.   };
  217.  
  218.   hMixBuff = CreateBuffer(PCM_2_16_11,0);
  219.  
  220. *********/
  221.  
  222.    thread_stack = UserAlloc(4096);
  223.    thread_stack+=4092;
  224.  
  225.    sound_state=1;  
  226.    CreateThread(sound_proc, thread_stack);
  227. }
  228.  
  229. typedef struct
  230. {
  231.   unsigned int  code;
  232.   unsigned int  sender;
  233.   unsigned int  stream;
  234.   unsigned int  offset;
  235.   unsigned int  size;
  236.   unsigned int  unused;
  237. }SND_EVENT;    
  238.  
  239. unsigned int mix_offset;
  240. int mix_size;
  241. extern signed short *mixbuffer;
  242.  
  243. void sound_proc(void)
  244. {
  245.   int ver;
  246.   SND_EVENT evnt;
  247.   int i;
  248.    
  249.   if((ver = InitSound())< SOUND_VERSION )
  250.   {  
  251.      printf("Sound service version mismatch\n\r");
  252.      printf("Installed version: %d, required version %d\n\r",
  253.              ver, SOUND_VERSION);
  254.   };
  255.  
  256.   hMixBuff=CreateBuffer(PCM_2_16_11|PCM_RING,0);
  257.  
  258.   if(!hMixBuff)
  259.   {
  260.     printf("sound not available\n\r");
  261.     _asm
  262.     {
  263.       mov eax, -1
  264.       int 0x40
  265.     };      
  266.   };
  267.  
  268.   mix_size=GetBufferSize(hMixBuff)/2;
  269.   printf("mixer size %d\n\r", mix_size);
  270.  
  271.   mixbuffer = malloc(mix_size);
  272.  
  273.   PlayBuffer(hMixBuff, 0);
  274.   while(sound_state)
  275.   {
  276.      GetNotify(&evnt);
  277.  
  278.      if(evnt.code != 0xFF000001)
  279.      {
  280.        printf("invalid code %d\n\r", evnt.code);
  281.        continue;
  282.      }    
  283.      
  284.      if(evnt.stream != hMixBuff)
  285.      {
  286.        printf("invalid stream %d hMixBuff= %d\n\r", evnt.stream, hMixBuff);
  287.        continue;
  288.      };
  289.      mix_offset= evnt.offset;
  290.      I_UpdateSound();
  291.   };
  292.  
  293.   //flush sound buffers
  294.  
  295.   for(i=0; i<32; i++)
  296.   {
  297.      GetNotify(&evnt);
  298.  
  299.      if(evnt.code != 0xFF000001)
  300.      {
  301.        printf("invalid code %d\n\r", evnt.code);
  302.        continue;
  303.      }    
  304.      
  305.      if(evnt.stream != hMixBuff)
  306.      {
  307.        printf("invalid stream %d hMixBuff= %d\n\r", evnt.stream, hMixBuff);
  308.        continue;
  309.      };
  310.      mix_offset= evnt.offset;
  311.      I_UpdateSound();
  312.   };  
  313.  
  314.   _asm
  315.   {
  316.     mov eax, -1
  317.     int 0x40
  318.   };      
  319.  
  320. };
  321.  
  322. //
  323. // Per level startup code.
  324. // Kills playing sounds at start of level,
  325. //  determines music if any, changes music.
  326. //
  327. void S_Start(void)
  328. {
  329.   int cnum;
  330.   int mnum;
  331.  
  332.   // kill all playing sounds at start of level
  333.   //  (trust me - a good idea)
  334.   for (cnum=0 ; cnum<numChannels ; cnum++)
  335.     if (channels[cnum].sfxinfo)
  336.       S_StopChannel(cnum);
  337.  
  338.   // start new music for the level
  339.   mus_paused = 0;
  340.  
  341.   if (gamemode == commercial)
  342.           mnum = mus_runnin + gamemap - 1;
  343.   else
  344.   {
  345.           int spmus[]=
  346.           {
  347.                   // Song - Who? - Where?
  348.                 mus_e3m4,       // American     e4m1
  349.                 mus_e3m2,       // Romero       e4m2
  350.                 mus_e3m3,       // Shawn        e4m3
  351.                 mus_e1m5,       // American     e4m4
  352.                 mus_e2m7,       // Tim  e4m5
  353.                 mus_e2m4,       // Romero       e4m6
  354.                 mus_e2m6,       // J.Anderson   e4m7 CHIRON.WAD
  355.                 mus_e2m5,       // Shawn        e4m8
  356.                 mus_e1m9        // Tim          e4m9
  357.           };
  358.          
  359.           if (gameepisode < 4)
  360.                   mnum = mus_e1m1 + (gameepisode-1)*9 + gamemap-1;
  361.           else
  362.                   mnum = spmus[gamemap-1];
  363.   }    
  364.  
  365.   // HACK FOR COMMERCIAL
  366.   //  if (commercial && mnum > mus_e3m9)        
  367.   //      mnum -= mus_e3m9;
  368.  
  369.   S_ChangeMusic(mnum, true);
  370.  
  371.   nextcleanup = 15;
  372. }      
  373.  
  374. void S_StartSoundAtVolume( void *origin_p, int sfx_id, int volume )
  375.    {
  376.     int        rc;
  377.     int        sep;
  378.     int        pitch;
  379.     int        priority;
  380.     sfxinfo_t *sfx;
  381.     int        cnum;
  382.     // int        chnum;  <-- 10.9.98 compiler warning
  383.  
  384.     mobj_t*     origin = (mobj_t *)origin_p;
  385.  
  386.     //WriteDebug("S_StartSoundAtVolume...\n");
  387.  
  388.     // Debug.
  389.     /*fprintf( stderr,"S_StartSoundAtVolume: playing sound %d (%s)\n",sfx_id, S_sfx[sfx_id].name );*/
  390.  
  391.     // check for bogus sound #
  392.     if (sfx_id < 1 || sfx_id > NUMSFX)
  393.         I_Error("Bad sfx #: %d", sfx_id);
  394.  
  395.     sfx = &S_sfx[sfx_id];
  396.  
  397.     // Initialize sound parameters
  398.     if (sfx->link)
  399.        {
  400.         pitch = sfx->pitch;
  401.         priority = sfx->priority;
  402.         volume += sfx->volume;
  403.    
  404.         if (volume < 1)
  405.            {
  406.             //WriteDebug("Volume off...\n");
  407.             return;
  408.            }
  409.    
  410.         if (volume > snd_SfxVolume)
  411.             volume = snd_SfxVolume;
  412.        }        
  413.     else
  414.        {
  415.         pitch = NORM_PITCH;
  416.         priority = NORM_PRIORITY;
  417.        }
  418.  
  419.  
  420.     // Check to see if it is audible,
  421.     //  and if not, modify the params
  422.     if (origin && origin != players[consoleplayer].mo)
  423.        {
  424.         rc = S_AdjustSoundParams(players[consoleplayer].mo, origin, &volume, &sep, &pitch);
  425.         if ( origin->x == players[consoleplayer].mo->x && origin->y == players[consoleplayer].mo->y)
  426.            {    
  427.             sep = NORM_SEP;
  428.            }
  429.         if (!rc)
  430.            {
  431.             //WriteDebug("No rc from S_AdjustSoundParams...\n");
  432.             return;
  433.            }
  434.        }        
  435.     else
  436.        {
  437.         sep = NORM_SEP;
  438.        }
  439.  
  440.     // hacks to vary the sfx pitches
  441.     if (sfx_id >= sfx_sawup && sfx_id <= sfx_sawhit)
  442.        {        
  443.         pitch += 8 - (M_Random()&15);
  444.         if (pitch < 0)
  445.             pitch = 0;
  446.         else
  447.         if (pitch>255)
  448.             pitch = 255;
  449.        }
  450.     else
  451.     if (sfx_id != sfx_itemup && sfx_id != sfx_tink)
  452.        {
  453.         pitch += 16 - (M_Random()&31);
  454.         if (pitch<0)
  455.             pitch = 0;
  456.         else
  457.         if (pitch > 255)
  458.             pitch = 255;
  459.        }
  460.  
  461.   // kill old sound
  462.   S_StopSound(origin);
  463.  
  464.   // try to find a channel
  465.   cnum = S_getChannel(origin, sfx, sfx_id);
  466.  
  467.   if (cnum<0)
  468.      {
  469.         //WriteDebug("cnum < 0 -- no channel...\n");
  470.     return;
  471.      }
  472.  
  473.   //
  474.   // This is supposed to handle the loading/caching.
  475.   // For some odd reason, the caching is done nearly
  476.   //  each time the sound is needed?
  477.   //
  478.  
  479.   // get lumpnum if necessary
  480.   if (sfx->lumpnum < 0)
  481.     sfx->lumpnum = I_GetSfxLumpNum(sfx);
  482.  
  483.   // cache data if necessary
  484.   if (!sfx->data)
  485.   {
  486.     sfx->data = (void *) W_CacheLumpNum(sfx->lumpnum, PU_MUSIC);
  487.    
  488.   }
  489.  
  490.   // increase the usefulness
  491.   if (sfx->usefulness++ < 0)
  492.       sfx->usefulness = 1;
  493.  
  494.   // Assigns the handle to one of the channels in the
  495.   //  mix/output buffer.
  496.   //WriteDebug("I_StartSound...\n");
  497.   channels[cnum].handle = I_StartSound(sfx_id,volume,sep,pitch,priority);
  498.   channels[cnum].handle = cnum;
  499.   channels[cnum].sfxinfo = sfx;
  500.   channels[cnum].origin = origin;
  501. }      
  502.  
  503. void S_StartSound( void *origin, int sfx_id )
  504.    {
  505. #ifdef SAWDEBUG
  506.     // if (sfx_id == sfx_sawful)
  507.     // sfx_id = sfx_itemup;
  508. #endif
  509.  
  510.     S_StartSoundAtVolume(origin, sfx_id, snd_SfxVolume);
  511.  
  512.  
  513.     // UNUSED. We had problems, had we not?
  514. #ifdef SAWDEBUG
  515. {
  516.     int i;
  517.     int n;
  518.        
  519.     static mobj_t*      last_saw_origins[10] = {1,1,1,1,1,1,1,1,1,1};
  520.     static int          first_saw=0;
  521.     static int          next_saw=0;
  522.        
  523.     if (sfx_id == sfx_sawidl
  524.         || sfx_id == sfx_sawful
  525.         || sfx_id == sfx_sawhit)
  526.     {
  527.         for (i=first_saw;i!=next_saw;i=(i+1)%10)
  528.             if (last_saw_origins[i] != origin)
  529.                 fprintf(stderr, "old origin 0x%lx != "
  530.                         "origin 0x%lx for sfx %d\n",
  531.                         last_saw_origins[i],
  532.                         origin,
  533.                         sfx_id);
  534.            
  535.         last_saw_origins[next_saw] = origin;
  536.         next_saw = (next_saw + 1) % 10;
  537.         if (next_saw == first_saw)
  538.             first_saw = (first_saw + 1) % 10;
  539.            
  540.         for (n=i=0; i<numChannels ; i++)
  541.         {
  542.             if (channels[i].sfxinfo == &S_sfx[sfx_sawidl]
  543.                 || channels[i].sfxinfo == &S_sfx[sfx_sawful]
  544.                 || channels[i].sfxinfo == &S_sfx[sfx_sawhit]) n++;
  545.         }
  546.            
  547.         if (n>1)
  548.         {
  549.             for (i=0; i<numChannels ; i++)
  550.             {
  551.                 if (channels[i].sfxinfo == &S_sfx[sfx_sawidl]
  552.                     || channels[i].sfxinfo == &S_sfx[sfx_sawful]
  553.                     || channels[i].sfxinfo == &S_sfx[sfx_sawhit])
  554.                 {
  555.                     fprintf(stderr,
  556.                             "chn: sfxinfo=0x%lx, origin=0x%lx, "
  557.                             "handle=%d\n",
  558.                             channels[i].sfxinfo,
  559.                             channels[i].origin,
  560.                             channels[i].handle);
  561.                 }
  562.             }
  563.             fprintf(stderr, "\n");
  564.         }
  565.     }
  566. }
  567. #endif
  568.  
  569. }
  570.  
  571.  
  572.  
  573.  
  574. void S_StopSound(void *origin)
  575. {
  576.  
  577.     int cnum;
  578.  
  579.     for (cnum=0 ; cnum<numChannels ; cnum++)
  580.     {
  581.         if (channels[cnum].sfxinfo && channels[cnum].origin == origin)
  582.         {
  583.             S_StopChannel(cnum);
  584.             break;
  585.         }
  586.     }
  587. }
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597. //
  598. // Stop and resume music, during game PAUSE.
  599. //
  600. void S_PauseSound(void)
  601. {
  602.     if (mus_playing && !mus_paused)
  603.     {
  604.         I_PauseSong(mus_playing->handle);
  605.         mus_paused = true;
  606.     }
  607. }
  608.  
  609. void S_ResumeSound(void)
  610. {
  611.     if (mus_playing && mus_paused)
  612.     {
  613.         I_ResumeSong(mus_playing->handle);
  614.         mus_paused = false;
  615.     }
  616. }
  617.  
  618.  
  619. //
  620. // Updates music & sounds
  621. //
  622. void S_UpdateSounds(void* listener_p)
  623. {
  624.     int         audible;
  625.     int         cnum;
  626.     int         volume;
  627.     int         sep;
  628.     int         pitch;
  629.     sfxinfo_t*  sfx;
  630.     channel_t*  c;
  631.    
  632.     mobj_t*     listener = (mobj_t*)listener_p;
  633.  
  634.  
  635.    
  636.     // Clean up unused data.
  637.     // This is currently not done for 16bit (sounds cached static).
  638.     // DOS 8bit remains.
  639.     /*if (gametic > nextcleanup)
  640.     {
  641.         for (i=1 ; i<NUMSFX ; i++)
  642.         {
  643.             if (S_sfx[i].usefulness < 1
  644.                 && S_sfx[i].usefulness > -1)
  645.             {
  646.                 if (--S_sfx[i].usefulness == -1)
  647.                 {
  648.                     Z_ChangeTag(S_sfx[i].data, PU_CACHE);
  649.                     S_sfx[i].data = 0;
  650.                 }
  651.             }
  652.         }
  653.         nextcleanup = gametic + 15;
  654.     }*/
  655.    
  656.     for (cnum=0 ; cnum<numChannels ; cnum++)
  657.     {
  658.         c = &channels[cnum];
  659.         sfx = c->sfxinfo;
  660.  
  661.         if (c->sfxinfo)
  662.         {
  663.             if (I_SoundIsPlaying(c->handle))
  664.             {
  665.                 // initialize parameters
  666.                 volume = snd_SfxVolume;
  667.                 pitch = NORM_PITCH;
  668.                 sep = NORM_SEP;
  669.  
  670.                 if (sfx->link)
  671.                 {
  672.                     pitch = sfx->pitch;
  673.                     volume += sfx->volume;
  674.                     if (volume < 1)
  675.                     {
  676.                         S_StopChannel(cnum);
  677.                         continue;
  678.                     }
  679.                     else if (volume > snd_SfxVolume)
  680.                     {
  681.                         volume = snd_SfxVolume;
  682.                     }
  683.                 }
  684.  
  685.                 // check non-local sounds for distance clipping
  686.                 //  or modify their params
  687.                 if (c->origin && listener_p != c->origin)
  688.                 {
  689.                     audible = S_AdjustSoundParams(listener,
  690.                                                   c->origin,
  691.                                                   &volume,
  692.                                                   &sep,
  693.                                                   &pitch);
  694.                    
  695.                     if (!audible)
  696.                     {
  697.                         S_StopChannel(cnum);
  698.                     }
  699.                     else
  700.                         I_UpdateSoundParams(c->handle, volume, sep, pitch);
  701.                 }
  702.             }
  703.             else
  704.             {
  705.                 // if channel is allocated but sound has stopped,
  706.                 //  free it
  707.                 S_StopChannel(cnum);
  708.             }
  709.         }
  710.     }
  711.     // kill music if it is a single-play && finished
  712.     // if (     mus_playing
  713.     //      && !I_QrySongPlaying(mus_playing->handle)
  714.     //      && !mus_paused )
  715.     // S_StopMusic();
  716. }
  717.  
  718.  
  719. void S_SetMusicVolume(int volume)
  720. {
  721.     if (volume < 0 || volume > 127)
  722.     {
  723.         I_Error("Attempt to set music volume at %d",
  724.                 volume);
  725.     }    
  726.  
  727.     I_SetMusicVolume(127);
  728.     I_SetMusicVolume(volume);
  729.     snd_MusicVolume = volume;
  730. }
  731.  
  732.  
  733.  
  734. void S_SetSfxVolume(int volume)
  735. {
  736.  
  737.     if (volume < 0 || volume > 127)
  738.         I_Error("Attempt to set sfx volume at %d", volume);
  739.  
  740.     snd_SfxVolume = volume;
  741.  
  742. }
  743.  
  744. //
  745. // Starts some music with the music id found in sounds.h.
  746. //
  747. void S_StartMusic(int m_id)
  748. {
  749. //    S_ChangeMusic(m_id, false);
  750. }
  751.  
  752.  
  753. // clean-up&code for orig midi 10.9.98-dlw
  754. void S_ChangeMusic(int musicnum, int looping)
  755. {
  756.  
  757.     // I_PlaySong(music->handle, looping);
  758. //      mus_playing = music;
  759. }
  760.  
  761.  
  762. void S_StopMusic(void)
  763. {
  764.     if (mus_playing)
  765.     {
  766.                 if (mus_paused) I_ResumeSong(mus_playing->handle);
  767.                 I_StopSong(mus_playing->handle);
  768.                 I_UnRegisterSong(mus_playing->handle);
  769.                 Z_ChangeTag(mus_playing->data, PU_CACHE);
  770.                 mus_playing->data = 0;
  771.                 mus_playing = 0;
  772.     }
  773. }
  774.  
  775. void S_StopChannel(int cnum)
  776. {
  777.  
  778.     int         i;
  779.     channel_t*  c = &channels[cnum];
  780.  
  781.     if (c->sfxinfo)
  782.     {
  783.         // stop the sound playing
  784.         if (I_SoundIsPlaying(c->handle))
  785.         {
  786. #ifdef SAWDEBUG
  787.             if (c->sfxinfo == &S_sfx[sfx_sawful])
  788.                 fprintf(stderr, "stopped\n");
  789. #endif
  790.             I_StopSound(c->handle);
  791.         }
  792.  
  793.         // check to see
  794.         //  if other channels are playing the sound
  795.         for (i=0 ; i<numChannels ; i++)
  796.         {
  797.             if (cnum != i
  798.                 && c->sfxinfo == channels[i].sfxinfo)
  799.             {
  800.                 break;
  801.             }
  802.         }
  803.        
  804.         // degrade usefulness of sound data
  805.         c->sfxinfo->usefulness--;
  806.  
  807.         c->sfxinfo = 0;
  808.     }
  809. }
  810.  
  811.  
  812. //
  813. // Changes volume, stereo-separation, and pitch variables
  814. //  from the norm of a sound effect to be played.
  815. // If the sound is not audible, returns a 0.
  816. // Otherwise, modifies parameters and returns 1.
  817. //
  818. int
  819. S_AdjustSoundParams (mobj_t* listener, mobj_t* source,
  820.                      int* vol, int* sep, int* pitch)
  821. {
  822.     fixed_t     approx_dist;
  823.     fixed_t     adx;
  824.     fixed_t     ady;
  825.     angle_t     angle;
  826.  
  827.     // calculate the distance to sound origin
  828.     //  and clip it if necessary
  829.     adx = abs(listener->x - source->x);
  830.     ady = abs(listener->y - source->y);
  831.  
  832.     // From _GG1_ p.428. Appox. eucledian distance fast.
  833.     approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1);
  834.    
  835.     if (gamemap != 8
  836.         && approx_dist > S_CLIPPING_DIST)
  837.     {
  838.         return 0;
  839.     }
  840.    
  841.     // angle of source to listener
  842.     angle = R_PointToAngle2(listener->x,
  843.                             listener->y,
  844.                             source->x,
  845.                             source->y);
  846.  
  847.     if (angle > listener->angle)
  848.         angle = angle - listener->angle;
  849.     else
  850.         angle = angle + (0xffffffff - listener->angle);
  851.  
  852.     angle >>= ANGLETOFINESHIFT;
  853.  
  854.     // stereo separation
  855.     *sep = 128 - (FixedMul(S_STEREO_SWING,finesine[angle])>>FRACBITS);
  856.  
  857.     // volume calculation
  858.     if (approx_dist < S_CLOSE_DIST)
  859.     {
  860.         *vol = snd_SfxVolume;
  861.     }
  862.     else if (gamemap == 8)
  863.     {
  864.         if (approx_dist > S_CLIPPING_DIST)
  865.             approx_dist = S_CLIPPING_DIST;
  866.  
  867.         *vol = 15+ ((snd_SfxVolume-15)
  868.                     *((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
  869.             / S_ATTENUATOR;
  870.     }
  871.     else
  872.     {
  873.         // distance effect
  874.         *vol = (snd_SfxVolume
  875.                 * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
  876.             / S_ATTENUATOR;
  877.     }
  878.    
  879.     return (*vol > 0);
  880. }
  881.  
  882. //
  883. // S_getChannel :
  884. //   If none available, return -1.  Otherwise channel #.
  885. //
  886. int S_getChannel( void *origin, sfxinfo_t *sfxinfo, int sfxid )
  887.    {
  888.     // channel number to use
  889.     int         cnum;
  890.        
  891.     channel_t*  c;
  892.  
  893.     // Find an open channel
  894.     //for (cnum = 0; cnum < numChannels; cnum++)
  895.     for (cnum = 0; cnum < NUM_CHANNELS; cnum++)
  896.        {
  897.         if (!channels[cnum].sfxinfo)
  898.             break;
  899.         else
  900.         if (origin && channels[cnum].origin == origin)
  901.            {
  902.             S_StopChannel(cnum);
  903.             break;
  904.            }
  905.        }
  906.  
  907.     // None available
  908.     if (cnum == NUM_CHANNELS)
  909.        {
  910.         // Look for lower priority
  911.         for (cnum = NUMSFX; cnum < NUM_CHANNELS; cnum++)
  912.              if (channels[cnum].sfxinfo->priority >= sfxinfo->priority)
  913.                  break;
  914.  
  915.         if (cnum == numChannels)
  916.            {
  917.             // FUCK!  No lower priority.  Sorry, Charlie.    
  918.             return -1;
  919.            }
  920.         else
  921.            {
  922.             // Otherwise, kick out lower priority.
  923.             S_StopChannel(cnum);
  924.            }
  925.        }
  926.  
  927.     c = &channels[cnum];
  928.  
  929.     // channel is decided to be cnum.
  930.     c->sfxinfo = sfxinfo;
  931.     c->origin = origin;
  932.  
  933.     return cnum;
  934.    }
  935.  
  936.  
  937.  
  938.  
  939.