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