home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / snd_dma.c < prev    next >
C/C++ Source or Header  |  2000-06-17  |  21KB  |  1,023 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // snd_dma.c -- main control for any streaming sound output device
  21.  
  22. #include "quakedef.h"
  23.  
  24. #ifdef _WIN32
  25. #include "winquake.h"
  26. #endif
  27.  
  28. void S_Play(void);
  29. void S_PlayVol(void);
  30. void S_SoundList(void);
  31. void S_Update_();
  32. void S_StopAllSounds(qboolean clear);
  33. void S_StopAllSoundsC(void);
  34.  
  35. // =======================================================================
  36. // Internal sound data & structures
  37. // =======================================================================
  38.  
  39. channel_t   channels[MAX_CHANNELS];
  40. int     total_channels;
  41.  
  42. int       snd_blocked = 0;
  43. static qboolean snd_ambient = 1;
  44. qboolean    snd_initialized = false;
  45.  
  46. // pointer should go away
  47. volatile dma_t  *shm = 0;
  48. volatile dma_t sn;
  49.  
  50. vec3_t    listener_origin;
  51. vec3_t    listener_forward;
  52. vec3_t    listener_right;
  53. vec3_t    listener_up;
  54. vec_t   sound_nominal_clip_dist=1000.0;
  55.  
  56. int     soundtime;    // sample PAIRS
  57. int       paintedtime;  // sample PAIRS
  58.  
  59.  
  60. #define MAX_SFX   512
  61. sfx_t   *known_sfx;   // hunk allocated [MAX_SFX]
  62. int     num_sfx;
  63.  
  64. sfx_t   *ambient_sfx[NUM_AMBIENTS];
  65.  
  66. int     desired_speed = 11025;
  67. int     desired_bits = 16;
  68.  
  69. int sound_started=0;
  70.  
  71. cvar_t bgmvolume = {"bgmvolume", "1", true};
  72. cvar_t volume = {"volume", "0.7", true};
  73.  
  74. cvar_t nosound = {"nosound", "0"};
  75. cvar_t precache = {"precache", "1"};
  76. cvar_t loadas8bit = {"loadas8bit", "0"};
  77. cvar_t bgmbuffer = {"bgmbuffer", "4096"};
  78. cvar_t ambient_level = {"ambient_level", "0.3"};
  79. cvar_t ambient_fade = {"ambient_fade", "100"};
  80. cvar_t snd_noextraupdate = {"snd_noextraupdate", "0"};
  81. cvar_t snd_show = {"snd_show", "0"};
  82. cvar_t _snd_mixahead = {"_snd_mixahead", "0.1", true};
  83.  
  84.  
  85. // ====================================================================
  86. // User-setable variables
  87. // ====================================================================
  88.  
  89.  
  90. //
  91. // Fake dma is a synchronous faking of the DMA progress used for
  92. // isolating performance in the renderer.  The fakedma_updates is
  93. // number of times S_Update() is called per second.
  94. //
  95.  
  96. qboolean fakedma = false;
  97. int fakedma_updates = 15;
  98.  
  99.  
  100. void S_AmbientOff (void)
  101. {
  102.   snd_ambient = false;
  103. }
  104.  
  105.  
  106. void S_AmbientOn (void)
  107. {
  108.   snd_ambient = true;
  109. }
  110.  
  111.  
  112. void S_SoundInfo_f(void)
  113. {
  114.   if (!sound_started || !shm)
  115.   {
  116.     Con_Printf ("sound system not started\n");
  117.     return;
  118.   }
  119.   
  120.     Con_Printf("%5d stereo\n", shm->channels - 1);
  121.     Con_Printf("%5d samples\n", shm->samples);
  122.     Con_Printf("%5d samplepos\n", shm->samplepos);
  123.     Con_Printf("%5d samplebits\n", shm->samplebits);
  124.     Con_Printf("%5d submission_chunk\n", shm->submission_chunk);
  125.     Con_Printf("%5d speed\n", shm->speed);
  126.     Con_Printf("0x%x dma buffer\n", shm->buffer);
  127.   Con_Printf("%5d total_channels\n", total_channels);
  128. }
  129.  
  130.  
  131. /*
  132. ================
  133. S_Startup
  134. ================
  135. */
  136.  
  137. void S_Startup (void)
  138. {
  139.   int   rc;
  140.  
  141.   if (!snd_initialized)
  142.     return;
  143.  
  144.   if (!fakedma)
  145.   {
  146.     rc = SNDDMA_Init();
  147.  
  148.     if (!rc)
  149.     {
  150. #ifndef _WIN32
  151.       Con_Printf("S_Startup: SNDDMA_Init failed.\n");
  152. #endif
  153.       sound_started = 0;
  154.       return;
  155.     }
  156.   }
  157.  
  158.   sound_started = 1;
  159. }
  160.  
  161.  
  162. /*
  163. ================
  164. S_Init
  165. ================
  166. */
  167. void S_Init (void)
  168. {
  169.  
  170.   Con_Printf("\nSound Initialization\n");
  171.  
  172.   if (COM_CheckParm("-nosound"))
  173.     return;
  174.  
  175.   if (COM_CheckParm("-simsound"))
  176.     fakedma = true;
  177.  
  178.   Cmd_AddCommand("play", S_Play);
  179.   Cmd_AddCommand("playvol", S_PlayVol);
  180.   Cmd_AddCommand("stopsound", S_StopAllSoundsC);
  181.   Cmd_AddCommand("soundlist", S_SoundList);
  182.   Cmd_AddCommand("soundinfo", S_SoundInfo_f);
  183.  
  184.   Cvar_RegisterVariable(&nosound);
  185. #ifndef AMIGA
  186.   Cvar_RegisterVariable(&volume);
  187. #endif
  188.   Cvar_RegisterVariable(&precache);
  189.   Cvar_RegisterVariable(&loadas8bit);
  190. #ifndef AMIGA
  191.   Cvar_RegisterVariable(&bgmvolume);
  192. #endif
  193.   Cvar_RegisterVariable(&bgmbuffer);
  194.   Cvar_RegisterVariable(&ambient_level);
  195.   Cvar_RegisterVariable(&ambient_fade);
  196.   Cvar_RegisterVariable(&snd_noextraupdate);
  197.   Cvar_RegisterVariable(&snd_show);
  198. #ifndef AMIGA
  199.   Cvar_RegisterVariable(&_snd_mixahead);
  200. #endif
  201.   if (host_parms.memsize < 0x800000)
  202.   {
  203.     Cvar_Set ("loadas8bit", "1");
  204.     Con_Printf ("loading all sounds as 8bit\n");
  205.   }
  206.  
  207.  
  208.  
  209.   snd_initialized = true;
  210.  
  211.   S_Startup ();
  212.  
  213.   SND_InitScaletable ();
  214.  
  215.   known_sfx = Hunk_AllocName (MAX_SFX*sizeof(sfx_t), "sfx_t");
  216.   num_sfx = 0;
  217.  
  218. // create a piece of DMA memory
  219.  
  220.   if (fakedma)
  221.   {
  222.     shm = (void *) Hunk_AllocName(sizeof(*shm), "shm");
  223.     shm->splitbuffer = 0;
  224.     shm->samplebits = 16;
  225.     shm->speed = 22050;
  226.     shm->channels = 2;
  227.     shm->samples = 32768;
  228.     shm->samplepos = 0;
  229.     shm->soundalive = true;
  230.     shm->gamealive = true;
  231.     shm->submission_chunk = 1;
  232.     shm->buffer = Hunk_AllocName(1<<16, "shmbuf");
  233.   }
  234.  
  235.   Con_Printf ("Sound sampling rate: %i\n", shm->speed);
  236.  
  237.   // provides a tick sound until washed clean
  238.  
  239. //  if (shm->buffer)
  240. //    shm->buffer[4] = shm->buffer[5] = 0x7f; // force a pop for debugging
  241.  
  242.   ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
  243.   ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
  244.  
  245.   S_StopAllSounds (true);
  246. }
  247.  
  248.  
  249. // =======================================================================
  250. // Shutdown sound engine
  251. // =======================================================================
  252.  
  253. void S_Shutdown(void)
  254. {
  255.  
  256.   if (!sound_started)
  257.     return;
  258.  
  259.   if (shm)
  260.     shm->gamealive = 0;
  261.  
  262.   shm = 0;
  263.   sound_started = 0;
  264.  
  265.   if (!fakedma)
  266.   {
  267.     SNDDMA_Shutdown();
  268.   }
  269. }
  270.  
  271.  
  272. // =======================================================================
  273. // Load a sound
  274. // =======================================================================
  275.  
  276. /*
  277. ==================
  278. S_FindName
  279.  
  280. ==================
  281. */
  282. sfx_t *S_FindName (char *name)
  283. {
  284.   int   i;
  285.   sfx_t *sfx;
  286.  
  287.   if (!name)
  288.     Sys_Error ("S_FindName: NULL\n");
  289.  
  290.   if (Q_strlen(name) >= MAX_QPATH)
  291.     Sys_Error ("Sound name too long: %s", name);
  292.  
  293. // see if already loaded
  294.   for (i=0 ; i < num_sfx ; i++)
  295.     if (!Q_strcmp(known_sfx[i].name, name))
  296.     {
  297.       return &known_sfx[i];
  298.     }
  299.  
  300.   if (num_sfx == MAX_SFX)
  301.     Sys_Error ("S_FindName: out of sfx_t");
  302.   
  303.   sfx = &known_sfx[i];
  304.   strcpy (sfx->name, name);
  305.  
  306.   num_sfx++;
  307.   
  308.   return sfx;
  309. }
  310.  
  311.  
  312. /*
  313. ==================
  314. S_TouchSound
  315.  
  316. ==================
  317. */
  318. void S_TouchSound (char *name)
  319. {
  320.   sfx_t *sfx;
  321.   
  322.   if (!sound_started)
  323.     return;
  324.  
  325.   sfx = S_FindName (name);
  326.   Cache_Check (&sfx->cache);
  327. }
  328.  
  329. /*
  330. ==================
  331. S_PrecacheSound
  332.  
  333. ==================
  334. */
  335. sfx_t *S_PrecacheSound (char *name)
  336. {
  337.   sfx_t *sfx;
  338.  
  339.   if (!sound_started || nosound.value)
  340.     return NULL;
  341.  
  342.   sfx = S_FindName (name);
  343.   
  344. // cache it in
  345.   if (precache.value)
  346.     S_LoadSound (sfx);
  347.   
  348.   return sfx;
  349. }
  350.  
  351.  
  352. //=============================================================================
  353.  
  354. /*
  355. =================
  356. SND_PickChannel
  357. =================
  358. */
  359. channel_t *SND_PickChannel(int entnum, int entchannel)
  360. {
  361.     int ch_idx;
  362.     int first_to_die;
  363.     int life_left;
  364.  
  365. // Check for replacement sound, or find the best one to replace
  366.     first_to_die = -1;
  367.     life_left = 0x7fffffff;
  368.     for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++)
  369.     {
  370.     if (entchannel != 0   // channel 0 never overrides
  371.     && channels[ch_idx].entnum == entnum
  372.     && (channels[ch_idx].entchannel == entchannel || entchannel == -1) )
  373.     { // allways override sound from same entity
  374.       first_to_die = ch_idx;
  375.       break;
  376.     }
  377.  
  378.     // don't let monster sounds override player sounds
  379.     if (channels[ch_idx].entnum == cl.viewentity && entnum != cl.viewentity && channels[ch_idx].sfx)
  380.       continue;
  381.  
  382.     if (channels[ch_idx].end - paintedtime < life_left)
  383.     {
  384.       life_left = channels[ch_idx].end - paintedtime;
  385.       first_to_die = ch_idx;
  386.     }
  387.    }
  388.  
  389.   if (first_to_die == -1)
  390.     return NULL;
  391.  
  392.   if (channels[first_to_die].sfx)
  393.     channels[first_to_die].sfx = NULL;
  394.  
  395.     return &channels[first_to_die];    
  396. }       
  397.  
  398. /*
  399. =================
  400. SND_Spatialize
  401. =================
  402. */
  403. void SND_Spatialize(channel_t *ch)
  404. {
  405.     vec_t dot;
  406.     vec_t ldist, rdist, dist;
  407.     vec_t lscale, rscale, scale;
  408.     vec3_t source_vec;
  409.   sfx_t *snd;
  410.  
  411. // anything coming from the view entity will allways be full volume
  412.   if (ch->entnum == cl.viewentity)
  413.   {
  414.     ch->leftvol = ch->master_vol;
  415.     ch->rightvol = ch->master_vol;
  416.     return;
  417.   }
  418.  
  419. // calculate stereo seperation and distance attenuation
  420.  
  421.   snd = ch->sfx;
  422.   VectorSubtract(ch->origin, listener_origin, source_vec);
  423.   
  424.   dist = VectorNormalize(source_vec) * ch->dist_mult;
  425.   
  426.   dot = DotProduct(listener_right, source_vec);
  427.  
  428.   if (shm->channels == 1)
  429.   {
  430.     rscale = 1.0;
  431.     lscale = 1.0;
  432.   }
  433.   else
  434.   {
  435.     rscale = 1.0 + dot;
  436.     lscale = 1.0 - dot;
  437.   }
  438.  
  439. // add in distance effect
  440.   scale = (1.0 - dist) * rscale;
  441.   ch->rightvol = (int) (ch->master_vol * scale);
  442.   if (ch->rightvol < 0)
  443.     ch->rightvol = 0;
  444.  
  445.   scale = (1.0 - dist) * lscale;
  446.   ch->leftvol = (int) (ch->master_vol * scale);
  447.   if (ch->leftvol < 0)
  448.     ch->leftvol = 0;
  449. }           
  450.  
  451.  
  452. // =======================================================================
  453. // Start a sound effect
  454. // =======================================================================
  455.  
  456. void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation)
  457. {
  458.   channel_t *target_chan, *check;
  459.   sfxcache_t  *sc;
  460.   int   vol;
  461.   int   ch_idx;
  462.   int   skip;
  463.  
  464.   if (!sound_started)
  465.     return;
  466.  
  467.   if (!sfx)
  468.     return;
  469.  
  470.   if (nosound.value)
  471.     return;
  472.  
  473.   vol = fvol*255;
  474.  
  475. // pick a channel to play on
  476.   target_chan = SND_PickChannel(entnum, entchannel);
  477.   if (!target_chan)
  478.     return;
  479.     
  480. // spatialize
  481.   memset (target_chan, 0, sizeof(*target_chan));
  482.   VectorCopy(origin, target_chan->origin);
  483.   target_chan->dist_mult = attenuation / sound_nominal_clip_dist;
  484.   target_chan->master_vol = vol;
  485.   target_chan->entnum = entnum;
  486.   target_chan->entchannel = entchannel;
  487.   SND_Spatialize(target_chan);
  488.  
  489.   if (!target_chan->leftvol && !target_chan->rightvol)
  490.     return;   // not audible at all
  491.  
  492. // new channel
  493.   sc = S_LoadSound (sfx);
  494.   if (!sc)
  495.   {
  496.     target_chan->sfx = NULL;
  497.     return;   // couldn't load the sound's data
  498.   }
  499.  
  500.   target_chan->sfx = sfx;
  501.   target_chan->pos = 0.0;
  502.     target_chan->end = paintedtime + sc->length;  
  503.  
  504. // if an identical sound has also been started this frame, offset the pos
  505. // a bit to keep it from just making the first one louder
  506.   check = &channels[NUM_AMBIENTS];
  507.     for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++)
  508.     {
  509.     if (check == target_chan)
  510.       continue;
  511.     if (check->sfx == sfx && !check->pos)
  512.     {
  513.       skip = rand () % (int)(0.1*shm->speed);
  514.       if (skip >= target_chan->end)
  515.         skip = target_chan->end - 1;
  516.       target_chan->pos += skip;
  517.       target_chan->end -= skip;
  518.       break;
  519.     }
  520.     
  521.   }
  522. }
  523.  
  524. void S_StopSound(int entnum, int entchannel)
  525. {
  526.   int i;
  527.  
  528.   for (i=0 ; i<MAX_DYNAMIC_CHANNELS ; i++)
  529.   {
  530.     if (channels[i].entnum == entnum
  531.       && channels[i].entchannel == entchannel)
  532.     {
  533.       channels[i].end = 0;
  534.       channels[i].sfx = NULL;
  535.       return;
  536.     }
  537.   }
  538. }
  539.  
  540. void S_StopAllSounds(qboolean clear)
  541. {
  542.   int   i;
  543.  
  544.   if (!sound_started)
  545.     return;
  546.  
  547.   total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics
  548.  
  549.   for (i=0 ; i<MAX_CHANNELS ; i++)
  550.     if (channels[i].sfx)
  551.       channels[i].sfx = NULL;
  552.  
  553.   Q_memset(channels, 0, MAX_CHANNELS * sizeof(channel_t));
  554.  
  555.   if (clear)
  556.     S_ClearBuffer ();
  557. }
  558.  
  559. void S_StopAllSoundsC (void)
  560. {
  561.   S_StopAllSounds (true);
  562. }
  563.  
  564. void S_ClearBuffer (void)
  565. {
  566.   int   clear;
  567.     
  568. #ifdef _WIN32
  569.   if (!sound_started || !shm || (!shm->buffer && !pDSBuf))
  570. #else
  571.   if (!sound_started || !shm || !shm->buffer)
  572. #endif
  573.     return;
  574.  
  575.   if (shm->samplebits == 8)
  576.     clear = 0x80;
  577.   else
  578.     clear = 0;
  579.  
  580. #ifdef _WIN32
  581.   if (pDSBuf)
  582.   {
  583.     DWORD dwSize;
  584.     DWORD *pData;
  585.     int   reps;
  586.     HRESULT hresult;
  587.  
  588.     reps = 0;
  589.  
  590.     while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pData, &dwSize, NULL, NULL, 0)) != DS_OK)
  591.     {
  592.       if (hresult != DSERR_BUFFERLOST)
  593.       {
  594.         Con_Printf ("S_ClearBuffer: DS::Lock Sound Buffer Failed\n");
  595.         S_Shutdown ();
  596.         return;
  597.       }
  598.  
  599.       if (++reps > 10000)
  600.       {
  601.         Con_Printf ("S_ClearBuffer: DS: couldn't restore buffer\n");
  602.         S_Shutdown ();
  603.         return;
  604.       }
  605.     }
  606.  
  607.     Q_memset(pData, clear, shm->samples * shm->samplebits/8);
  608.  
  609.     pDSBuf->lpVtbl->Unlock(pDSBuf, pData, dwSize, NULL, 0);
  610.   
  611.   }
  612.   else
  613. #endif
  614.   {
  615.     Q_memset(shm->buffer, clear, shm->samples * shm->samplebits/8);
  616.   }
  617. }
  618.  
  619.  
  620. /*
  621. =================
  622. S_StaticSound
  623. =================
  624. */
  625. void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
  626. {
  627.   channel_t *ss;
  628.   sfxcache_t    *sc;
  629.  
  630.   if (!sfx)
  631.     return;
  632.  
  633.   if (total_channels == MAX_CHANNELS)
  634.   {
  635.     Con_Printf ("total_channels == MAX_CHANNELS\n");
  636.     return;
  637.   }
  638.  
  639.   ss = &channels[total_channels];
  640.   total_channels++;
  641.  
  642.   sc = S_LoadSound (sfx);
  643.   if (!sc)
  644.     return;
  645.  
  646.   if (sc->loopstart == -1)
  647.   {
  648.     Con_Printf ("Sound %s not looped\n", sfx->name);
  649.     return;
  650.   }
  651.   
  652.   ss->sfx = sfx;
  653.   VectorCopy (origin, ss->origin);
  654.   ss->master_vol = vol;
  655.   ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist;
  656.     ss->end = paintedtime + sc->length; 
  657.   
  658.   SND_Spatialize (ss);
  659. }
  660.  
  661.  
  662. //=============================================================================
  663.  
  664. /*
  665. ===================
  666. S_UpdateAmbientSounds
  667. ===================
  668. */
  669. void S_UpdateAmbientSounds (void)
  670. {
  671.   mleaf_t   *l;
  672.   float   vol;
  673.   int     ambient_channel;
  674.   channel_t *chan;
  675.  
  676.   if (!snd_ambient)
  677.     return;
  678.  
  679. // calc ambient sound levels
  680.   if (!cl.worldmodel)
  681.     return;
  682.  
  683.   l = Mod_PointInLeaf (listener_origin, cl.worldmodel);
  684.   if (!l || !ambient_level.value)
  685.   {
  686.     for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
  687.       channels[ambient_channel].sfx = NULL;
  688.     return;
  689.   }
  690.  
  691.   for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
  692.   {
  693.     chan = &channels[ambient_channel];  
  694.     chan->sfx = ambient_sfx[ambient_channel];
  695.   
  696.     vol = ambient_level.value * l->ambient_sound_level[ambient_channel];
  697.     if (vol < 8)
  698.       vol = 0;
  699.  
  700.   // don't adjust volume too fast
  701.     if (chan->master_vol < vol)
  702.     {
  703.       chan->master_vol += host_frametime * ambient_fade.value;
  704.       if (chan->master_vol > vol)
  705.         chan->master_vol = vol;
  706.     }
  707.     else if (chan->master_vol > vol)
  708.     {
  709.       chan->master_vol -= host_frametime * ambient_fade.value;
  710.       if (chan->master_vol < vol)
  711.         chan->master_vol = vol;
  712.     }
  713.     
  714.     chan->leftvol = chan->rightvol = chan->master_vol;
  715.   }
  716. }
  717.  
  718.  
  719. /*
  720. ============
  721. S_Update
  722.  
  723. Called once each time through the main loop
  724. ============
  725. */
  726. void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
  727. {
  728.   int     i, j;
  729.   int     total;
  730.   channel_t *ch;
  731.   channel_t *combine;
  732.  
  733.   if (!sound_started || (snd_blocked > 0))
  734.     return;
  735.  
  736.   VectorCopy(origin, listener_origin);
  737.   VectorCopy(forward, listener_forward);
  738.   VectorCopy(right, listener_right);
  739.   VectorCopy(up, listener_up);
  740.   
  741. // update general area ambient sound sources
  742.   S_UpdateAmbientSounds ();
  743.  
  744.   combine = NULL;
  745.  
  746. // update spatialization for static and dynamic sounds  
  747.   ch = channels+NUM_AMBIENTS;
  748.   for (i=NUM_AMBIENTS ; i<total_channels; i++, ch++)
  749.   {
  750.     if (!ch->sfx)
  751.       continue;
  752.     SND_Spatialize(ch);         // respatialize channel
  753.     if (!ch->leftvol && !ch->rightvol)
  754.       continue;
  755.  
  756.   // try to combine static sounds with a previous channel of the same
  757.   // sound effect so we don't mix five torches every frame
  758.   
  759.     if (i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS)
  760.     {
  761.     // see if it can just use the last one
  762.       if (combine && combine->sfx == ch->sfx)
  763.       {
  764.         combine->leftvol += ch->leftvol;
  765.         combine->rightvol += ch->rightvol;
  766.         ch->leftvol = ch->rightvol = 0;
  767.         continue;
  768.       }
  769.     // search for one
  770.       combine = channels+MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS;
  771.       for (j=MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS ; j<i; j++, combine++)
  772.         if (combine->sfx == ch->sfx)
  773.           break;
  774.           
  775.       if (j == total_channels)
  776.       {
  777.         combine = NULL;
  778.       }
  779.       else
  780.       {
  781.         if (combine != ch)
  782.         {
  783.           combine->leftvol += ch->leftvol;
  784.           combine->rightvol += ch->rightvol;
  785.           ch->leftvol = ch->rightvol = 0;
  786.         }
  787.         continue;
  788.       }
  789.     }
  790.     
  791.     
  792.   }
  793.  
  794. //
  795. // debugging output
  796. //
  797.   if (snd_show.value)
  798.   {
  799.     total = 0;
  800.     ch = channels;
  801.     for (i=0 ; i<total_channels; i++, ch++)
  802.       if (ch->sfx && (ch->leftvol || ch->rightvol) )
  803.       {
  804.         //Con_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name);
  805.         total++;
  806.       }
  807.     
  808.     Con_Printf ("----(%i)----\n", total);
  809.   }
  810.  
  811. // mix some sound
  812.   S_Update_();
  813. }
  814.  
  815. void GetSoundtime(void)
  816. {
  817.   int   samplepos;
  818.   static  int   buffers;
  819.   static  int   oldsamplepos;
  820.   int   fullsamples;
  821.   
  822.   fullsamples = shm->samples / shm->channels;
  823.  
  824. // it is possible to miscount buffers if it has wrapped twice between
  825. // calls to S_Update.  Oh well.
  826. #ifdef __sun__
  827.   soundtime = SNDDMA_GetSamples();
  828. #else
  829.   samplepos = SNDDMA_GetDMAPos();
  830.  
  831.  
  832.   if (samplepos < oldsamplepos)
  833.   {
  834.     buffers++;          // buffer wrapped
  835.     
  836.     if (paintedtime > 0x40000000)
  837.     { // time to chop things off to avoid 32 bit limits
  838.       buffers = 0;
  839.       paintedtime = fullsamples;
  840.       S_StopAllSounds (true);
  841.     }
  842.   }
  843.   oldsamplepos = samplepos;
  844.  
  845.   soundtime = buffers*fullsamples + samplepos/shm->channels;
  846. #endif
  847. }
  848.  
  849. void S_ExtraUpdate (void)
  850. {
  851.  
  852. #ifdef _WIN32
  853.   IN_Accumulate ();
  854. #endif
  855.  
  856.   if (snd_noextraupdate.value)
  857.     return;   // don't pollute timings
  858.   S_Update_();
  859. }
  860.  
  861. void S_Update_(void)
  862. {
  863.   unsigned        endtime;
  864.   int       samps;
  865.   
  866.   if (!sound_started || (snd_blocked > 0))
  867.     return;
  868.  
  869. // Updates DMA time
  870.   GetSoundtime();
  871.  
  872. // check to make sure that we haven't overshot
  873.   if (paintedtime < soundtime)
  874.   {
  875.     //Con_Printf ("S_Update_ : overflow\n");
  876.     paintedtime = soundtime;
  877.   }
  878.  
  879. // mix ahead of current position
  880.   endtime = soundtime + _snd_mixahead.value * shm->speed;
  881.   samps = shm->samples >> (shm->channels-1);
  882.   if (endtime - soundtime > samps)
  883.     endtime = soundtime + samps;
  884.  
  885. #ifdef _WIN32
  886. // if the buffer was lost or stopped, restore it and/or restart it
  887.   {
  888.     DWORD dwStatus;
  889.  
  890.     if (pDSBuf)
  891.     {
  892.       if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DD_OK)
  893.         Con_Printf ("Couldn't get sound buffer status\n");
  894.       
  895.       if (dwStatus & DSBSTATUS_BUFFERLOST)
  896.         pDSBuf->lpVtbl->Restore (pDSBuf);
  897.       
  898.       if (!(dwStatus & DSBSTATUS_PLAYING))
  899.         pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
  900.     }
  901.   }
  902. #endif
  903.  
  904.   S_PaintChannels (endtime);
  905.  
  906.   SNDDMA_Submit ();
  907. }
  908.  
  909. /*
  910. ===============================================================================
  911.  
  912. console functions
  913.  
  914. ===============================================================================
  915. */
  916.  
  917. void S_Play(void)
  918. {
  919.   static int hash=345;
  920.   int   i;
  921.   char name[256];
  922.   sfx_t *sfx;
  923.   
  924.   i = 1;
  925.   while (i<Cmd_Argc())
  926.   {
  927.     if (!Q_strrchr(Cmd_Argv(i), '.'))
  928.     {
  929.       Q_strcpy(name, Cmd_Argv(i));
  930.       Q_strcat(name, ".wav");
  931.     }
  932.     else
  933.       Q_strcpy(name, Cmd_Argv(i));
  934.     sfx = S_PrecacheSound(name);
  935.     S_StartSound(hash++, 0, sfx, listener_origin, 1.0, 1.0);
  936.     i++;
  937.   }
  938. }
  939.  
  940. void S_PlayVol(void)
  941. {
  942.   static int hash=543;
  943.   int i;
  944.   float vol;
  945.   char name[256];
  946.   sfx_t *sfx;
  947.   
  948.   i = 1;
  949.   while (i<Cmd_Argc())
  950.   {
  951.     if (!Q_strrchr(Cmd_Argv(i), '.'))
  952.     {
  953.       Q_strcpy(name, Cmd_Argv(i));
  954.       Q_strcat(name, ".wav");
  955.     }
  956.     else
  957.       Q_strcpy(name, Cmd_Argv(i));
  958.     sfx = S_PrecacheSound(name);
  959.     vol = Q_atof(Cmd_Argv(i+1));
  960.     S_StartSound(hash++, 0, sfx, listener_origin, vol, 1.0);
  961.     i+=2;
  962.   }
  963. }
  964.  
  965. void S_SoundList(void)
  966. {
  967.   int   i;
  968.   sfx_t *sfx;
  969.   sfxcache_t  *sc;
  970.   int   size, total;
  971.  
  972.   total = 0;
  973.   for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++)
  974.   {
  975.     sc = Cache_Check (&sfx->cache);
  976.     if (!sc)
  977.       continue;
  978.     size = sc->length*sc->width*(sc->stereo+1);
  979.     total += size;
  980.     if (sc->loopstart >= 0)
  981.       Con_Printf ("L");
  982.     else
  983.       Con_Printf (" ");
  984.     Con_Printf("(%2db) %6i : %s\n",sc->width*8,  size, sfx->name);
  985.   }
  986.   Con_Printf ("Total resident: %i\n", total);
  987. }
  988.  
  989.  
  990. void S_LocalSound (char *sound)
  991. {
  992.   sfx_t *sfx;
  993.  
  994.   if (nosound.value)
  995.     return;
  996.   if (!sound_started)
  997.     return;
  998.     
  999.   sfx = S_PrecacheSound (sound);
  1000.   if (!sfx)
  1001.   {
  1002.     Con_Printf ("S_LocalSound: can't cache %s\n", sound);
  1003.     return;
  1004.   }
  1005.   S_StartSound (cl.viewentity, -1, sfx, vec3_origin, 1, 1);
  1006. }
  1007.  
  1008.  
  1009. void S_ClearPrecache (void)
  1010. {
  1011. }
  1012.  
  1013.  
  1014. void S_BeginPrecaching (void)
  1015. {
  1016. }
  1017.  
  1018.  
  1019. void S_EndPrecaching (void)
  1020. {
  1021. }
  1022.  
  1023.