Subversion Repositories Kolibri OS

Rev

Rev 298 | 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,volume,sep,pitch,priority);
  376.   channels[cnum].handle = cnum;
  377.   channels[cnum].sfxinfo = sfx;
  378.   channels[cnum].origin = origin;
  379. }      
  380.  
  381. void S_StartSound( void *origin, int sfx_id )
  382.    {
  383. #ifdef SAWDEBUG
  384.     // if (sfx_id == sfx_sawful)
  385.     // sfx_id = sfx_itemup;
  386. #endif
  387.  
  388.     S_StartSoundAtVolume(origin, sfx_id, snd_SfxVolume);
  389.  
  390.  
  391.     // UNUSED. We had problems, had we not?
  392. #ifdef SAWDEBUG
  393. {
  394.     int i;
  395.     int n;
  396.        
  397.     static mobj_t*      last_saw_origins[10] = {1,1,1,1,1,1,1,1,1,1};
  398.     static int          first_saw=0;
  399.     static int          next_saw=0;
  400.        
  401.     if (sfx_id == sfx_sawidl
  402.         || sfx_id == sfx_sawful
  403.         || sfx_id == sfx_sawhit)
  404.     {
  405.         for (i=first_saw;i!=next_saw;i=(i+1)%10)
  406.             if (last_saw_origins[i] != origin)
  407.                 fprintf(stderr, "old origin 0x%lx != "
  408.                         "origin 0x%lx for sfx %d\n",
  409.                         last_saw_origins[i],
  410.                         origin,
  411.                         sfx_id);
  412.            
  413.         last_saw_origins[next_saw] = origin;
  414.         next_saw = (next_saw + 1) % 10;
  415.         if (next_saw == first_saw)
  416.             first_saw = (first_saw + 1) % 10;
  417.            
  418.         for (n=i=0; i<numChannels ; i++)
  419.         {
  420.             if (channels[i].sfxinfo == &S_sfx[sfx_sawidl]
  421.                 || channels[i].sfxinfo == &S_sfx[sfx_sawful]
  422.                 || channels[i].sfxinfo == &S_sfx[sfx_sawhit]) n++;
  423.         }
  424.            
  425.         if (n>1)
  426.         {
  427.             for (i=0; i<numChannels ; i++)
  428.             {
  429.                 if (channels[i].sfxinfo == &S_sfx[sfx_sawidl]
  430.                     || channels[i].sfxinfo == &S_sfx[sfx_sawful]
  431.                     || channels[i].sfxinfo == &S_sfx[sfx_sawhit])
  432.                 {
  433.                     fprintf(stderr,
  434.                             "chn: sfxinfo=0x%lx, origin=0x%lx, "
  435.                             "handle=%d\n",
  436.                             channels[i].sfxinfo,
  437.                             channels[i].origin,
  438.                             channels[i].handle);
  439.                 }
  440.             }
  441.             fprintf(stderr, "\n");
  442.         }
  443.     }
  444. }
  445. #endif
  446.  
  447. }
  448.  
  449.  
  450.  
  451.  
  452. void S_StopSound(void *origin)
  453. {
  454.  
  455.     int cnum;
  456.  
  457.     for (cnum=0 ; cnum<numChannels ; cnum++)
  458.     {
  459.         if (channels[cnum].sfxinfo && channels[cnum].origin == origin)
  460.         {
  461.             S_StopChannel(cnum);
  462.             break;
  463.         }
  464.     }
  465. }
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474.  
  475. //
  476. // Stop and resume music, during game PAUSE.
  477. //
  478. void S_PauseSound(void)
  479. {
  480.     if (mus_playing && !mus_paused)
  481.     {
  482.         I_PauseSong(mus_playing->handle);
  483.         mus_paused = true;
  484.     }
  485. }
  486.  
  487. void S_ResumeSound(void)
  488. {
  489.     if (mus_playing && mus_paused)
  490.     {
  491.         I_ResumeSong(mus_playing->handle);
  492.         mus_paused = false;
  493.     }
  494. }
  495.  
  496.  
  497. //
  498. // Updates music & sounds
  499. //
  500. void S_UpdateSounds(void* listener_p)
  501. {
  502.     int         audible;
  503.     int         cnum;
  504.     int         volume;
  505.     int         sep;
  506.     int         pitch;
  507.     sfxinfo_t*  sfx;
  508.     channel_t*  c;
  509.    
  510.     mobj_t*     listener = (mobj_t*)listener_p;
  511.  
  512.  
  513.    
  514.     // Clean up unused data.
  515.     // This is currently not done for 16bit (sounds cached static).
  516.     // DOS 8bit remains.
  517.     /*if (gametic > nextcleanup)
  518.     {
  519.         for (i=1 ; i<NUMSFX ; i++)
  520.         {
  521.             if (S_sfx[i].usefulness < 1
  522.                 && S_sfx[i].usefulness > -1)
  523.             {
  524.                 if (--S_sfx[i].usefulness == -1)
  525.                 {
  526.                     Z_ChangeTag(S_sfx[i].data, PU_CACHE);
  527.                     S_sfx[i].data = 0;
  528.                 }
  529.             }
  530.         }
  531.         nextcleanup = gametic + 15;
  532.     }*/
  533.    
  534.     for (cnum=0 ; cnum<numChannels ; cnum++)
  535.     {
  536.         c = &channels[cnum];
  537.         sfx = c->sfxinfo;
  538.  
  539.         if (c->sfxinfo)
  540.         {
  541.             if (I_SoundIsPlaying(c->handle))
  542.             {
  543.                 // initialize parameters
  544.                 volume = snd_SfxVolume;
  545.                 pitch = NORM_PITCH;
  546.                 sep = NORM_SEP;
  547.  
  548.                 if (sfx->link)
  549.                 {
  550.                     pitch = sfx->pitch;
  551.                     volume += sfx->volume;
  552.                     if (volume < 1)
  553.                     {
  554.                         S_StopChannel(cnum);
  555.                         continue;
  556.                     }
  557.                     else if (volume > snd_SfxVolume)
  558.                     {
  559.                         volume = snd_SfxVolume;
  560.                     }
  561.                 }
  562.  
  563.                 // check non-local sounds for distance clipping
  564.                 //  or modify their params
  565.                 if (c->origin && listener_p != c->origin)
  566.                 {
  567.                     audible = S_AdjustSoundParams(listener,
  568.                                                   c->origin,
  569.                                                   &volume,
  570.                                                   &sep,
  571.                                                   &pitch);
  572.                    
  573.                     if (!audible)
  574.                     {
  575.                         S_StopChannel(cnum);
  576.                     }
  577.                     else
  578.                         I_UpdateSoundParams(c->handle, volume, sep, pitch);
  579.                 }
  580.             }
  581.             else
  582.             {
  583.                 // if channel is allocated but sound has stopped,
  584.                 //  free it
  585.                 S_StopChannel(cnum);
  586.             }
  587.         }
  588.     }
  589.     // kill music if it is a single-play && finished
  590.     // if (     mus_playing
  591.     //      && !I_QrySongPlaying(mus_playing->handle)
  592.     //      && !mus_paused )
  593.     // S_StopMusic();
  594. }
  595.  
  596.  
  597. void S_SetMusicVolume(int volume)
  598. {
  599.     if (volume < 0 || volume > 127)
  600.     {
  601.         I_Error("Attempt to set music volume at %d",
  602.                 volume);
  603.     }    
  604.  
  605.     I_SetMusicVolume(127);
  606.     I_SetMusicVolume(volume);
  607.     snd_MusicVolume = volume;
  608. }
  609.  
  610.  
  611.  
  612. void S_SetSfxVolume(int volume)
  613. {
  614.  
  615.     if (volume < 0 || volume > 127)
  616.         I_Error("Attempt to set sfx volume at %d", volume);
  617.  
  618.     snd_SfxVolume = volume;
  619.  
  620. }
  621.  
  622. //
  623. // Starts some music with the music id found in sounds.h.
  624. //
  625. void S_StartMusic(int m_id)
  626. {
  627. //    S_ChangeMusic(m_id, false);
  628. }
  629.  
  630.  
  631. // clean-up&code for orig midi 10.9.98-dlw
  632. void S_ChangeMusic(int musicnum, int looping)
  633. {
  634.  
  635.     // I_PlaySong(music->handle, looping);
  636. //      mus_playing = music;
  637. }
  638.  
  639.  
  640. void S_StopMusic(void)
  641. {
  642.     if (mus_playing)
  643.     {
  644.                 if (mus_paused) I_ResumeSong(mus_playing->handle);
  645.                 I_StopSong(mus_playing->handle);
  646.                 I_UnRegisterSong(mus_playing->handle);
  647.                 Z_ChangeTag(mus_playing->data, PU_CACHE);
  648.                 mus_playing->data = 0;
  649.                 mus_playing = 0;
  650.     }
  651. }
  652.  
  653. void S_StopChannel(int cnum)
  654. {
  655.  
  656.     int         i;
  657.     channel_t*  c = &channels[cnum];
  658.  
  659.     if (c->sfxinfo)
  660.     {
  661.         // stop the sound playing
  662.         if (I_SoundIsPlaying(c->handle))
  663.         {
  664. #ifdef SAWDEBUG
  665.             if (c->sfxinfo == &S_sfx[sfx_sawful])
  666.                 fprintf(stderr, "stopped\n");
  667. #endif
  668.             I_StopSound(c->handle);
  669.         }
  670.  
  671.         // check to see
  672.         //  if other channels are playing the sound
  673.         for (i=0 ; i<numChannels ; i++)
  674.         {
  675.             if (cnum != i
  676.                 && c->sfxinfo == channels[i].sfxinfo)
  677.             {
  678.                 break;
  679.             }
  680.         }
  681.        
  682.         // degrade usefulness of sound data
  683.         c->sfxinfo->usefulness--;
  684.  
  685.         c->sfxinfo = 0;
  686.     }
  687. }
  688.  
  689.  
  690. //
  691. // Changes volume, stereo-separation, and pitch variables
  692. //  from the norm of a sound effect to be played.
  693. // If the sound is not audible, returns a 0.
  694. // Otherwise, modifies parameters and returns 1.
  695. //
  696. int
  697. S_AdjustSoundParams (mobj_t* listener, mobj_t* source,
  698.                      int* vol, int* sep, int* pitch)
  699. {
  700.     fixed_t     approx_dist;
  701.     fixed_t     adx;
  702.     fixed_t     ady;
  703.     angle_t     angle;
  704.  
  705.     // calculate the distance to sound origin
  706.     //  and clip it if necessary
  707.     adx = abs(listener->x - source->x);
  708.     ady = abs(listener->y - source->y);
  709.  
  710.     // From _GG1_ p.428. Appox. eucledian distance fast.
  711.     approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1);
  712.    
  713.     if (gamemap != 8
  714.         && approx_dist > S_CLIPPING_DIST)
  715.     {
  716.         return 0;
  717.     }
  718.    
  719.     // angle of source to listener
  720.     angle = R_PointToAngle2(listener->x,
  721.                             listener->y,
  722.                             source->x,
  723.                             source->y);
  724.  
  725.     if (angle > listener->angle)
  726.         angle = angle - listener->angle;
  727.     else
  728.         angle = angle + (0xffffffff - listener->angle);
  729.  
  730.     angle >>= ANGLETOFINESHIFT;
  731.  
  732.     // stereo separation
  733.     *sep = 128 - (FixedMul(S_STEREO_SWING,finesine[angle])>>FRACBITS);
  734.  
  735.     // volume calculation
  736.     if (approx_dist < S_CLOSE_DIST)
  737.     {
  738.         *vol = snd_SfxVolume;
  739.     }
  740.     else if (gamemap == 8)
  741.     {
  742.         if (approx_dist > S_CLIPPING_DIST)
  743.             approx_dist = S_CLIPPING_DIST;
  744.  
  745.         *vol = 15+ ((snd_SfxVolume-15)
  746.                     *((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
  747.             / S_ATTENUATOR;
  748.     }
  749.     else
  750.     {
  751.         // distance effect
  752.         *vol = (snd_SfxVolume
  753.                 * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
  754.             / S_ATTENUATOR;
  755.     }
  756.    
  757.     return (*vol > 0);
  758. }
  759.  
  760. //
  761. // S_getChannel :
  762. //   If none available, return -1.  Otherwise channel #.
  763. //
  764. int S_getChannel( void *origin, sfxinfo_t *sfxinfo, int sfxid )
  765.    {
  766.     // channel number to use
  767.     int         cnum;
  768.        
  769.     channel_t*  c;
  770.  
  771.     // Find an open channel
  772.     //for (cnum = 0; cnum < numChannels; cnum++)
  773.     for (cnum = 0; cnum < NUM_CHANNELS; cnum++)
  774.        {
  775.         if (!channels[cnum].sfxinfo)
  776.             break;
  777.         else
  778.         if (origin && channels[cnum].origin == origin)
  779.            {
  780.             S_StopChannel(cnum);
  781.             break;
  782.            }
  783.        }
  784.  
  785.     // None available
  786.     if (cnum == NUM_CHANNELS)
  787.        {
  788.         // Look for lower priority
  789.         for (cnum = NUMSFX; cnum < NUM_CHANNELS; cnum++)
  790.              if (channels[cnum].sfxinfo->priority >= sfxinfo->priority)
  791.                  break;
  792.  
  793.         if (cnum == numChannels)
  794.            {
  795.             // FUCK!  No lower priority.  Sorry, Charlie.    
  796.             return -1;
  797.            }
  798.         else
  799.            {
  800.             // Otherwise, kick out lower priority.
  801.             S_StopChannel(cnum);
  802.            }
  803.        }
  804.  
  805.     c = &channels[cnum];
  806.  
  807.     // channel is decided to be cnum.
  808.     c->sfxinfo = sfxinfo;
  809.     c->origin = origin;
  810.  
  811.     return cnum;
  812.    }
  813.  
  814.  
  815.  
  816.  
  817.