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 "../qcommon/redblack.h"
24 #include "snd_loc.h"
25 
26 //FIXME OpenAL
27 #ifdef _WIN32
28 extern qboolean ActiveApp;
29 #endif
30 
31 void S_Play(void);
32 void S_SoundList_f (void);
33 void S_Update_(void);
34 void S_StopAllSounds(void);
35 
36 /* Factor to control attenuation of audio.
37 We'll divide all coordinates by this factor each time we update
38 the source positions. OpenAL does provide a cleaner way to do
39 this, but it changed recently. */
40 #define DISTANCE_FACTOR 50.0
41 
42 
43 // =======================================================================
44 // Internal sound data & structures
45 // =======================================================================
46 
47 // only begin attenuating sound volumes when outside the FULLVOLUME range
48 static int			s_registration_sequence;
49 
50 channel_t   channels[MAX_CHANNELS];
51 
52 static int			sound_started=0;
53 
54 dma_t		dma;
55 
56 vec3_t		listener_origin;
57 vec3_t		listener_forward;
58 vec3_t		listener_right;
59 vec3_t		listener_up;
60 
61 static qboolean	s_registering;
62 
63 static int	soundtime;		// sample PAIRS
64 int   		paintedtime; 	// sample PAIRS
65 
66 // during registration it is possible to have more sounds
67 // than could actually be referenced during gameplay,
68 // because we don't want to free anything until we are
69 // sure we won't need it.
70 #define		MAX_SFX		(MAX_SOUNDS*2)
71 static sfx_t		known_sfx[MAX_SFX];
72 static int			num_sfx;
73 
74 static struct rbtree *knownsounds;
75 
76 #define		MAX_PLAYSOUNDS	128
77 static playsound_t	s_playsounds[MAX_PLAYSOUNDS];
78 static playsound_t	s_freeplays;
79 playsound_t	s_pendingplays;
80 
81 static int			s_beginofs;
82 
83 cvar_t		*s_volume;
84 cvar_t		*s_testsound;
85 cvar_t		*s_loadas8bit;
86 cvar_t		*s_khz;
87 cvar_t		*s_primary;
88 
89 cvar_t		*s_openal_extensions;
90 cvar_t		*s_openal_eax;
91 
92 static cvar_t		*s_show;
93 static cvar_t		*s_mixahead;
94 static cvar_t		*s_ambient;
95 
96 cvar_t		*s_focusfree = &uninitialized_cvar;
97 //cvar_t		*s_dx8;
98 
99 
100 int		s_rawend;
101 portable_samplepair_t	s_rawsamples[MAX_RAW_SAMPLES];
102 
103 #ifdef USE_OPENAL
104 cvar_t		*s_openal_volume;
105 cvar_t		*s_openal_device;
106 static openal_listener_t	s_openal_listener;
107 static openal_channel_t		s_openal_channels[MAX_CHANNELS];
108 static int					s_openal_numChannels;
109 static int					s_openal_frameCount;
110 
111 #ifdef _WIN32
112 const GUID			DSPROPSETID_EAX20_ListenerProperties = {0x306a6a8, 0xb224, 0x11d2, {0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22}};
113 const GUID			DSPROPSETID_EAX20_BufferProperties = {0x306a6a7, 0xb224, 0x11d2, {0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22}};
114 #endif
115 
116 #endif
117 
118 
119 // ====================================================================
120 // User-setable variables
121 // ====================================================================
122 
123 
S_SoundInfo_f(void)124 void S_SoundInfo_f(void)
125 {
126 	if (!sound_started)
127 	{
128 		Com_Printf ("sound system not started\n", LOG_CLIENT);
129 		return;
130 	}
131 
132     Com_Printf("%5d stereo\n", LOG_CLIENT, dma.channels - 1);
133     Com_Printf("%5d samples\n", LOG_CLIENT, dma.samples);
134     Com_Printf("%5d samplepos\n", LOG_CLIENT, dma.samplepos);
135     Com_Printf("%5d samplebits\n", LOG_CLIENT, dma.samplebits);
136     Com_Printf("%5d submission_chunk\n", LOG_CLIENT, dma.submission_chunk);
137     Com_Printf("%5d speed\n", LOG_CLIENT, dma.speed);
138     Com_Printf("%p dma buffer\n", LOG_CLIENT, dma.buffer);
139 }
140 
141 #ifdef USE_OPENAL
S_OpenAL_AllocChannels(void)142 static void S_OpenAL_AllocChannels (void)
143 {
144 	openal_channel_t	*ch;
145 	int					i;
146 
147 	for (i = 0, ch = s_openal_channels; i < MAX_CHANNELS; i++, ch++)
148 	{
149 		qalGenSources(1, &ch->sourceNum);
150 
151 		if (qalGetError() != AL_NO_ERROR)
152 			break;
153 
154 		s_openal_numChannels++;
155 	}
156 }
157 #endif
158 
159 /*
160 ================
161 S_Init
162 ================
163 */
S_Init(int fullInit)164 void S_Init (int fullInit)
165 {
166 	cvar_t	*cv;
167 
168 	if (!cl_quietstartup->intvalue || developer->intvalue)
169 		Com_Printf("\n------- sound initialization -------\n", LOG_CLIENT|LOG_NOTICE);
170 
171 	knownsounds = rbinit ((int (EXPORT *)(const void *, const void *))strcmp, 0);
172 
173 	s_volume = Cvar_Get ("s_volume", "0.5", CVAR_ARCHIVE);
174 	s_khz = Cvar_Get ("s_khz", "22", CVAR_ARCHIVE);
175 	s_loadas8bit = Cvar_Get ("s_loadas8bit", "0", CVAR_ARCHIVE);
176 	s_mixahead = Cvar_Get ("s_mixahead", "0.2", CVAR_ARCHIVE);
177 	s_show = Cvar_Get ("s_show", "0", 0);
178 	s_ambient = Cvar_Get ("s_ambient", "1", 0);
179 	s_testsound = Cvar_Get ("s_testsound", "0", 0);
180 	s_primary = Cvar_Get ("s_primary", "0", CVAR_ARCHIVE);	// win32 specific
181 
182 	s_focusfree = Cvar_Get ("s_focusfree", "0", 0);
183 	//s_dx8 = Cvar_Get ("s_dx8", "0", CVAR_ARCHIVE);
184 
185 #ifdef USE_OPENAL
186 	s_openal_device = Cvar_Get ("s_openal_device", "", 0);
187 	s_openal_extensions = Cvar_Get ("s_openal_extensions", "1", 0);
188 	s_openal_eax = Cvar_Get ("s_openal_eax", "0", 0);
189 	s_openal_volume = Cvar_Get ("s_openal_volume", "1", 0);
190 #endif
191 
192 	s_volume = Cvar_Get ("s_volume", "0.5", CVAR_ARCHIVE);
193 	s_show = Cvar_Get ("s_show", "0", 0);
194 	s_ambient = Cvar_Get ("s_ambient", "1", 0);
195 
196 	cv = Cvar_Get ("s_initsound", "1", 0);
197 	if (!cv->intvalue)
198 		Com_Printf ("not initializing.\n", LOG_CLIENT|LOG_NOTICE);
199 	else
200 	{
201 		if (cv->intvalue == 2)
202 		{
203 #ifdef USE_OPENAL
204 			if (ALimp_Init ())
205 			{
206 				sound_started = 1;
207 
208 				Cmd_AddCommand("play", S_Play);
209 				Cmd_AddCommand("stopsound", S_StopAllSounds);
210 
211 				S_OpenAL_AllocChannels ();
212 				S_StopAllSounds ();	//inits freeplays
213 				S_StartLocalSound ("openalinit.wav");
214 			}
215 			else
216 			{
217 				Com_Printf ("OpenAL failed to initialize; no sound available\n", LOG_CLIENT);
218 			}
219 #else
220 			Com_Printf ("This binary was compiled without OpenAL support.\n", LOG_CLIENT);
221 #endif
222 		}
223 		else
224 		{
225 			if (!SNDDMA_Init(fullInit))
226 				return;
227 
228 			Cmd_AddCommand("play", S_Play);
229 			Cmd_AddCommand("stopsound", S_StopAllSounds);
230 			Cmd_AddCommand("soundlist", S_SoundList_f);
231 			Cmd_AddCommand("soundinfo", S_SoundInfo_f);
232 
233 			S_InitScaletable ();
234 
235 			sound_started = 1;
236 			num_sfx = 0;
237 
238 			soundtime = 0;
239 			paintedtime = 0;
240 
241 			if (!cl_quietstartup->intvalue || developer->intvalue)
242 				Com_Printf ("sound sampling rate: %i\n", LOG_CLIENT|LOG_NOTICE, dma.speed);
243 
244 			S_StopAllSounds ();
245 		}
246 	}
247 
248 	if (!cl_quietstartup->intvalue || developer->intvalue)
249 		Com_Printf("------------------------------------\n", LOG_CLIENT|LOG_NOTICE);
250 }
251 
252 
253 // =======================================================================
254 // Shutdown sound engine
255 // =======================================================================
256 
257 #ifdef USE_OPENAL
258 
S_OpenAL_FreeChannels(void)259 static void S_OpenAL_FreeChannels (void)
260 {
261 	openal_channel_t	*ch;
262 	int					i;
263 
264 	for (i = 0, ch = s_openal_channels; i < s_openal_numChannels; i++, ch++)
265 	{
266 		qalDeleteSources(1, &ch->sourceNum);
267 		memset(ch, 0, sizeof(*ch));
268 	}
269 
270 	s_openal_numChannels = 0;
271 }
272 
S_OpenAL_FreeSounds(void)273 void S_OpenAL_FreeSounds (void)
274 {
275 	sfx_t	*sfx;
276 	int		i;
277 
278 	// Stop all sounds
279 	S_StopAllSounds();
280 
281 	// Free all sounds
282 	for (i = 0; i < num_sfx; i++)
283 	{
284 		sfx = &known_sfx[i];
285 
286 		qalDeleteBuffers(1, &sfx->bufferNum);
287 	}
288 }
289 
290 #endif
291 
S_Shutdown(void)292 void S_Shutdown(void)
293 {
294 	int		i;
295 	sfx_t	*sfx;
296 
297 	if (!sound_started)
298 		return;
299 
300 #ifdef USE_OPENAL
301 	if (openal_active)
302 	{
303 		S_OpenAL_FreeSounds ();
304 		S_OpenAL_FreeChannels ();
305 	}
306 #endif
307 
308 	// free all sounds
309 	for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
310 	{
311 		if (!sfx->name[0])
312 			continue;
313 		if (sfx->cache)
314 			Z_Free (sfx->cache);
315 		rbdelete (sfx->name, knownsounds);
316 	}
317 
318 	memset (known_sfx, 0, sizeof(known_sfx));
319 
320 	rbdestroy (knownsounds);
321 
322 	num_sfx = 0;
323 	sound_started = 0;
324 
325 #ifdef USE_OPENAL
326 	if (openal_active)
327 	{
328 		ALimp_Shutdown ();
329 	}
330 	else
331 #endif
332 	{
333 		SNDDMA_Shutdown();
334 		Cmd_RemoveCommand("soundlist");
335 		Cmd_RemoveCommand("soundinfo");
336 	}
337 	Cmd_RemoveCommand("play");
338 	Cmd_RemoveCommand("stopsound");
339 }
340 
341 
342 // =======================================================================
343 // Load a sound
344 // =======================================================================
345 
346 /*
347 ==================
348 S_FindName
349 
350 ==================
351 */
S_FindName(char * name,qboolean create)352 sfx_t *S_FindName (char *name, qboolean create)
353 {
354 	int		i;
355 	sfx_t	*sfx;
356 	void	**data;
357 
358 	if (!name)
359 		Com_Error (ERR_FATAL, "S_FindName: NULL\n");
360 
361 	// see if already loaded
362 	/*for (i=0 ; i < num_sfx ; i++)
363 		if (!strcmp(known_sfx[i].name, name))
364 		{
365 			return &known_sfx[i];
366 		}*/
367 
368 	data = rbfind (name, knownsounds);
369 	if (data)
370 	{
371 		sfx = *(sfx_t **)data;
372 		return sfx;
373 	}
374 
375 	if (!name[0])
376 		Com_Error (ERR_FATAL, "S_FindName: empty name\n");
377 
378 	if (!create)
379 		return NULL;
380 
381 	// find a free sfx
382 	for (i=0 ; i < num_sfx ; i++)
383 		if (!known_sfx[i].name[0])
384 //			registration_sequence < s_registration_sequence)
385 			break;
386 
387 	if (i == num_sfx)
388 	{
389 		if (num_sfx == MAX_SFX)
390 			Com_Error (ERR_FATAL, "S_FindName: out of sfx_t");
391 		num_sfx++;
392 	}
393 
394 	if (strlen(name) >= MAX_QPATH-1)
395 		Com_Error (ERR_FATAL, "Sound name too long: %s", name);
396 
397 	sfx = &known_sfx[i];
398 
399 	sfx->cache = NULL;
400 	sfx->truename = NULL;
401 	strcpy (sfx->name, name);
402 	sfx->registration_sequence = s_registration_sequence;
403 
404 #ifdef USE_OPENAL
405 	sfx->loaded = false;
406 	sfx->samples = 0;
407 	sfx->rate = 0;
408 	sfx->format = 0;
409 	sfx->bufferNum = 0;
410 #endif
411 
412 	data = rbsearch (sfx->name, knownsounds);
413 	*data = sfx;
414 
415 	return sfx;
416 }
417 
418 
419 /*
420 ==================
421 S_AliasName
422 
423 ==================
424 */
S_AliasName(char * aliasname,char * truename)425 sfx_t *S_AliasName (char *aliasname, char *truename)
426 {
427 	sfx_t	*sfx;
428 	void	**data;
429 	int		i;
430 
431 	//s = Z_TagMalloc (MAX_QPATH, TAGMALLOC_CLIENT_SFX);
432 	//strcpy (s, truename);
433 
434 	// find a free sfx
435 	for (i=0 ; i < num_sfx ; i++)
436 		if (!known_sfx[i].name[0])
437 			break;
438 
439 	if (i == num_sfx)
440 	{
441 		if (num_sfx == MAX_SFX)
442 			Com_Error (ERR_FATAL, "S_FindName: out of sfx_t");
443 		num_sfx++;
444 	}
445 
446 	sfx = &known_sfx[i];
447 	//memset (sfx, 0, sizeof(*sfx));
448 	sfx->cache = NULL;
449 
450 #ifdef USE_OPENAL
451 	sfx->loaded = false;
452 	sfx->samples = 0;
453 	sfx->rate = 0;
454 	sfx->format = 0;
455 	sfx->bufferNum = 0;
456 #endif
457 
458 	strcpy (sfx->name, aliasname);
459 	sfx->registration_sequence = s_registration_sequence;
460 	sfx->truename = CopyString (truename, TAGMALLOC_CLIENT_SFX);
461 
462 	data = rbsearch (sfx->name, knownsounds);
463 	*data = sfx;
464 
465 	return sfx;
466 }
467 
468 
469 /*
470 =====================
471 S_BeginRegistration
472 
473 =====================
474 */
S_BeginRegistration(void)475 void S_BeginRegistration (void)
476 {
477 	s_registration_sequence++;
478 	s_registering = true;
479 }
480 
481 /*
482 ==================
483 S_RegisterSound
484 
485 ==================
486 */
S_RegisterSound(char * name)487 sfx_t *S_RegisterSound (char *name)
488 {
489 	sfx_t	*sfx;
490 
491 	if (!sound_started)
492 		return NULL;
493 
494 	sfx = S_FindName (name, true);
495 	sfx->registration_sequence = s_registration_sequence;
496 
497 	if (!s_registering)
498 	{
499 #ifdef USE_OPENAL
500 		if (openal_active)
501 		{
502 			S_OpenAL_LoadSound (sfx);
503 		}
504 		else
505 #endif
506 		{
507 			S_LoadSound (sfx);
508 		}
509 	}
510 
511 	return sfx;
512 }
513 
514 
515 /*
516 =====================
517 S_EndRegistration
518 
519 =====================
520 */
S_EndRegistration(void)521 void S_EndRegistration (void)
522 {
523 	int		i;
524 	sfx_t	*sfx;
525 	int		size;
526 
527 	// free any sounds not from this registration sequence
528 	for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
529 	{
530 		if (!sfx->name[0])
531 			continue;
532 
533 		if (sfx->registration_sequence != s_registration_sequence)
534 		{	// don't need this sound
535 			if (sfx->cache)				// it is possible to have a leftover
536 				Z_Free (sfx->cache);	// from a server that didn't finish loading
537 			if (sfx->truename)
538 				Z_Free (sfx->truename); // memleak fix from echon
539 			rbdelete (sfx->name, knownsounds);
540 			sfx->cache = NULL;
541 			sfx->name[0] = 0;
542 #ifdef USE_OPENAL
543 			sfx->loaded = false;
544 #endif
545 			//memset (sfx, 0, sizeof(*sfx));
546 		}
547 		else
548 		{	// make sure it is paged in
549 #ifdef USE_OPENAL
550 			if (openal_active)
551 				continue;
552 #endif
553 
554 			if (sfx->cache)
555 			{
556 				size = sfx->cache->length*sfx->cache->width;
557 				Com_PageInMemory ((byte *)sfx->cache, size);
558 			}
559 		}
560 	}
561 
562 	// load everything in
563 	for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
564 	{
565 		if (!sfx->name[0])
566 			continue;
567 
568 #ifdef USE_OPENAL
569 		if (openal_active)
570 			S_OpenAL_LoadSound (sfx);
571 		else
572 #endif
573 			S_LoadSound (sfx);
574 	}
575 
576 	s_registering = false;
577 }
578 
579 
580 //=============================================================================
581 
582 /*
583 =================
584 S_PickChannel
585 =================
586 */
S_PickChannel(int entnum,int entchannel)587 channel_t *S_PickChannel(int entnum, int entchannel)
588 {
589     int			ch_idx;
590     int			first_to_die;
591     int			life_left;
592 	channel_t	*ch;
593 
594 	if (entchannel < 0)
595 		Com_Error (ERR_DROP, "S_PickChannel: entchannel<0");
596 
597 // Check for replacement sound, or find the best one to replace
598     first_to_die = -1;
599     life_left = 0x7fffffff;
600     for (ch_idx=0 ; ch_idx < MAX_CHANNELS ; ch_idx++)
601     {
602 		if (entchannel != 0		// channel 0 never overrides
603 		&& channels[ch_idx].entnum == entnum
604 		&& channels[ch_idx].entchannel == entchannel)
605 		{	// always override sound from same entity
606 			first_to_die = ch_idx;
607 			break;
608 		}
609 
610 		// don't let monster sounds override player sounds
611 		if (channels[ch_idx].entnum == cl.playernum+1 && entnum != cl.playernum+1 && channels[ch_idx].sfx)
612 			continue;
613 
614 		if (channels[ch_idx].end - paintedtime < life_left)
615 		{
616 			life_left = channels[ch_idx].end - paintedtime;
617 			first_to_die = ch_idx;
618 		}
619    }
620 
621 	if (first_to_die == -1)
622 		return NULL;
623 
624 	ch = &channels[first_to_die];
625 	memset (ch, 0, sizeof(*ch));
626 
627     return ch;
628 }
629 
630 /*
631 =================
632 S_SpatializeOrigin
633 
634 Used for spatializing channels and autosounds
635 =================
636 */
S_SpatializeOrigin(vec3_t origin,float master_vol,float dist_mult,int * left_vol,int * right_vol)637 void S_SpatializeOrigin (vec3_t origin, float master_vol, float dist_mult, int *left_vol, int *right_vol)
638 {
639     vec_t		dot;
640     vec_t		dist;
641     vec_t		lscale, rscale, scale;
642     vec3_t		source_vec;
643 
644 	if (cls.state != ca_active)
645 	{
646 		*left_vol = *right_vol = 255;
647 		return;
648 	}
649 
650 // calculate stereo seperation and distance attenuation
651 	VectorSubtract(origin, listener_origin, source_vec);
652 
653 	dist = VectorNormalize(source_vec);
654 	dist -= SOUND_FULLVOLUME;
655 
656 	if (FLOAT_LT_ZERO(dist))
657 		dist = 0;			// close enough to be at full volume
658 
659 	dist *= dist_mult;		// different attenuation levels
660 
661 	dot = DotProduct(listener_right, source_vec);
662 
663 	if (dma.channels == 1 || !dist_mult)
664 	{ // no attenuation = no spatialization
665 		rscale = 1.0f;
666 		lscale = 1.0f;
667 	}
668 	else
669 	{
670 		rscale = 0.5f * (1.0f + dot);
671 		lscale = 0.5f * (1.0f - dot);
672 	}
673 
674 	// add in distance effect
675 	scale = (1.0f - dist) * rscale;
676 	*right_vol = (int) (master_vol * scale);
677 	if (*right_vol < 0)
678 		*right_vol = 0;
679 
680 	scale = (1.0f - dist) * lscale;
681 	*left_vol = (int) (master_vol * scale);
682 	if (*left_vol < 0)
683 		*left_vol = 0;
684 }
685 
Snd_GetEntityOrigin(int entNum,vec3_t origin)686 void Snd_GetEntityOrigin (int entNum, vec3_t origin)
687 {
688 	if (entNum == cl.playernum + 1)
689 		FastVectorCopy (listener_origin, *origin);
690 	else
691 		CL_GetEntityOrigin (entNum, origin);
692 }
693 
694 /*
695 =================
696 S_Spatialize
697 =================
698 */
S_Spatialize(channel_t * ch)699 void S_Spatialize(channel_t *ch)
700 {
701 	vec3_t		origin;
702 
703 	// anything coming from the view entity will always be full volume
704 	if (ch->entnum == cl.playernum+1)
705 	{
706 		ch->leftvol = ch->master_vol;
707 		ch->rightvol = ch->master_vol;
708 		return;
709 	}
710 
711 	if (ch->fixed_origin)
712 	{
713 		FastVectorCopy (ch->origin, origin);
714 	}
715 	else
716 		Snd_GetEntityOrigin (ch->entnum, origin);
717 
718 	S_SpatializeOrigin (origin, (float)ch->master_vol, ch->dist_mult, &ch->leftvol, &ch->rightvol);
719 }
720 
721 
722 /*
723 =================
724 S_AllocPlaysound
725 =================
726 */
S_AllocPlaysound(void)727 playsound_t *S_AllocPlaysound (void)
728 {
729 	playsound_t	*ps;
730 
731 	ps = s_freeplays.next;
732 	if (ps == &s_freeplays)
733 		return NULL;		// no free playsounds
734 
735 	// unlink from freelist
736 	ps->prev->next = ps->next;
737 	ps->next->prev = ps->prev;
738 
739 	return ps;
740 }
741 
742 
743 /*
744 =================
745 S_FreePlaysound
746 =================
747 */
S_FreePlaysound(playsound_t * ps)748 void S_FreePlaysound (playsound_t *ps)
749 {
750 	// unlink from channel
751 	ps->prev->next = ps->next;
752 	ps->next->prev = ps->prev;
753 
754 	// add to free list
755 	ps->next = s_freeplays.next;
756 	s_freeplays.next->prev = ps;
757 	ps->prev = &s_freeplays;
758 	s_freeplays.next = ps;
759 }
760 
761 
762 
763 /*
764 ===============
765 S_IssuePlaysound
766 
767 Take the next playsound and begin it on the channel
768 This is never called directly by S_Play*, but only
769 by the update loop.
770 ===============
771 */
S_IssuePlaysound(playsound_t * ps)772 void S_IssuePlaysound (playsound_t *ps)
773 {
774 	channel_t	*ch;
775 	sfxcache_t	*sc;
776 
777 	if (s_show->intvalue)
778 		Com_Printf ("Issue %i\n", LOG_CLIENT, ps->begin);
779 	// pick a channel to play on
780 	ch = S_PickChannel(ps->entnum, ps->entchannel);
781 	if (!ch)
782 	{
783 		S_FreePlaysound (ps);
784 		return;
785 	}
786 
787 	// spatialize
788 	if (ps->attenuation == ATTN_STATIC)
789 		ch->dist_mult = ps->attenuation * 0.001f;
790 	else
791 		ch->dist_mult = ps->attenuation * 0.0005f;
792 	ch->master_vol = (int)ps->volume;
793 	ch->entnum = ps->entnum;
794 	ch->entchannel = ps->entchannel;
795 	ch->sfx = ps->sfx;
796 	FastVectorCopy (ps->origin, ch->origin);
797 	ch->fixed_origin = ps->fixed_origin;
798 
799 	S_Spatialize(ch);
800 
801 	ch->pos = 0;
802 	sc = S_LoadSound (ch->sfx);
803     ch->end = paintedtime + sc->length;
804 
805 	// free the playsound
806 	S_FreePlaysound (ps);
807 }
808 
S_RegisterSexedSound(char * base,int entnum)809 struct sfx_s *S_RegisterSexedSound (char *base, int entnum)
810 {
811 	int				n;
812 	int				len;
813 	char			*p;
814 	struct sfx_s	*sfx;
815 //	FILE			*f;
816 	char			model[MAX_QPATH];
817 	char			sexedFilename[MAX_QPATH];
818 	char			maleFilename[MAX_QPATH];
819 
820 	// determine what model the client is using
821 	model[0] = 0;
822 	//n = CS_PLAYERSKINS + ent->number - 1;
823 	n = CS_PLAYERSKINS + entnum - 1;
824 	if (cl.configstrings[n][0])
825 	{
826 		p = strchr(cl.configstrings[n], '\\');
827 		if (p)
828 		{
829 			p += 1;
830 			Q_strncpy(model, p, sizeof(model)-1);
831 			p = strchr(model, '/');
832 			if (p)
833 				p[0] = 0;
834 		}
835 	}
836 
837 	// if we can't figure it out, they're male
838 	if (!model[0])
839 		strcpy(model, "male");
840 
841 	// see if we already know of the model specific sound
842 	Com_sprintf (sexedFilename, sizeof(sexedFilename), "#players/%s/%s", model, base+1);
843 	sfx = S_FindName (sexedFilename, false);
844 
845 	if (!sfx)
846 	{
847 		// no, so see if it exists
848 		//FS_FOpenFile (&sexedFilename[1], &f, false);
849 		len = FS_LoadFile (&sexedFilename[1], NULL);
850 		if (len != -1)
851 		{
852 			// yes, close the file and register it
853 			//FS_FCloseFile (f);
854 			sfx = S_RegisterSound (sexedFilename);
855 		}
856 		else
857 		{
858 			// no, revert to the male sound in the pak0.pak
859 			Com_sprintf (maleFilename, sizeof(maleFilename), "player/male/%s", base+1);
860 			sfx = S_AliasName (sexedFilename, maleFilename);
861 		}
862 	}
863 
864 	return sfx;
865 }
866 
867 
868 // =======================================================================
869 // Start a sound effect
870 // =======================================================================
871 
872 
873 /*
874 ====================
875 S_StartSound
876 
877 Validates the parms and ques the sound up
878 if pos is NULL, the sound will be dynamically sourced from the entity
879 Entchannel 0 will never override a playing sound
880 ====================
881 */
882 #ifdef USE_OPENAL
S_OpenAL_StartSound(const vec3_t position,int entNum,int entChannel,sfx_t * sfx,float volume,float attenuation,int timeOfs)883 void S_OpenAL_StartSound (const vec3_t position, int entNum, int entChannel, sfx_t *sfx, float volume, float attenuation, int timeOfs)
884 {
885 	playsound_t *ps, *sort;
886 
887 	if (!sound_started)
888 		return;
889 
890 	if (!sfx)
891 		return;
892 
893 	if (sfx->name[0] == '*')
894 		sfx = S_RegisterSexedSound(sfx->name, entNum);
895 
896 	// Make sure the sound is loaded
897 	if (!S_OpenAL_LoadSound(sfx))
898 		return;
899 
900 	// Allocate a playSound
901 	ps = S_AllocPlaysound ();
902 	if (!ps)
903 	{
904 		if (sfx->name[0] == '#')
905 			Com_DPrintf("Dropped sound %s\n", &sfx->name[1]);
906 		else
907 			Com_DPrintf("Dropped sound sound/%s\n", sfx->name);
908 
909 		return;
910 	}
911 
912 	volume *= volume;
913 
914 	ps->sfx = sfx;
915 	ps->entnum = entNum;
916 	ps->entchannel = entChannel;
917 
918 	if (position)
919 	{
920 		ps->fixed_origin = true;
921 		FastVectorCopy (*position, ps->origin);
922 	}
923 	else
924 		ps->fixed_origin = false;
925 
926 	ps->volume = volume;
927 	ps->attenuation = attenuation;
928 	ps->begin = cl.time + timeOfs;
929 
930 	// Sort into the pending playSounds list
931 	for (sort = s_pendingplays.next; sort != &s_pendingplays&& sort->begin < ps->begin; sort = sort->next)
932 		;
933 
934 	ps->next = sort;
935 	ps->prev = sort->prev;
936 
937 	ps->next->prev = ps;
938 	ps->prev->next = ps;
939 }
940 #endif
941 
S_StartSound(vec3_t origin,int entnum,int entchannel,sfx_t * sfx,float fvol,float attenuation,float timeofs)942 void S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float timeofs)
943 {
944 	sfxcache_t	*sc;
945 	int			vol;
946 	playsound_t	*ps, *sort;
947 	int			start;
948 
949 #ifdef USE_OPENAL
950 	if (openal_active)
951 	{
952 		S_OpenAL_StartSound (origin, entnum, entchannel, sfx, fvol, attenuation, (int)(timeofs * 1000.0));
953 		return;
954 	}
955 #endif
956 
957 	if (!sound_started)
958 		return;
959 
960 	if (!sfx)
961 		return;
962 
963 	if (sfx->name[0] == '*')
964 		sfx = S_RegisterSexedSound(sfx->name, entnum);
965 
966 	//Com_DPrintf ("S_StartSound: %s\n", sfx->name);
967 
968 	// make sure the sound is loaded
969 	sc = S_LoadSound (sfx);
970 	if (!sc)
971 		return;		// couldn't load the sound's data
972 
973 	vol = (int)(fvol*255);
974 
975 	// make the playsound_t
976 	ps = S_AllocPlaysound ();
977 	if (!ps)
978 		return;
979 
980 	if (origin)
981 	{
982 		FastVectorCopy (*origin, ps->origin);
983 		ps->fixed_origin = true;
984 	}
985 	else
986 		ps->fixed_origin = false;
987 
988 	ps->entnum = entnum;
989 	ps->entchannel = entchannel;
990 	ps->attenuation = attenuation;
991 	ps->sfx = sfx;
992 
993 	// drift s_beginofs
994 	start = (int)(cl.frame.servertime * 0.001f * dma.speed + s_beginofs);
995 	if (start < paintedtime)
996 	{
997 		start = paintedtime;
998 		s_beginofs = (int)(start - (cl.frame.servertime * 0.001f * dma.speed));
999 	}
1000 	else if (start > paintedtime + 0.3f * dma.speed)
1001 	{
1002 		start = (int)(paintedtime + 0.1f * dma.speed);
1003 		s_beginofs = (int)(start - (cl.frame.servertime * 0.001f * dma.speed));
1004 	}
1005 	else
1006 	{
1007 		s_beginofs-=10;
1008 	}
1009 
1010 	if (!timeofs)
1011 		ps->begin = paintedtime;
1012 	else
1013 		ps->begin = (int)(start + timeofs * dma.speed);
1014 
1015 	ps->volume = fvol*255;
1016 
1017 	// sort into the pending sound list
1018 	for (sort = s_pendingplays.next ;
1019 		sort != &s_pendingplays && sort->begin < ps->begin ;
1020 		sort = sort->next)
1021 			;
1022 
1023 	ps->next = sort;
1024 	ps->prev = sort->prev;
1025 
1026 	ps->next->prev = ps;
1027 	ps->prev->next = ps;
1028 }
1029 
1030 
1031 /*
1032 ==================
1033 S_StartLocalSound
1034 ==================
1035 */
S_StartLocalSound(char * sound)1036 void S_StartLocalSound (char *sound)
1037 {
1038 	sfx_t	*sfx;
1039 
1040 	if (!sound_started)
1041 		return;
1042 
1043 	sfx = S_RegisterSound (sound);
1044 	if (!sfx)
1045 	{
1046 		Com_Printf ("S_StartLocalSound: can't cache %s\n", LOG_CLIENT, sound);
1047 		return;
1048 	}
1049 
1050 	//r1: don't use attenuation calculations on local sounds
1051 	S_StartSound (NULL, cl.playernum + 1, 0, sfx, 1, ATTN_NONE, 0);
1052 }
1053 
1054 
1055 /*
1056 ==================
1057 S_ClearBuffer
1058 ==================
1059 */
S_ClearBuffer(void)1060 void S_ClearBuffer (void)
1061 {
1062 	int		clear;
1063 
1064 	if (!sound_started)
1065 		return;
1066 
1067 #ifdef USE_OPENAL
1068 	if (openal_active)
1069 	{
1070 		return;
1071 	}
1072 #endif
1073 
1074 	s_rawend = 0;
1075 
1076 	if (dma.samplebits == 8)
1077 		clear = 0x80;
1078 	else
1079 		clear = 0;
1080 
1081 	SNDDMA_BeginPainting ();
1082 	if (dma.buffer)
1083 		memset(dma.buffer, clear, dma.samples * dma.samplebits/8);
1084 	SNDDMA_Submit ();
1085 }
1086 
1087 #ifdef USE_OPENAL
S_OpenAL_StopChannel(openal_channel_t * ch)1088 static void S_OpenAL_StopChannel (openal_channel_t *ch)
1089 {
1090 	ch->sfx = NULL;
1091 
1092 	qalSourceStop(ch->sourceNum);
1093 	qalSourcei(ch->sourceNum, AL_BUFFER, 0);
1094 }
1095 #endif
1096 
1097 /*
1098 ==================
1099 S_StopAllSounds
1100 ==================
1101 */
S_StopAllSounds(void)1102 void S_StopAllSounds(void)
1103 {
1104 	int		i;
1105 
1106 	if (!sound_started)
1107 		return;
1108 
1109 	// clear all the playsounds
1110 	memset(s_playsounds, 0, sizeof(s_playsounds));
1111 	s_freeplays.next = s_freeplays.prev = &s_freeplays;
1112 	s_pendingplays.next = s_pendingplays.prev = &s_pendingplays;
1113 
1114 	for (i=0 ; i<MAX_PLAYSOUNDS ; i++)
1115 	{
1116 		s_playsounds[i].prev = &s_freeplays;
1117 		s_playsounds[i].next = s_freeplays.next;
1118 		s_playsounds[i].prev->next = &s_playsounds[i];
1119 		s_playsounds[i].next->prev = &s_playsounds[i];
1120 	}
1121 
1122 #ifdef USE_OPENAL
1123 	if (openal_active)
1124 	{
1125 		openal_channel_t	*ch;
1126 
1127 		// Stop all the channels
1128 		for (i = 0, ch = s_openal_channels; i < s_openal_numChannels; i++, ch++)
1129 		{
1130 			if (!ch->sfx)
1131 				continue;
1132 
1133 			S_OpenAL_StopChannel(ch);
1134 		}
1135 
1136 		// Reset frame count
1137 		s_openal_frameCount = 0;
1138 	}
1139 #endif
1140 
1141 	// clear all the channels
1142 	memset(channels, 0, sizeof(channels));
1143 
1144 	S_ClearBuffer ();
1145 }
1146 
1147 /*
1148 ==================
1149 S_AddLoopSounds
1150 
1151 Entities with a ->sound field will generated looped sounds
1152 that are automatically started, stopped, and merged together
1153 as the entities are sent to the client
1154 ==================
1155 */
S_AddLoopSounds(void)1156 void S_AddLoopSounds (void)
1157 {
1158 	int			i, j;
1159 	int			sounds[MAX_EDICTS];
1160 	int			left, right, left_total, right_total;
1161 	channel_t	*ch;
1162 	sfx_t		*sfx;
1163 	sfxcache_t	*sc;
1164 	int			num;
1165 	entity_state_t	*ent;
1166 	vec3_t		origin;
1167 
1168 	if (cl_paused->intvalue)
1169 		return;
1170 
1171 	if (cls.state != ca_active)
1172 		return;
1173 
1174 	if (!cl.sound_prepped)
1175 		return;
1176 
1177 	for (i=0 ; i<cl.frame.num_entities ; i++)
1178 	{
1179 		num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
1180 		ent = &cl_parse_entities[num];
1181 		sounds[i] = ent->sound;
1182 	}
1183 
1184 	for (i=0 ; i<cl.frame.num_entities ; i++)
1185 	{
1186 		if (!sounds[i])
1187 			continue;
1188 
1189 		sfx = cl.sound_precache[sounds[i]];
1190 		if (!sfx)
1191 			continue;		// bad sound effect
1192 
1193 		sc = sfx->cache;
1194 		if (!sc)
1195 			continue;
1196 
1197 		num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
1198 		ent = &cl_parse_entities[num];
1199 
1200 		//cmodel sound fix
1201 		/*if (ent->solid == 31)
1202 		{
1203 			cmodel_t	*model;
1204 
1205 			model = cl.model_clip[ent->modelindex];
1206 
1207 			//not loaded (deferred?)
1208 			if (!model)
1209 				continue;
1210 
1211 			origin[0] = ent->origin[0]+0.5f*(model->mins[0]+model->maxs[0]);
1212 			origin[1] = ent->origin[1]+0.5f*(model->mins[1]+model->maxs[1]);
1213 			origin[2] = ent->origin[2]+0.5f*(model->mins[2]+model->maxs[2]);
1214 		}
1215 		else
1216 		{
1217 			VectorCopy (ent->origin, origin);
1218 		}*/
1219 		Snd_GetEntityOrigin (ent->number, origin);
1220 
1221 		// find the total contribution of all sounds of this type
1222 		S_SpatializeOrigin (origin, 255.0f, SOUND_LOOPATTENUATE,
1223 			&left_total, &right_total);
1224 
1225 		for (j=i+1 ; j<cl.frame.num_entities ; j++)
1226 		{
1227 			if (sounds[j] != sounds[i])
1228 				continue;
1229 			sounds[j] = 0;	// don't check this again later
1230 
1231 			num = (cl.frame.parse_entities + j)&(MAX_PARSE_ENTITIES-1);
1232 			ent = &cl_parse_entities[num];
1233 
1234 			S_SpatializeOrigin (ent->origin, 255.0f, SOUND_LOOPATTENUATE,
1235 				&left, &right);
1236 			left_total += left;
1237 			right_total += right;
1238 		}
1239 
1240 		if (left_total == 0 && right_total == 0)
1241 			continue;		// not audible
1242 
1243 		// allocate a channel
1244 		ch = S_PickChannel(0, 0);
1245 		if (!ch)
1246 			return;
1247 
1248 		if (left_total > 255)
1249 			left_total = 255;
1250 		if (right_total > 255)
1251 			right_total = 255;
1252 		ch->leftvol = left_total;
1253 		ch->rightvol = right_total;
1254 		ch->autosound = true;	// remove next frame
1255 		ch->sfx = sfx;
1256 		ch->pos = paintedtime % sc->length;
1257 		ch->end = paintedtime + sc->length - ch->pos;
1258 	}
1259 }
1260 
1261 //=============================================================================
1262 
1263 /*
1264 ============
1265 S_RawSamples
1266 
1267 Cinematic streaming and voice over network
1268 ============
1269 */
S_RawSamples(int samples,int rate,int width,int channels,byte * data)1270 void S_RawSamples (int samples, int rate, int width, int channels, byte *data)
1271 {
1272 	int		i;
1273 	int		src, dst;
1274 	float	scale;
1275 
1276 	if (!sound_started)
1277 		return;
1278 
1279 #ifdef USE_OPENAL
1280 	if (openal_active)
1281 		return;
1282 #endif
1283 
1284 	if (s_rawend < paintedtime)
1285 		s_rawend = paintedtime;
1286 	scale = (float)rate / dma.speed;
1287 
1288 //Com_Printf ("%i < %i < %i\n", soundtime, paintedtime, s_rawend);
1289 	if (channels == 2 && width == 2)
1290 	{
1291 		if (scale == 1.0f)
1292 		{	// optimized case
1293 			for (i=0 ; i<samples ; i++)
1294 			{
1295 				dst = s_rawend&(MAX_RAW_SAMPLES-1);
1296 				s_rawend++;
1297 				s_rawsamples[dst].left =
1298 				    LittleShort(((int16 *)data)[i*2]) << 8;
1299 				s_rawsamples[dst].right =
1300 				    LittleShort(((int16 *)data)[i*2+1]) << 8;
1301 			}
1302 		}
1303 		else
1304 		{
1305 			for (i=0 ; ; i++)
1306 			{
1307 				src = (int)(i*scale);
1308 				if (src >= samples)
1309 					break;
1310 				dst = s_rawend&(MAX_RAW_SAMPLES-1);
1311 				s_rawend++;
1312 				s_rawsamples[dst].left =
1313 				    LittleShort(((int16 *)data)[src*2]) << 8;
1314 				s_rawsamples[dst].right =
1315 				    LittleShort(((int16 *)data)[src*2+1]) << 8;
1316 			}
1317 		}
1318 	}
1319 	else if (channels == 1 && width == 2)
1320 	{
1321 		for (i=0 ; ; i++)
1322 		{
1323 			src = (int)(i*scale);
1324 			if (src >= samples)
1325 				break;
1326 			dst = s_rawend&(MAX_RAW_SAMPLES-1);
1327 			s_rawend++;
1328 			s_rawsamples[dst].left =
1329 			    LittleShort(((int16 *)data)[src]) << 8;
1330 			s_rawsamples[dst].right =
1331 			    LittleShort(((int16 *)data)[src]) << 8;
1332 		}
1333 	}
1334 	else if (channels == 2 && width == 1)
1335 	{
1336 		for (i=0 ; ; i++)
1337 		{
1338 			src = (int)(i*scale);
1339 			if (src >= samples)
1340 				break;
1341 			dst = s_rawend&(MAX_RAW_SAMPLES-1);
1342 			s_rawend++;
1343 			s_rawsamples[dst].left =
1344 			    ((char *)data)[src*2] << 16;
1345 			s_rawsamples[dst].right =
1346 			    ((char *)data)[src*2+1] << 16;
1347 		}
1348 	}
1349 	else if (channels == 1 && width == 1)
1350 	{
1351 		for (i=0 ; ; i++)
1352 		{
1353 			src = (int)(i*scale);
1354 			if (src >= samples)
1355 				break;
1356 			dst = s_rawend&(MAX_RAW_SAMPLES-1);
1357 			s_rawend++;
1358 			s_rawsamples[dst].left =
1359 			    (((byte *)data)[src]-128) << 16;
1360 			s_rawsamples[dst].right = (((byte *)data)[src]-128) << 16;
1361 		}
1362 	}
1363 }
1364 
1365 /*
1366  =================
1367  S_FreeChannels
1368  =================
1369 */
1370 #ifdef USE_OPENAL
S_OpenAL_PlayChannel(openal_channel_t * ch,sfx_t * sfx)1371 static void S_OpenAL_PlayChannel (openal_channel_t *ch, sfx_t *sfx)
1372 {
1373 	ch->sfx = sfx;
1374 
1375 	qalSourcei(ch->sourceNum, AL_BUFFER, sfx->bufferNum);
1376 	qalSourcei(ch->sourceNum, AL_LOOPING, ch->loopSound);
1377 	qalSourcei(ch->sourceNum, AL_SOURCE_RELATIVE, AL_FALSE);
1378 	qalSourcePlay(ch->sourceNum);
1379 }
1380 
S_OpenAL_PickChannel(int entNum,int entChannel)1381 openal_channel_t *S_OpenAL_PickChannel (int entNum, int entChannel)
1382 {
1383 	openal_channel_t	*ch;
1384 	int					i;
1385 	int					firstToDie = -1;
1386 	int					oldestTime = cl.time;
1387 
1388 	if (entNum < 0 || entChannel < 0)
1389 		Com_Error (ERR_DROP, "S_PickChannel: bad entNum");
1390 
1391 	for (i = 0, ch = s_openal_channels; i < s_openal_numChannels; i++, ch++)
1392 	{
1393 		// Don't let game sounds override streaming sounds
1394 		if (ch->streaming)
1395 			continue;
1396 
1397 		// Check if this channel is active
1398 		if (!ch->sfx)
1399 		{
1400 			// Free channel
1401 			firstToDie = i;
1402 			break;
1403 		}
1404 
1405 		// Channel 0 never overrides
1406 		if (entChannel != 0 && (ch->entNum == entNum && ch->entChannel == entChannel))
1407 		{
1408 			// Always override sound from same entity
1409 			firstToDie = i;
1410 			break;
1411 		}
1412 
1413 		// Don't let monster sounds override player sounds
1414 		if (entNum != cl.playernum+1 && ch->entNum == cl.playernum+1)
1415 			continue;
1416 
1417 		// Replace the oldest sound
1418 		if (ch->startTime < oldestTime)
1419 		{
1420 			oldestTime = ch->startTime;
1421 			firstToDie = i;
1422 		}
1423 	}
1424 
1425 	if (firstToDie == -1)
1426 		return NULL;
1427 
1428 	ch = &s_openal_channels[firstToDie];
1429 
1430 	ch->entNum = entNum;
1431 	ch->entChannel = entChannel;
1432 	ch->startTime = cl.time;
1433 
1434 	// Make sure this channel is stopped
1435 	qalSourceStop(ch->sourceNum);
1436 	qalSourcei(ch->sourceNum, AL_BUFFER, 0);
1437 
1438 	return ch;
1439 }
1440 
S_OpenAL_SpatializeChannel(openal_channel_t * ch)1441 static void S_OpenAL_SpatializeChannel (openal_channel_t *ch)
1442 {
1443 	vec3_t	position;
1444 
1445 	// Update position and velocity
1446 	if (ch->entNum == cl.playernum+1 || !ch->distanceMult)
1447 	{
1448 		qalSourcefv(ch->sourceNum, AL_POSITION, s_openal_listener.position);
1449 		//qalSourcefv(ch->sourceNum, AL_VELOCITY, s_openal_listener.velocity);
1450 	}
1451 	else
1452 	{
1453 		if (ch->fixedPosition)
1454 		{
1455 			qalSource3f(ch->sourceNum, AL_POSITION, ch->position[1], ch->position[2], -ch->position[0]);
1456 			//qalSource3f(ch->sourceNum, AL_VELOCITY, 0, 0, 0);
1457 		}
1458 		else
1459 		{
1460 			if (ch->loopSound)
1461 				Snd_GetEntityOrigin (ch->loopNum, position);
1462 			else
1463 				Snd_GetEntityOrigin (ch->entNum, position);
1464 
1465 			qalSource3f(ch->sourceNum, AL_POSITION, position[1], position[2], -position[0]);
1466 			//qalSource3f(ch->sourceNum, AL_VELOCITY, velocity[1], velocity[2], -velocity[0]);
1467 		}
1468 	}
1469 
1470 	// Update min/max distance
1471 	if (ch->distanceMult)
1472 		qalSourcef(ch->sourceNum, AL_REFERENCE_DISTANCE, 240.0f * ch->distanceMult);
1473 	else
1474 		qalSourcef(ch->sourceNum, AL_REFERENCE_DISTANCE,  8192);
1475 
1476 	qalSourcef(ch->sourceNum, AL_MAX_DISTANCE, 8192);
1477 
1478 	// Update volume and rolloff factor
1479 	qalSourcef(ch->sourceNum, AL_GAIN, s_openal_volume->value * ch->volume);
1480 
1481 	qalSourcef(ch->sourceNum, AL_ROLLOFF_FACTOR, 1.0f);
1482 }
1483 
S_OpenAL_AddLoopingSounds(void)1484 static void S_OpenAL_AddLoopingSounds (void)
1485 {
1486 	entity_state_t			*ent;
1487 	sfx_t					*sfx;
1488 //	openal_sfx_t			asfx;
1489 	openal_channel_t		*ch;
1490 	int						i, j;
1491 
1492 	if (cls.state != ca_active || cl_paused->intvalue)
1493 		return;
1494 
1495 	for (i = 0; i < cl.frame.num_entities; i++)
1496 	{
1497 		ent = &cl_parse_entities[(cl.frame.parse_entities+i) & (MAX_PARSE_ENTITIES-1)];
1498 		if (!ent->sound)
1499 			continue;
1500 
1501 		sfx = cl.sound_precache[ent->sound];
1502 
1503 		if (!sfx || !sfx->loaded)
1504 			continue;		// Bad sound effect
1505 
1506 		// If this entity is already playing the same sound effect on an
1507 		// active channel, then simply update it
1508 		for (j = 0, ch = s_openal_channels; j < s_openal_numChannels; j++, ch++)
1509 		{
1510 			if (ch->sfx != sfx)
1511 				continue;
1512 
1513 			if (!ch->loopSound)
1514 				continue;
1515 
1516 			if (ch->loopNum != ent->number)
1517 				continue;
1518 
1519 			if (ch->loopFrame + 1 != s_openal_frameCount)
1520 				continue;
1521 
1522 			ch->loopFrame = s_openal_frameCount;
1523 			break;
1524 		}
1525 
1526 		if (j != s_openal_numChannels)
1527 			continue;
1528 
1529 		// Otherwise pick a channel and start the sound effect
1530 		ch = S_OpenAL_PickChannel(0, 0);
1531 
1532 		if (!ch)
1533 		{
1534 			if (sfx->name[0] == '#')
1535 				Com_DPrintf("Dropped sound %s\n", &sfx->name[1]);
1536 			else
1537 				Com_DPrintf("Dropped sound sound/%s\n", sfx->name);
1538 
1539 			continue;
1540 		}
1541 
1542 		ch->loopSound = true;
1543 		ch->loopNum = ent->number;
1544 		ch->loopFrame = s_openal_frameCount;
1545 		ch->fixedPosition = false;
1546 		ch->volume = 1.0f;
1547 		ch->distanceMult = 0.3f;//1.0f / ATTN_STATIC;
1548 
1549 		S_OpenAL_SpatializeChannel(ch);
1550 
1551 		S_OpenAL_PlayChannel(ch, sfx);
1552 	}
1553 }
1554 
S_OpenAL_ChannelState(openal_channel_t * ch)1555 static int S_OpenAL_ChannelState (openal_channel_t *ch)
1556 {
1557 	int		state;
1558 
1559 	qalGetSourcei(ch->sourceNum, AL_SOURCE_STATE, &state);
1560 
1561 	return state;
1562 }
1563 
S_OpenAL_IssuePlaySounds(void)1564 static void S_OpenAL_IssuePlaySounds (void)
1565 {
1566 	playsound_t 		*ps;
1567 	openal_channel_t	*ch;
1568 
1569 	for (;;)
1570 	{
1571 		ps = s_pendingplays.next;
1572 
1573 		if (ps == &s_pendingplays)
1574 			break;		// No more pending playSounds
1575 
1576 		if (ps->begin > cl.time)
1577 			break;		// No more pending playSounds this frame
1578 
1579 		// Pick a channel and start the sound effect
1580 		ch = S_OpenAL_PickChannel(ps->entnum, ps->entchannel);
1581 
1582 		if (!ch)
1583 		{
1584 			if (ps->sfx->name[0] == '#')
1585 				Com_DPrintf("Dropped sound %s\n", &ps->sfx->name[1]);
1586 			else
1587 				Com_DPrintf("Dropped sound sound/%s\n", ps->sfx->name);
1588 
1589 			S_FreePlaysound (ps);
1590 			continue;
1591 		}
1592 
1593 		ch->loopSound = false;
1594 		ch->fixedPosition = ps->fixed_origin;
1595 		FastVectorCopy (ps->origin, ch->position);
1596 		ch->volume = ps->volume;
1597 
1598 		if (ps->attenuation != ATTN_NONE)
1599 			ch->distanceMult = 1.0f / ps->attenuation;
1600 		else
1601 			ch->distanceMult = 0.0f;
1602 
1603 		S_OpenAL_SpatializeChannel(ch);
1604 
1605 		S_OpenAL_PlayChannel(ch, ps->sfx);
1606 
1607 		// Free the playSound
1608 		S_FreePlaysound(ps);
1609 	}
1610 }
1611 
1612 //=============================================================================
1613 int	EXPORT CL_PMpointcontents (vec3_t point);
S_Update_OpenAL(vec3_t position,const vec3_t velocity,const vec3_t at,const vec3_t up)1614 void S_Update_OpenAL (vec3_t position, const vec3_t velocity, const vec3_t at, const vec3_t up)
1615 {
1616 	unsigned			eaxEnv;
1617 	openal_channel_t	*ch;
1618 	int					i, total = 0;
1619 
1620 	// Bump frame count
1621 	s_openal_frameCount++;
1622 
1623 	// Set up listener
1624 	VectorSet(s_openal_listener.position, position[1], position[2], -position[0]);
1625 	//VectorSet(s_openal_listener.velocity, velocity[1], velocity[2], -velocity[0]);
1626 
1627 	s_openal_listener.orientation[0] = at[1];
1628 	s_openal_listener.orientation[1] = -at[2];
1629 	s_openal_listener.orientation[2] = -at[0];
1630 	s_openal_listener.orientation[3] = up[1];
1631 	s_openal_listener.orientation[4] = -up[2];
1632 	s_openal_listener.orientation[5] = -up[0];
1633 
1634 	qalListenerfv(AL_POSITION, s_openal_listener.position);
1635 	//qalListenerfv(AL_VELOCITY, s_openal_listener.velocity);
1636 	qalListenerfv(AL_ORIENTATION, s_openal_listener.orientation);
1637 #ifdef _WIN32
1638 	qalListenerf(AL_GAIN, (ActiveApp) ? s_volume->value : 0);
1639 #else
1640 	qalListenerf(AL_GAIN, s_volume->value);
1641 #endif
1642 
1643 	// Set state
1644 	qalDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
1645 	//qalDistanceModel(AL_INVERSE_DISTANCE);
1646 
1647 	//qalDopplerFactor(s_dopplerFactor->value);
1648 	//qalDopplerVelocity(s_dopplerVelocity->value);
1649 
1650 	// If EAX is enabled, apply listener environmental effects
1651 #ifdef _WIN32
1652 	if (alConfig.eax)
1653 	{
1654 		if (cls.state != ca_active)
1655 		{
1656 			eaxEnv = EAX_ENVIRONMENT_GENERIC;
1657 		}
1658 		else
1659 		{
1660 			if (CL_PMpointcontents (position) & MASK_WATER)
1661 				eaxEnv = EAX_ENVIRONMENT_UNDERWATER;
1662 			else
1663 				eaxEnv = EAX_ENVIRONMENT_GENERIC;
1664 		}
1665 
1666 		if (eaxEnv != alConfig.eaxState)
1667 		{
1668 			alConfig.eaxState = eaxEnv;
1669 			qalEAXSet (&DSPROPSETID_EAX20_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENT | DSPROPERTY_EAXLISTENER_IMMEDIATE, 0, &eaxEnv, sizeof(eaxEnv));
1670 		}
1671 	}
1672 #endif
1673 
1674 	// Stream background track
1675 	//S_StreamBackgroundTrack();
1676 
1677 	// Add looping sounds
1678 	if (s_ambient->intvalue)
1679 		S_OpenAL_AddLoopingSounds();
1680 
1681 	// Issue playSounds
1682 	S_OpenAL_IssuePlaySounds();
1683 
1684 	// Update spatialization for all sounds
1685 	for (i = 0, ch = s_openal_channels; i < s_openal_numChannels; i++, ch++)
1686 	{
1687 		if (!ch->sfx)
1688 			continue;		// Not active
1689 
1690 		// Check for stop
1691 		if (ch->loopSound)
1692 		{
1693 			if (ch->loopFrame != s_openal_frameCount)
1694 			{
1695 				S_OpenAL_StopChannel(ch);
1696 				continue;
1697 			}
1698 		}
1699 		else
1700 		{
1701 			if (S_OpenAL_ChannelState(ch) == AL_STOPPED)
1702 			{
1703 				S_OpenAL_StopChannel(ch);
1704 				continue;
1705 			}
1706 		}
1707 
1708 		// Respatialize channel
1709 		S_OpenAL_SpatializeChannel(ch);
1710 
1711 		if (s_show->intvalue)
1712 		{
1713 			if (ch->sfx->name[0] == '#')
1714 				Com_Printf("%2i: %s\n", LOG_CLIENT, i+1, &ch->sfx->name[1]);
1715 			else
1716 				Com_Printf("%2i: sound/%s\n", LOG_CLIENT, i+1, ch->sfx->name);
1717 		}
1718 
1719 		total++;
1720 	}
1721 
1722 	if (s_show->intvalue)
1723 		Com_Printf("--- ( %i ) ---\n", LOG_CLIENT, total);
1724 }
1725 #endif
1726 
1727 /*
1728 ============
1729 S_Update
1730 
1731 Called once each time through the main loop
1732 ============
1733 */
S_Update(vec3_t origin,vec3_t forward,vec3_t right,vec3_t up)1734 void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
1735 {
1736 	int			i;
1737 	int			total;
1738 	channel_t	*ch;
1739 //	channel_t	*combine;
1740 
1741 	if (!sound_started)
1742 		return;
1743 
1744 	// if the laoding plaque is up, clear everything
1745 	// out to make sure we aren't looping a dirty
1746 	// dma buffer while loading
1747 	if (cls.disable_screen)
1748 	{
1749 		S_ClearBuffer ();
1750 		return;
1751 	}
1752 
1753 #ifdef USE_OPENAL
1754 	if (openal_active)
1755 	{
1756 		S_Update_OpenAL (origin, vec3_origin, forward, up);
1757 		return;
1758 	}
1759 #endif
1760 
1761 	FastVectorCopy (*origin, listener_origin);
1762 	FastVectorCopy (*forward, listener_forward);
1763 	FastVectorCopy (*right, listener_right);
1764 	FastVectorCopy (*up, listener_up);
1765 
1766 	// rebuild scale tables if volume is modified
1767 	if (s_volume->modified)
1768 		S_InitScaletable ();
1769 
1770 	//combine = NULL;
1771 
1772 	// update spatialization for dynamic sounds
1773 	ch = channels;
1774 	for (i=0 ; i<MAX_CHANNELS; i++, ch++)
1775 	{
1776 		if (!ch->sfx)
1777 			continue;
1778 		if (ch->autosound)
1779 		{	// autosounds are regenerated fresh each frame
1780 			memset (ch, 0, sizeof(*ch));
1781 			continue;
1782 		}
1783 		S_Spatialize(ch);         // respatialize channel
1784 		if (!ch->leftvol && !ch->rightvol)
1785 		{
1786 			memset (ch, 0, sizeof(*ch));
1787 			continue;
1788 		}
1789 	}
1790 
1791 	// add loopsounds
1792 	if (s_ambient->intvalue)
1793 		S_AddLoopSounds ();
1794 
1795 	//
1796 	// debugging output
1797 	//
1798 	if (s_show->intvalue)
1799 	{
1800 		total = 0;
1801 		ch = channels;
1802 		for (i=0 ; i<MAX_CHANNELS; i++, ch++)
1803 			if (ch->sfx && (ch->leftvol || ch->rightvol) )
1804 			{
1805 				Com_Printf ("%3i %3i %s\n", LOG_CLIENT, ch->leftvol, ch->rightvol, ch->sfx->name);
1806 				total++;
1807 			}
1808 
1809 		Com_Printf ("----(%i)---- painted: %i\n", LOG_CLIENT, total, paintedtime);
1810 	}
1811 
1812 // mix some sound
1813 	S_Update_();
1814 }
1815 
GetSoundtime(void)1816 void GetSoundtime(void)
1817 {
1818 	int		samplepos;
1819 	static	int		buffers;
1820 	static	int		oldsamplepos;
1821 	int		fullsamples;
1822 
1823 	fullsamples = dma.samples / dma.channels;
1824 
1825 // it is possible to miscount buffers if it has wrapped twice between
1826 // calls to S_Update.  Oh well.
1827 	samplepos = SNDDMA_GetDMAPos();
1828 
1829 	if (samplepos < oldsamplepos)
1830 	{
1831 		buffers++;					// buffer wrapped
1832 
1833 		if (paintedtime > 0x40000000)
1834 		{	// time to chop things off to avoid 32 bit limits
1835 			buffers = 0;
1836 			paintedtime = fullsamples;
1837 			S_StopAllSounds ();
1838 		}
1839 	}
1840 	oldsamplepos = samplepos;
1841 
1842 	soundtime = buffers*fullsamples + samplepos/dma.channels;
1843 }
1844 
1845 
S_Update_(void)1846 void S_Update_(void)
1847 {
1848 	uint32	endtime;
1849 	int32	samps;
1850 
1851 	if (!sound_started)
1852 		return;
1853 
1854 	SNDDMA_BeginPainting ();
1855 
1856 	if (!dma.buffer)
1857 		return;
1858 
1859 // Updates DMA time
1860 	GetSoundtime();
1861 
1862 // check to make sure that we haven't overshot
1863 	if (paintedtime < soundtime)
1864 	{
1865 		//Com_DPrintf ("S_Update_ : overflow\n");
1866 		paintedtime = soundtime;
1867 	}
1868 
1869 // mix ahead of current position
1870 	endtime = (int)(soundtime + s_mixahead->value * dma.speed);
1871 //endtime = (soundtime + 4096) & ~4095;
1872 
1873 	// mix to an even submission block size
1874 	endtime = (endtime + dma.submission_chunk-1)
1875 		& ~(dma.submission_chunk-1);
1876 	samps = dma.samples >> (dma.channels-1);
1877 	if (endtime - soundtime > samps)
1878 		endtime = soundtime + samps;
1879 
1880 	S_PaintChannels (endtime);
1881 
1882 	SNDDMA_Submit ();
1883 }
1884 
1885 /*
1886 ===============================================================================
1887 
1888 console functions
1889 
1890 ===============================================================================
1891 */
1892 
S_Play(void)1893 void S_Play(void)
1894 {
1895 	int 	i;
1896 	char name[256];
1897 	sfx_t	*sfx;
1898 
1899 	i = 1;
1900 	while (i<Cmd_Argc())
1901 	{
1902 		if (!strrchr(Cmd_Argv(i), '.'))
1903 		{
1904 			Q_strncpy (name, Cmd_Argv(i), sizeof(name)-5);
1905 			strcat(name, ".wav");
1906 		}
1907 		else
1908 			Q_strncpy (name, Cmd_Argv(i), sizeof(name)-1);
1909 
1910 		if (strstr(name, "..") || name[0] == '/' || name[0] == '\\') {
1911 			Com_Printf ("Bad filename %s\n", LOG_CLIENT, name);
1912 			return;
1913 		}
1914 
1915 		sfx = S_RegisterSound(name);
1916 		if (sfx)
1917 		{
1918 			S_StartSound(NULL, cl.playernum+1, 0, sfx, 1.0, 1.0, 0);
1919 			//sfx->name[0] = '\0';
1920 		}
1921 		i++;
1922 	}
1923 }
1924 
S_SoundList_f(void)1925 void S_SoundList_f (void)
1926 {
1927 	int		i;
1928 	sfx_t	*sfx;
1929 	sfxcache_t	*sc;
1930 	int		size, total;
1931 	int		numsounds;
1932 
1933 	total = 0;
1934 	numsounds = 0;
1935 
1936 	for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++)
1937 	{
1938 		if (!sfx->name[0])
1939 			continue;
1940 
1941 		sc = sfx->cache;
1942 		if (sc)
1943 		{
1944 			size = sc->length*sc->width*(sc->stereo+1);
1945 			total += size;
1946 			Com_Printf("%s(%2db) %8i : %s\n", LOG_CLIENT, sc->loopstart != -1 ? "L" : " ", sc->width*8,  size, sfx->name);
1947 		}
1948 		else
1949 		{
1950 			if (sfx->name[0] == '*')
1951 				Com_Printf("    placeholder : %s\n", LOG_CLIENT, sfx->name);
1952 			else
1953 				Com_Printf("    not loaded  : %s\n", LOG_CLIENT, sfx->name);
1954 		}
1955 		numsounds++;
1956 	}
1957 	Com_Printf ("Total resident: %i bytes (%.2f MB) in %d sounds\n", LOG_CLIENT, total, (float)total / 1024 / 1024, numsounds);
1958 }
1959 
1960