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