home *** CD-ROM | disk | FTP | other *** search
/ ST-Computer Leser-CD 2000 January / LCD_01_2000.iso / games / doom / pmdoom / src / s_sound.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-17  |  17.7 KB  |  882 lines

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