Subversion Repositories Kolibri OS

Rev

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