Subversion Repositories Kolibri OS

Rev

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