Subversion Repositories Kolibri OS

Rev

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