1 /*
2 Copyright (C) 1997-2001 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 "client.h"
23 #include "snd_loc.h"
24 
25 void S_Play(void);
26 void S_SoundList(void);
27 void S_Update_();
28 void S_StopAllSounds(void);
29 
30 
31 // =======================================================================
32 // Internal sound data & structures
33 // =======================================================================
34 
35 // only begin attenuating sound volumes when outside the FULLVOLUME range
36 #define		SOUND_FULLVOLUME	80
37 
38 #define		SOUND_LOOPATTENUATE	0.003
39 
40 int			s_registration_sequence;
41 
42 channel_t   channels[MAX_CHANNELS];
43 
44 qboolean	snd_initialized = false;
45 int			sound_started=0;
46 
47 dma_t		dma;
48 
49 vec3_t		listener_origin;
50 vec3_t		listener_forward;
51 vec3_t		listener_right;
52 vec3_t		listener_up;
53 
54 qboolean	s_registering;
55 
56 int			soundtime;		// sample PAIRS
57 int   		paintedtime; 	// sample PAIRS
58 
59 // during registration it is possible to have more sounds
60 // than could actually be referenced during gameplay,
61 // because we don't want to free anything until we are
62 // sure we won't need it.
63 #define		MAX_SFX		(MAX_SOUNDS*2)
64 sfx_t		known_sfx[MAX_SFX];
65 int			num_sfx;
66 
67 #define		MAX_PLAYSOUNDS	128
68 playsound_t	s_playsounds[MAX_PLAYSOUNDS];
69 playsound_t	s_freeplays;
70 playsound_t	s_pendingplays;
71 
72 int			s_beginofs;
73 
74 cvar_t		*s_volume;
75 cvar_t		*s_testsound;
76 cvar_t		*s_loadas8bit;
77 cvar_t		*s_khz;
78 cvar_t		*s_show;
79 cvar_t		*s_mixahead;
80 cvar_t		*s_primary;
81 
82 
83 int		s_rawend;
84 portable_samplepair_t	s_rawsamples[MAX_RAW_SAMPLES];
85 
86 
87 // ====================================================================
88 // User-setable variables
89 // ====================================================================
90 
91 
S_SoundInfo_f(void)92 void S_SoundInfo_f(void)
93 {
94 	if (!sound_started)
95 	{
96 		Com_Printf ("sound system not started\n");
97 		return;
98 	}
99 
100     Com_Printf("%5d stereo\n", dma.channels - 1);
101     Com_Printf("%5d samples\n", dma.samples);
102     Com_Printf("%5d samplepos\n", dma.samplepos);
103     Com_Printf("%5d samplebits\n", dma.samplebits);
104     Com_Printf("%5d submission_chunk\n", dma.submission_chunk);
105     Com_Printf("%5d speed\n", dma.speed);
106     Com_Printf("0x%x dma buffer\n", dma.buffer);
107 }
108 
109 
110 
111 /*
112 ================
113 S_Init
114 ================
115 */
S_Init(void)116 void S_Init (void)
117 {
118 	cvar_t	*cv;
119 
120 	Com_Printf("\n------- sound initialization -------\n");
121 
122 	cv = Cvar_Get ("s_initsound", "1", 0);
123 	if (!cv->value)
124 		Com_Printf ("not initializing.\n");
125 	else
126 	{
127 		s_volume = Cvar_Get ("s_volume", "0.7", CVAR_ARCHIVE);
128 		s_khz = Cvar_Get ("s_khz", "11", CVAR_ARCHIVE);
129 		s_loadas8bit = Cvar_Get ("s_loadas8bit", "1", CVAR_ARCHIVE);
130 		s_mixahead = Cvar_Get ("s_mixahead", "0.2", CVAR_ARCHIVE);
131 		s_show = Cvar_Get ("s_show", "0", 0);
132 		s_testsound = Cvar_Get ("s_testsound", "0", 0);
133 		s_primary = Cvar_Get ("s_primary", "0", CVAR_ARCHIVE);	// win32 specific
134 
135 		Cmd_AddCommand("play", S_Play);
136 		Cmd_AddCommand("stopsound", S_StopAllSounds);
137 		Cmd_AddCommand("soundlist", S_SoundList);
138 		Cmd_AddCommand("soundinfo", S_SoundInfo_f);
139 
140 		if (!SNDDMA_Init())
141 			return;
142 
143 		S_InitScaletable ();
144 
145 		sound_started = 1;
146 		num_sfx = 0;
147 
148 		soundtime = 0;
149 		paintedtime = 0;
150 
151 		Com_Printf ("sound sampling rate: %i\n", dma.speed);
152 
153 		S_StopAllSounds ();
154 	}
155 
156 	Com_Printf("------------------------------------\n");
157 }
158 
159 
160 // =======================================================================
161 // Shutdown sound engine
162 // =======================================================================
163 
S_Shutdown(void)164 void S_Shutdown(void)
165 {
166 	int		i;
167 	sfx_t	*sfx;
168 
169 	if (!sound_started)
170 		return;
171 
172 	SNDDMA_Shutdown();
173 
174 	sound_started = 0;
175 
176 	Cmd_RemoveCommand("play");
177 	Cmd_RemoveCommand("stopsound");
178 	Cmd_RemoveCommand("soundlist");
179 	Cmd_RemoveCommand("soundinfo");
180 
181 	// free all sounds
182 	for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
183 	{
184 		if (!sfx->name[0])
185 			continue;
186 		if (sfx->cache)
187 			Z_Free (sfx->cache);
188 		memset (sfx, 0, sizeof(*sfx));
189 	}
190 
191 	num_sfx = 0;
192 }
193 
194 
195 // =======================================================================
196 // Load a sound
197 // =======================================================================
198 
199 /*
200 ==================
201 S_FindName
202 
203 ==================
204 */
S_FindName(char * name,qboolean create)205 sfx_t *S_FindName (char *name, qboolean create)
206 {
207 	int		i;
208 	sfx_t	*sfx;
209 
210 	if (!name)
211 		Com_Error (ERR_FATAL, "S_FindName: NULL\n");
212 	if (!name[0])
213 		Com_Error (ERR_FATAL, "S_FindName: empty name\n");
214 
215 	if (strlen(name) >= MAX_QPATH)
216 		Com_Error (ERR_FATAL, "Sound name too long: %s", name);
217 
218 	// see if already loaded
219 	for (i=0 ; i < num_sfx ; i++)
220 		if (!strcmp(known_sfx[i].name, name))
221 		{
222 			return &known_sfx[i];
223 		}
224 
225 	if (!create)
226 		return NULL;
227 
228 	// find a free sfx
229 	for (i=0 ; i < num_sfx ; i++)
230 		if (!known_sfx[i].name[0])
231 //			registration_sequence < s_registration_sequence)
232 			break;
233 
234 	if (i == num_sfx)
235 	{
236 		if (num_sfx == MAX_SFX)
237 			Com_Error (ERR_FATAL, "S_FindName: out of sfx_t");
238 		num_sfx++;
239 	}
240 
241 	sfx = &known_sfx[i];
242 	memset (sfx, 0, sizeof(*sfx));
243 	strcpy (sfx->name, name);
244 	sfx->registration_sequence = s_registration_sequence;
245 
246 	return sfx;
247 }
248 
249 
250 /*
251 ==================
252 S_AliasName
253 
254 ==================
255 */
S_AliasName(char * aliasname,char * truename)256 sfx_t *S_AliasName (char *aliasname, char *truename)
257 {
258 	sfx_t	*sfx;
259 	char	*s;
260 	int		i;
261 
262 	s = Z_Malloc (MAX_QPATH);
263 	strcpy (s, truename);
264 
265 	// find a free sfx
266 	for (i=0 ; i < num_sfx ; i++)
267 		if (!known_sfx[i].name[0])
268 			break;
269 
270 	if (i == num_sfx)
271 	{
272 		if (num_sfx == MAX_SFX)
273 			Com_Error (ERR_FATAL, "S_FindName: out of sfx_t");
274 		num_sfx++;
275 	}
276 
277 	sfx = &known_sfx[i];
278 	memset (sfx, 0, sizeof(*sfx));
279 	strcpy (sfx->name, aliasname);
280 	sfx->registration_sequence = s_registration_sequence;
281 	sfx->truename = s;
282 
283 	return sfx;
284 }
285 
286 
287 /*
288 =====================
289 S_BeginRegistration
290 
291 =====================
292 */
S_BeginRegistration(void)293 void S_BeginRegistration (void)
294 {
295 	s_registration_sequence++;
296 	s_registering = true;
297 }
298 
299 /*
300 ==================
301 S_RegisterSound
302 
303 ==================
304 */
S_RegisterSound(char * name)305 sfx_t *S_RegisterSound (char *name)
306 {
307 	sfx_t	*sfx;
308 
309 	if (!sound_started)
310 		return NULL;
311 
312 	sfx = S_FindName (name, true);
313 	sfx->registration_sequence = s_registration_sequence;
314 
315 	if (!s_registering)
316 		S_LoadSound (sfx);
317 
318 	return sfx;
319 }
320 
321 
322 /*
323 =====================
324 S_EndRegistration
325 
326 =====================
327 */
S_EndRegistration(void)328 void S_EndRegistration (void)
329 {
330 	int		i;
331 	sfx_t	*sfx;
332 	int		size;
333 
334 	// free any sounds not from this registration sequence
335 	for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
336 	{
337 		if (!sfx->name[0])
338 			continue;
339 		if (sfx->registration_sequence != s_registration_sequence)
340 		{	// don't need this sound
341 			if (sfx->cache)	// it is possible to have a leftover
342 				Z_Free (sfx->cache);	// from a server that didn't finish loading
343 			memset (sfx, 0, sizeof(*sfx));
344 		}
345 		else
346 		{	// make sure it is paged in
347 			if (sfx->cache)
348 			{
349 				size = sfx->cache->length*sfx->cache->width;
350 				Com_PageInMemory ((byte *)sfx->cache, size);
351 			}
352 		}
353 
354 	}
355 
356 	// load everything in
357 	for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
358 	{
359 		if (!sfx->name[0])
360 			continue;
361 		S_LoadSound (sfx);
362 	}
363 
364 	s_registering = false;
365 }
366 
367 
368 //=============================================================================
369 
370 /*
371 =================
372 S_PickChannel
373 =================
374 */
S_PickChannel(int entnum,int entchannel)375 channel_t *S_PickChannel(int entnum, int entchannel)
376 {
377     int			ch_idx;
378     int			first_to_die;
379     int			life_left;
380 	channel_t	*ch;
381 
382 	if (entchannel<0)
383 		Com_Error (ERR_DROP, "S_PickChannel: entchannel<0");
384 
385 // Check for replacement sound, or find the best one to replace
386     first_to_die = -1;
387     life_left = 0x7fffffff;
388     for (ch_idx=0 ; ch_idx < MAX_CHANNELS ; ch_idx++)
389     {
390 		if (entchannel != 0		// channel 0 never overrides
391 		&& channels[ch_idx].entnum == entnum
392 		&& channels[ch_idx].entchannel == entchannel)
393 		{	// always override sound from same entity
394 			first_to_die = ch_idx;
395 			break;
396 		}
397 
398 		// don't let monster sounds override player sounds
399 		if (channels[ch_idx].entnum == cl.playernum+1 && entnum != cl.playernum+1 && channels[ch_idx].sfx)
400 			continue;
401 
402 		if (channels[ch_idx].end - paintedtime < life_left)
403 		{
404 			life_left = channels[ch_idx].end - paintedtime;
405 			first_to_die = ch_idx;
406 		}
407    }
408 
409 	if (first_to_die == -1)
410 		return NULL;
411 
412 	ch = &channels[first_to_die];
413 	memset (ch, 0, sizeof(*ch));
414 
415     return ch;
416 }
417 
418 /*
419 =================
420 S_SpatializeOrigin
421 
422 Used for spatializing channels and autosounds
423 =================
424 */
S_SpatializeOrigin(vec3_t origin,float master_vol,float dist_mult,int * left_vol,int * right_vol)425 void S_SpatializeOrigin (vec3_t origin, float master_vol, float dist_mult, int *left_vol, int *right_vol)
426 {
427     vec_t		dot;
428     vec_t		dist;
429     vec_t		lscale, rscale, scale;
430     vec3_t		source_vec;
431 
432 	if (cls.state != ca_active)
433 	{
434 		*left_vol = *right_vol = 255;
435 		return;
436 	}
437 
438 // calculate stereo seperation and distance attenuation
439 	VectorSubtract(origin, listener_origin, source_vec);
440 
441 	dist = VectorNormalize(source_vec);
442 	dist -= SOUND_FULLVOLUME;
443 	if (dist < 0)
444 		dist = 0;			// close enough to be at full volume
445 	dist *= dist_mult;		// different attenuation levels
446 
447 	dot = DotProduct(listener_right, source_vec);
448 
449 	if (dma.channels == 1 || !dist_mult)
450 	{ // no attenuation = no spatialization
451 		rscale = 1.0;
452 		lscale = 1.0;
453 	}
454 	else
455 	{
456 		rscale = 0.5 * (1.0 + dot);
457 		lscale = 0.5*(1.0 - dot);
458 	}
459 
460 	// add in distance effect
461 	scale = (1.0 - dist) * rscale;
462 	*right_vol = (int) (master_vol * scale);
463 	if (*right_vol < 0)
464 		*right_vol = 0;
465 
466 	scale = (1.0 - dist) * lscale;
467 	*left_vol = (int) (master_vol * scale);
468 	if (*left_vol < 0)
469 		*left_vol = 0;
470 }
471 
472 /*
473 =================
474 S_Spatialize
475 =================
476 */
S_Spatialize(channel_t * ch)477 void S_Spatialize(channel_t *ch)
478 {
479 	vec3_t		origin;
480 
481 	// anything coming from the view entity will always be full volume
482 	if (ch->entnum == cl.playernum+1)
483 	{
484 		ch->leftvol = ch->master_vol;
485 		ch->rightvol = ch->master_vol;
486 		return;
487 	}
488 
489 	if (ch->fixed_origin)
490 	{
491 		VectorCopy (ch->origin, origin);
492 	}
493 	else
494 		CL_GetEntitySoundOrigin (ch->entnum, origin);
495 
496 	S_SpatializeOrigin (origin, ch->master_vol, ch->dist_mult, &ch->leftvol, &ch->rightvol);
497 }
498 
499 
500 /*
501 =================
502 S_AllocPlaysound
503 =================
504 */
S_AllocPlaysound(void)505 playsound_t *S_AllocPlaysound (void)
506 {
507 	playsound_t	*ps;
508 
509 	ps = s_freeplays.next;
510 	if (ps == &s_freeplays)
511 		return NULL;		// no free playsounds
512 
513 	// unlink from freelist
514 	ps->prev->next = ps->next;
515 	ps->next->prev = ps->prev;
516 
517 	return ps;
518 }
519 
520 
521 /*
522 =================
523 S_FreePlaysound
524 =================
525 */
S_FreePlaysound(playsound_t * ps)526 void S_FreePlaysound (playsound_t *ps)
527 {
528 	// unlink from channel
529 	ps->prev->next = ps->next;
530 	ps->next->prev = ps->prev;
531 
532 	// add to free list
533 	ps->next = s_freeplays.next;
534 	s_freeplays.next->prev = ps;
535 	ps->prev = &s_freeplays;
536 	s_freeplays.next = ps;
537 }
538 
539 
540 
541 /*
542 ===============
543 S_IssuePlaysound
544 
545 Take the next playsound and begin it on the channel
546 This is never called directly by S_Play*, but only
547 by the update loop.
548 ===============
549 */
S_IssuePlaysound(playsound_t * ps)550 void S_IssuePlaysound (playsound_t *ps)
551 {
552 	channel_t	*ch;
553 	sfxcache_t	*sc;
554 
555 	if (s_show->value)
556 		Com_Printf ("Issue %i\n", ps->begin);
557 	// pick a channel to play on
558 	ch = S_PickChannel(ps->entnum, ps->entchannel);
559 	if (!ch)
560 	{
561 		S_FreePlaysound (ps);
562 		return;
563 	}
564 
565 	// spatialize
566 	if (ps->attenuation == ATTN_STATIC)
567 		ch->dist_mult = ps->attenuation * 0.001;
568 	else
569 		ch->dist_mult = ps->attenuation * 0.0005;
570 	ch->master_vol = ps->volume;
571 	ch->entnum = ps->entnum;
572 	ch->entchannel = ps->entchannel;
573 	ch->sfx = ps->sfx;
574 	VectorCopy (ps->origin, ch->origin);
575 	ch->fixed_origin = ps->fixed_origin;
576 
577 	S_Spatialize(ch);
578 
579 	ch->pos = 0;
580 	sc = S_LoadSound (ch->sfx);
581     ch->end = paintedtime + sc->length;
582 
583 	// free the playsound
584 	S_FreePlaysound (ps);
585 }
586 
S_RegisterSexedSound(entity_state_t * ent,char * base)587 struct sfx_s *S_RegisterSexedSound (entity_state_t *ent, char *base)
588 {
589 	int				n;
590 	char			*p;
591 	struct sfx_s	*sfx;
592 	FILE			*f;
593 	char			model[MAX_QPATH];
594 	char			sexedFilename[MAX_QPATH];
595 	char			maleFilename[MAX_QPATH];
596 
597 	// determine what model the client is using
598 	model[0] = 0;
599 	n = CS_PLAYERSKINS + ent->number - 1;
600 	if (cl.configstrings[n][0])
601 	{
602 		p = strchr(cl.configstrings[n], '\\');
603 		if (p)
604 		{
605 			p += 1;
606 			strcpy(model, p);
607 			p = strchr(model, '/');
608 			if (p)
609 				*p = 0;
610 		}
611 	}
612 	// if we can't figure it out, they're male
613 	if (!model[0])
614 		strcpy(model, "male");
615 
616 	// see if we already know of the model specific sound
617 	Com_sprintf (sexedFilename, sizeof(sexedFilename), "#players/%s/%s", model, base+1);
618 	sfx = S_FindName (sexedFilename, false);
619 
620 	if (!sfx)
621 	{
622 		// no, so see if it exists
623 		FS_FOpenFile (&sexedFilename[1], &f);
624 		if (f)
625 		{
626 			// yes, close the file and register it
627 			FS_FCloseFile (f);
628 			sfx = S_RegisterSound (sexedFilename);
629 		}
630 		else
631 		{
632 			// no, revert to the male sound in the pak0.pak
633 			Com_sprintf (maleFilename, sizeof(maleFilename), "player/%s/%s", "male", base+1);
634 			sfx = S_AliasName (sexedFilename, maleFilename);
635 		}
636 	}
637 
638 	return sfx;
639 }
640 
641 
642 // =======================================================================
643 // Start a sound effect
644 // =======================================================================
645 
646 /*
647 ====================
648 S_StartSound
649 
650 Validates the parms and ques the sound up
651 if pos is NULL, the sound will be dynamically sourced from the entity
652 Entchannel 0 will never override a playing sound
653 ====================
654 */
S_StartSound(vec3_t origin,int entnum,int entchannel,sfx_t * sfx,float fvol,float attenuation,float timeofs)655 void S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float timeofs)
656 {
657 	sfxcache_t	*sc;
658 	int			vol;
659 	playsound_t	*ps, *sort;
660 	int			start;
661 
662 	if (!sound_started)
663 		return;
664 
665 	if (!sfx)
666 		return;
667 
668 	if (sfx->name[0] == '*')
669 		sfx = S_RegisterSexedSound(&cl_entities[entnum].current, sfx->name);
670 
671 	// make sure the sound is loaded
672 	sc = S_LoadSound (sfx);
673 	if (!sc)
674 		return;		// couldn't load the sound's data
675 
676 	vol = fvol*255;
677 
678 	// make the playsound_t
679 	ps = S_AllocPlaysound ();
680 	if (!ps)
681 		return;
682 
683 	if (origin)
684 	{
685 		VectorCopy (origin, ps->origin);
686 		ps->fixed_origin = true;
687 	}
688 	else
689 		ps->fixed_origin = false;
690 
691 	ps->entnum = entnum;
692 	ps->entchannel = entchannel;
693 	ps->attenuation = attenuation;
694 	ps->volume = vol;
695 	ps->sfx = sfx;
696 
697 	// drift s_beginofs
698 	start = cl.frame.servertime * 0.001 * dma.speed + s_beginofs;
699 	if (start < paintedtime)
700 	{
701 		start = paintedtime;
702 		s_beginofs = start - (cl.frame.servertime * 0.001 * dma.speed);
703 	}
704 	else if (start > paintedtime + 0.3 * dma.speed)
705 	{
706 		start = paintedtime + 0.1 * dma.speed;
707 		s_beginofs = start - (cl.frame.servertime * 0.001 * dma.speed);
708 	}
709 	else
710 	{
711 		s_beginofs-=10;
712 	}
713 
714 	if (!timeofs)
715 		ps->begin = paintedtime;
716 	else
717 		ps->begin = start + timeofs * dma.speed;
718 
719 	// sort into the pending sound list
720 	for (sort = s_pendingplays.next ;
721 		sort != &s_pendingplays && sort->begin < ps->begin ;
722 		sort = sort->next)
723 			;
724 
725 	ps->next = sort;
726 	ps->prev = sort->prev;
727 
728 	ps->next->prev = ps;
729 	ps->prev->next = ps;
730 }
731 
732 
733 /*
734 ==================
735 S_StartLocalSound
736 ==================
737 */
S_StartLocalSound(char * sound)738 void S_StartLocalSound (char *sound)
739 {
740 	sfx_t	*sfx;
741 
742 	if (!sound_started)
743 		return;
744 
745 	sfx = S_RegisterSound (sound);
746 	if (!sfx)
747 	{
748 		Com_Printf ("S_StartLocalSound: can't cache %s\n", sound);
749 		return;
750 	}
751 	S_StartSound (NULL, cl.playernum+1, 0, sfx, 1, 1, 0);
752 }
753 
754 
755 /*
756 ==================
757 S_ClearBuffer
758 ==================
759 */
S_ClearBuffer(void)760 void S_ClearBuffer (void)
761 {
762 	int		clear;
763 
764 	if (!sound_started)
765 		return;
766 
767 	s_rawend = 0;
768 
769 	if (dma.samplebits == 8)
770 		clear = 0x80;
771 	else
772 		clear = 0;
773 
774 	SNDDMA_BeginPainting ();
775 	if (dma.buffer) {
776 		/* memset(dma.buffer, clear, dma.samples * dma.samplebits/8); */
777 		int i;
778 		unsigned char *ptr = (unsigned char *)dma.buffer;
779 
780 		/* clear it manually because the buffer might be writeonly (mmap) */
781 		i = dma.samples * dma.samplebits/8;
782 		while (i--) {
783 			*ptr = clear;
784 			ptr++;
785 		}
786 	}
787 	SNDDMA_Submit ();
788 }
789 
790 /*
791 ==================
792 S_StopAllSounds
793 ==================
794 */
S_StopAllSounds(void)795 void S_StopAllSounds(void)
796 {
797 	int		i;
798 
799 	if (!sound_started)
800 		return;
801 
802 	// clear all the playsounds
803 	memset(s_playsounds, 0, sizeof(s_playsounds));
804 	s_freeplays.next = s_freeplays.prev = &s_freeplays;
805 	s_pendingplays.next = s_pendingplays.prev = &s_pendingplays;
806 
807 	for (i=0 ; i<MAX_PLAYSOUNDS ; i++)
808 	{
809 		s_playsounds[i].prev = &s_freeplays;
810 		s_playsounds[i].next = s_freeplays.next;
811 		s_playsounds[i].prev->next = &s_playsounds[i];
812 		s_playsounds[i].next->prev = &s_playsounds[i];
813 	}
814 
815 	// clear all the channels
816 	memset(channels, 0, sizeof(channels));
817 
818 	S_ClearBuffer ();
819 }
820 
821 /*
822 ==================
823 S_AddLoopSounds
824 
825 Entities with a ->sound field will generated looped sounds
826 that are automatically started, stopped, and merged together
827 as the entities are sent to the client
828 ==================
829 */
S_AddLoopSounds(void)830 void S_AddLoopSounds (void)
831 {
832 	int			i, j;
833 	int			sounds[MAX_EDICTS];
834 	int			left, right, left_total, right_total;
835 	channel_t	*ch;
836 	sfx_t		*sfx;
837 	sfxcache_t	*sc;
838 	int			num;
839 	entity_state_t	*ent;
840 
841 	if (cl_paused->value)
842 		return;
843 
844 	if (cls.state != ca_active)
845 		return;
846 
847 	if (!cl.sound_prepped)
848 		return;
849 
850 	for (i=0 ; i<cl.frame.num_entities ; i++)
851 	{
852 		num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
853 		ent = &cl_parse_entities[num];
854 		sounds[i] = ent->sound;
855 	}
856 
857 	for (i=0 ; i<cl.frame.num_entities ; i++)
858 	{
859 		if (!sounds[i])
860 			continue;
861 
862 		sfx = cl.sound_precache[sounds[i]];
863 		if (!sfx)
864 			continue;		// bad sound effect
865 		sc = sfx->cache;
866 		if (!sc)
867 			continue;
868 
869 		num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
870 		ent = &cl_parse_entities[num];
871 
872 		// find the total contribution of all sounds of this type
873 		S_SpatializeOrigin (ent->origin, 255.0, SOUND_LOOPATTENUATE,
874 			&left_total, &right_total);
875 		for (j=i+1 ; j<cl.frame.num_entities ; j++)
876 		{
877 			if (sounds[j] != sounds[i])
878 				continue;
879 			sounds[j] = 0;	// don't check this again later
880 
881 			num = (cl.frame.parse_entities + j)&(MAX_PARSE_ENTITIES-1);
882 			ent = &cl_parse_entities[num];
883 
884 			S_SpatializeOrigin (ent->origin, 255.0, SOUND_LOOPATTENUATE,
885 				&left, &right);
886 			left_total += left;
887 			right_total += right;
888 		}
889 
890 		if (left_total == 0 && right_total == 0)
891 			continue;		// not audible
892 
893 		// allocate a channel
894 		ch = S_PickChannel(0, 0);
895 		if (!ch)
896 			return;
897 
898 		if (left_total > 255)
899 			left_total = 255;
900 		if (right_total > 255)
901 			right_total = 255;
902 		ch->leftvol = left_total;
903 		ch->rightvol = right_total;
904 		ch->autosound = true;	// remove next frame
905 		ch->sfx = sfx;
906                 /*
907                  * PATCH: eliasm
908                  *
909                  * Sometimes, the sc->length argument can become 0,
910                  * and in that case we get a SIGFPE in the next
911                  * modulo operation. The workaround checks for this
912                  * situation and in that case, sets the pos and end
913                  * parameters to 0.
914                  *
915                  *   ch->pos = paintedtime % sc->length;
916                  *   ch->end = paintedtime + sc->length - ch->pos;
917                  */
918                 if( sc->length == 0 ) {
919                   ch->pos = 0;
920                   ch->end = 0;
921                 }
922                 else {
923 		ch->pos = paintedtime % sc->length;
924 		ch->end = paintedtime + sc->length - ch->pos;
925 	}
926 	}
927 }
928 
929 //=============================================================================
930 
931 /*
932 ============
933 S_RawSamples
934 
935 Cinematic streaming and voice over network
936 ============
937 */
S_RawSamples(int samples,int rate,int width,int channels,byte * data)938 void S_RawSamples (int samples, int rate, int width, int channels, byte *data)
939 {
940 	int		i;
941 	int		src, dst;
942 	float	scale;
943 
944 	if (!sound_started)
945 		return;
946 
947 	if (s_rawend < paintedtime)
948 		s_rawend = paintedtime;
949 	scale = (float)rate / dma.speed;
950 
951 //Com_Printf ("%i < %i < %i\n", soundtime, paintedtime, s_rawend);
952 	if (channels == 2 && width == 2)
953 	{
954 		if (scale == 1.0)
955 		{	// optimized case
956 			for (i=0 ; i<samples ; i++)
957 			{
958 				dst = s_rawend&(MAX_RAW_SAMPLES-1);
959 				s_rawend++;
960 				s_rawsamples[dst].left =
961 				    LittleShort(((short *)data)[i*2]) << 8;
962 				s_rawsamples[dst].right =
963 				    LittleShort(((short *)data)[i*2+1]) << 8;
964 			}
965 		}
966 		else
967 		{
968 			for (i=0 ; ; i++)
969 			{
970 				src = i*scale;
971 				if (src >= samples)
972 					break;
973 				dst = s_rawend&(MAX_RAW_SAMPLES-1);
974 				s_rawend++;
975 				s_rawsamples[dst].left =
976 				    LittleShort(((short *)data)[src*2]) << 8;
977 				s_rawsamples[dst].right =
978 				    LittleShort(((short *)data)[src*2+1]) << 8;
979 			}
980 		}
981 	}
982 	else if (channels == 1 && width == 2)
983 	{
984 		for (i=0 ; ; i++)
985 		{
986 			src = i*scale;
987 			if (src >= samples)
988 				break;
989 			dst = s_rawend&(MAX_RAW_SAMPLES-1);
990 			s_rawend++;
991 			s_rawsamples[dst].left =
992 			    LittleShort(((short *)data)[src]) << 8;
993 			s_rawsamples[dst].right =
994 			    LittleShort(((short *)data)[src]) << 8;
995 		}
996 	}
997 	else if (channels == 2 && width == 1)
998 	{
999 		for (i=0 ; ; i++)
1000 		{
1001 			src = i*scale;
1002 			if (src >= samples)
1003 				break;
1004 			dst = s_rawend&(MAX_RAW_SAMPLES-1);
1005 			s_rawend++;
1006 			s_rawsamples[dst].left =
1007 			    ((char *)data)[src*2] << 16;
1008 			s_rawsamples[dst].right =
1009 			    ((char *)data)[src*2+1] << 16;
1010 		}
1011 	}
1012 	else if (channels == 1 && width == 1)
1013 	{
1014 		for (i=0 ; ; i++)
1015 		{
1016 			src = i*scale;
1017 			if (src >= samples)
1018 				break;
1019 			dst = s_rawend&(MAX_RAW_SAMPLES-1);
1020 			s_rawend++;
1021 			s_rawsamples[dst].left =
1022 			    (((byte *)data)[src]-128) << 16;
1023 			s_rawsamples[dst].right = (((byte *)data)[src]-128) << 16;
1024 		}
1025 	}
1026 }
1027 
1028 //=============================================================================
1029 
1030 /*
1031 ============
1032 S_Update
1033 
1034 Called once each time through the main loop
1035 ============
1036 */
S_Update(vec3_t origin,vec3_t forward,vec3_t right,vec3_t up)1037 void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
1038 {
1039 	int			i;
1040 	int			total;
1041 	channel_t	*ch;
1042 	channel_t	*combine;
1043 
1044 	if (!sound_started)
1045 		return;
1046 
1047 	// if the laoding plaque is up, clear everything
1048 	// out to make sure we aren't looping a dirty
1049 	// dma buffer while loading
1050 	if (cls.disable_screen)
1051 	{
1052 		S_ClearBuffer ();
1053 		return;
1054 	}
1055 
1056 	// rebuild scale tables if volume is modified
1057 	if (s_volume->modified)
1058 		S_InitScaletable ();
1059 
1060 	VectorCopy(origin, listener_origin);
1061 	VectorCopy(forward, listener_forward);
1062 	VectorCopy(right, listener_right);
1063 	VectorCopy(up, listener_up);
1064 
1065 	combine = NULL;
1066 
1067 	// update spatialization for dynamic sounds
1068 	ch = channels;
1069 	for (i=0 ; i<MAX_CHANNELS; i++, ch++)
1070 	{
1071 		if (!ch->sfx)
1072 			continue;
1073 		if (ch->autosound)
1074 		{	// autosounds are regenerated fresh each frame
1075 			memset (ch, 0, sizeof(*ch));
1076 			continue;
1077 		}
1078 		S_Spatialize(ch);         // respatialize channel
1079 		if (!ch->leftvol && !ch->rightvol)
1080 		{
1081 			memset (ch, 0, sizeof(*ch));
1082 			continue;
1083 		}
1084 	}
1085 
1086 	// add loopsounds
1087 	S_AddLoopSounds ();
1088 
1089 	//
1090 	// debugging output
1091 	//
1092 	if (s_show->value)
1093 	{
1094 		total = 0;
1095 		ch = channels;
1096 		for (i=0 ; i<MAX_CHANNELS; i++, ch++)
1097 			if (ch->sfx && (ch->leftvol || ch->rightvol) )
1098 			{
1099 				Com_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name);
1100 				total++;
1101 			}
1102 
1103 		Com_Printf ("----(%i)---- painted: %i\n", total, paintedtime);
1104 	}
1105 
1106 // mix some sound
1107 	S_Update_();
1108 }
1109 
GetSoundtime(void)1110 void GetSoundtime(void)
1111 {
1112 	int		samplepos;
1113 	static	int		buffers;
1114 	static	int		oldsamplepos;
1115 	int		fullsamples;
1116 
1117 	fullsamples = dma.samples / dma.channels;
1118 
1119 // it is possible to miscount buffers if it has wrapped twice between
1120 // calls to S_Update.  Oh well.
1121 	samplepos = SNDDMA_GetDMAPos();
1122 
1123 	if (samplepos < oldsamplepos)
1124 	{
1125 		buffers++;					// buffer wrapped
1126 
1127 		if (paintedtime > 0x40000000)
1128 		{	// time to chop things off to avoid 32 bit limits
1129 			buffers = 0;
1130 			paintedtime = fullsamples;
1131 			S_StopAllSounds ();
1132 		}
1133 	}
1134 	oldsamplepos = samplepos;
1135 
1136 	soundtime = buffers*fullsamples + samplepos/dma.channels;
1137 }
1138 
1139 
S_Update_(void)1140 void S_Update_(void)
1141 {
1142 	unsigned        endtime;
1143 	int				samps;
1144 
1145 	if (!sound_started)
1146 		return;
1147 
1148 	SNDDMA_BeginPainting ();
1149 
1150 	if (!dma.buffer)
1151 		return;
1152 
1153 // Updates DMA time
1154 	GetSoundtime();
1155 
1156 // check to make sure that we haven't overshot
1157 	if (paintedtime < soundtime)
1158 	{
1159 		Com_DPrintf ("S_Update_ : overflow\n");
1160 		paintedtime = soundtime;
1161 	}
1162 
1163 // mix ahead of current position
1164 	endtime = soundtime + s_mixahead->value * dma.speed;
1165 //endtime = (soundtime + 4096) & ~4095;
1166 
1167 	// mix to an even submission block size
1168 	endtime = (endtime + dma.submission_chunk-1)
1169 		& ~(dma.submission_chunk-1);
1170 	samps = dma.samples >> (dma.channels-1);
1171 	if (endtime - soundtime > samps)
1172 		endtime = soundtime + samps;
1173 
1174 	S_PaintChannels (endtime);
1175 
1176 	SNDDMA_Submit ();
1177 }
1178 
1179 /*
1180 ===============================================================================
1181 
1182 console functions
1183 
1184 ===============================================================================
1185 */
1186 
S_Play(void)1187 void S_Play(void)
1188 {
1189 	int 	i;
1190 	char name[256];
1191 	sfx_t	*sfx;
1192 
1193 	i = 1;
1194 	while (i<Cmd_Argc())
1195 	{
1196 		if (!strrchr(Cmd_Argv(i), '.'))
1197 		{
1198 			strcpy(name, Cmd_Argv(i));
1199 			strcat(name, ".wav");
1200 		}
1201 		else
1202 			strcpy(name, Cmd_Argv(i));
1203 		sfx = S_RegisterSound(name);
1204 		S_StartSound(NULL, cl.playernum+1, 0, sfx, 1.0, 1.0, 0);
1205 		i++;
1206 	}
1207 }
1208 
S_SoundList(void)1209 void S_SoundList(void)
1210 {
1211 	int		i;
1212 	sfx_t	*sfx;
1213 	sfxcache_t	*sc;
1214 	int		size, total;
1215 
1216 	total = 0;
1217 	for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++)
1218 	{
1219 		if (!sfx->registration_sequence)
1220 			continue;
1221 		sc = sfx->cache;
1222 		if (sc)
1223 		{
1224 			size = sc->length*sc->width*(sc->stereo+1);
1225 			total += size;
1226 			if (sc->loopstart >= 0)
1227 				Com_Printf ("L");
1228 			else
1229 				Com_Printf (" ");
1230 			Com_Printf("(%2db) %6i : %s\n",sc->width*8,  size, sfx->name);
1231 		}
1232 		else
1233 		{
1234 			if (sfx->name[0] == '*')
1235 				Com_Printf("  placeholder : %s\n", sfx->name);
1236 			else
1237 				Com_Printf("  not loaded  : %s\n", sfx->name);
1238 		}
1239 	}
1240 	Com_Printf ("Total resident: %i\n", total);
1241 }
1242 
1243