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 //
21 // snd_main.c
22 //
23 
24 #include "snd_local.h"
25 
26 qBool					snd_isActive = qTrue;
27 qBool					snd_isFirstInit = qTrue;
28 qBool					snd_isInitialized = qFalse;
29 qBool					snd_isDMA;
30 qBool					snd_isAL;
31 
32 static qBool			snd_queueRestart;
33 
34 // Sound registration
35 #define MAX_SFX_HASH	(MAX_SFX/4)
36 
37 static sfx_t			snd_sfxList[MAX_SFX];
38 static sfx_t			*snd_sfxHashList[MAX_SFX_HASH];
39 static int				snd_numSFX;
40 
41 uint32					snd_registrationFrame;
42 
43 // Play sounds
44 playSound_t				snd_playSounds[MAX_PLAYSOUNDS];
45 playSound_t				snd_freePlays;
46 playSound_t				snd_pendingPlays;
47 
48 cVar_t	*s_initSound;
49 cVar_t	*s_show;
50 cVar_t	*s_loadas8bit;
51 cVar_t	*s_volume;
52 
53 cVar_t	*s_testsound;
54 cVar_t	*s_khz;
55 cVar_t	*s_mixahead;
56 cVar_t	*s_primary;
57 
58 cVar_t	*al_allowExtensions;
59 cVar_t	*al_device;
60 cVar_t	*al_dopplerFactor;
61 cVar_t	*al_dopplerVelocity;
62 cVar_t	*al_driver;
63 cVar_t	*al_errorCheck;
64 cVar_t	*al_ext_eax2;
65 cVar_t	*al_gain;
66 cVar_t	*al_minDistance;
67 cVar_t	*al_maxDistance;
68 cVar_t	*al_rollOffFactor;
69 
70 /*
71 ===========
72 Snd_Activate
73 ===========
74 */
Snd_Activate(qBool active)75 void Snd_Activate (qBool active)
76 {
77 	if (!snd_isInitialized)
78 		return;
79 
80 	snd_isActive = active;
81 
82 	if (snd_isAL)
83 		ALSnd_Activate (active);
84 }
85 
86 /*
87 ===============================================================================
88 
89 	WAV LOADING AND RESAMPLING
90 
91 ===============================================================================
92 */
93 
94 static byte		*snd_dataPtr;
95 static byte		*snd_iffEnd;
96 static byte		*snd_lastIffChunk;
97 static byte		*snd_iffData;
98 static int		snd_iffChunkLength;
99 
100 /*
101 ============
102 _wGetLittleShort
103 ============
104 */
_wGetLittleShort(void)105 static int16 _wGetLittleShort (void)
106 {
107 	int16 val = 0;
108 
109 	val = *snd_dataPtr;
110 	val = val + (*(snd_dataPtr+1)<<8);
111 
112 	snd_dataPtr += 2;
113 
114 	return val;
115 }
116 
117 
118 /*
119 ============
120 _wGetLittleLong
121 ============
122 */
_wGetLittleLong(void)123 static int _wGetLittleLong (void)
124 {
125 	int val = 0;
126 
127 	val = *snd_dataPtr;
128 	val = val + (*(snd_dataPtr+1)<<8);
129 	val = val + (*(snd_dataPtr+2)<<16);
130 	val = val + (*(snd_dataPtr+3)<<24);
131 
132 	snd_dataPtr += 4;
133 
134 	return val;
135 }
136 
137 
138 /*
139 ============
140 _wFindNextChunk
141 ============
142 */
_wFindNextChunk(char * name)143 static void _wFindNextChunk (char *name)
144 {
145 	for ( ; ; ) {
146 		snd_dataPtr = snd_lastIffChunk;
147 
148 		snd_dataPtr += 4;
149 		if (snd_dataPtr >= snd_iffEnd) {
150 			// Didn't find the chunk
151 			snd_dataPtr = NULL;
152 			return;
153 		}
154 
155 		snd_iffChunkLength = _wGetLittleLong ();
156 		if (snd_iffChunkLength < 0) {
157 			snd_dataPtr = NULL;
158 			return;
159 		}
160 
161 		snd_dataPtr -= 8;
162 		snd_lastIffChunk = snd_dataPtr + 8 + ((snd_iffChunkLength + 1) & ~1);
163 		if (!strncmp ((char *)snd_dataPtr, name, 4))
164 			return;
165 	}
166 }
167 
168 
169 /*
170 ============
171 _wFindChunk
172 ============
173 */
_wFindChunk(char * name)174 static void _wFindChunk (char *name)
175 {
176 	snd_lastIffChunk = snd_iffData;
177 	_wFindNextChunk (name);
178 }
179 
180 
181 /*
182 ============
183 Snd_GetWavinfo
184 ============
185 */
Snd_GetWavinfo(char * name,byte * wav,int wavLength)186 static wavInfo_t Snd_GetWavinfo (char *name, byte *wav, int wavLength)
187 {
188 	wavInfo_t	info;
189 	int			i;
190 	int			format;
191 	int			samples;
192 
193 	memset (&info, 0, sizeof (info));
194 
195 	if (!wav)
196 		return info;
197 
198 	snd_iffData = wav;
199 	snd_iffEnd = wav + wavLength;
200 
201 	// Find "RIFF" chunk
202 	_wFindChunk ("RIFF");
203 	if (!(snd_dataPtr && !strncmp ((char *)snd_dataPtr+8, "WAVE", 4))) {
204 		Com_Printf (0, "Missing RIFF/WAVE chunks\n");
205 		return info;
206 	}
207 
208 	// Get "fmt " chunk
209 	snd_iffData = snd_dataPtr + 12;
210 	_wFindChunk ("fmt ");
211 	if (!snd_dataPtr) {
212 		Com_Printf (0, "Missing fmt chunk\n");
213 		return info;
214 	}
215 
216 	snd_dataPtr += 8;
217 	format = _wGetLittleShort ();
218 	if (format != 1) {
219 		Com_Printf (0, "Microsoft PCM format only\n");
220 		return info;
221 	}
222 
223 	// Channels, rate, width...
224 	info.channels = _wGetLittleShort ();
225 	info.rate = _wGetLittleLong ();
226 	snd_dataPtr += 4+2;
227 	info.width = _wGetLittleShort () / 8;
228 
229 	// Get cue chunk
230 	_wFindChunk ("cue ");
231 	if (snd_dataPtr) {
232 		snd_dataPtr += 32;
233 		info.loopStart = _wGetLittleLong ();
234 
235 		// If the next chunk is a LIST chunk, look for a cue length marker
236 		_wFindNextChunk ("LIST");
237 		if (snd_dataPtr) {
238 			if (!strncmp ((char *)snd_dataPtr+28, "mark", 4)) {
239 				// This is not a proper parse, but it works with cooledit
240 				snd_dataPtr += 24;
241 				i = _wGetLittleLong ();	// Samples in loop
242 				info.samples = info.loopStart + i;
243 			}
244 		}
245 	}
246 	else
247 		info.loopStart = -1;
248 
249 	// Find data chunk
250 	_wFindChunk ("data");
251 	if (!snd_dataPtr) {
252 		Com_Printf (0, "Missing data chunk\n");
253 		return info;
254 	}
255 
256 	// Check loop length
257 	snd_dataPtr += 4;
258 	samples = _wGetLittleLong () / info.width;
259 	if (info.samples) {
260 		if (samples < info.samples)
261 			Com_Error (ERR_DROP, "Sound %s has a bad loop length", name);
262 	}
263 	else
264 		info.samples = samples;
265 
266 	info.dataOfs = snd_dataPtr - wav;
267 	return info;
268 }
269 
270 
271 /*
272 ================
273 DMASnd_ResampleSfx
274 ================
275 */
DMASnd_ResampleSfx(sfx_t * sfx,int inRate,int inWidth,byte * data)276 static void DMASnd_ResampleSfx (sfx_t *sfx, int inRate, int inWidth, byte *data)
277 {
278 	int		outcount;
279 	int		srcsample;
280 	float	stepscale;
281 	int		i;
282 	int		sample, samplefrac, fracstep;
283 	sfxCache_t	*sc;
284 
285 	sc = sfx->cache;
286 	if (!sc)
287 		return;
288 
289 	stepscale = (float)inRate / snd_audioDMA.speed;	// This is usually 0.5, 1, or 2
290 
291 	outcount = sc->length / stepscale;
292 	sc->length = outcount;
293 	if (sc->loopStart != -1)
294 		sc->loopStart = sc->loopStart / stepscale;
295 
296 	sc->speed = snd_audioDMA.speed;
297 	if (s_loadas8bit->intVal)
298 		sc->width = 1;
299 	else
300 		sc->width = inWidth;
301 	sc->stereo = 0;
302 
303 	// Resample / decimate to the current source rate
304 	if (stepscale == 1 && inWidth == 1 && sc->width == 1) {
305 		// Fast special case
306 		for (i=0 ; i<outcount ; i++)
307 			((signed char *)sc->data)[i] = (int)((byte)(data[i]) - 128);
308 	}
309 	else {
310 		// General case
311 		samplefrac = 0;
312 		fracstep = stepscale*256;
313 		for (i=0 ; i<outcount ; i++) {
314 			srcsample = samplefrac >> 8;
315 			samplefrac += fracstep;
316 			if (inWidth == 2)
317 				sample = LittleShort (((int16 *)data)[srcsample]);
318 			else
319 				sample = (int)((byte)(data[srcsample]) - 128) << 8;
320 			if (sc->width == 2)
321 				((int16 *)sc->data)[i] = sample;
322 			else
323 				((signed char *)sc->data)[i] = sample >> 8;
324 		}
325 	}
326 }
327 
328 
329 /*
330 ==============
331 Snd_LoadSound
332 ==============
333 */
Snd_LoadSound(sfx_t * s)334 sfxCache_t *Snd_LoadSound (sfx_t *s)
335 {
336     char		namebuffer[MAX_QPATH];
337 	byte		*data;
338 	wavInfo_t	info;
339 	int			len;
340 	float		stepscale;
341 	sfxCache_t	*sc;
342 	int			fileLen;
343 	char		*name;
344 
345 	if (!s)
346 		return NULL;
347 
348 	s->touchFrame = snd_registrationFrame;
349 	if (s->name[0] == '*')
350 		return NULL;
351 
352 	// See if still in memory
353 	sc = s->cache;
354 	if (sc)
355 		return sc;
356 
357 	// Load it in
358 	if (s->trueName)
359 		name = s->trueName;
360 	else
361 		name = s->name;
362 
363 	if (name[0] == '#')
364 		Q_strncpyz (namebuffer, &name[1], sizeof (namebuffer));
365 	else
366 		Q_snprintfz (namebuffer, sizeof (namebuffer), "sound/%s", name);
367 
368 	fileLen = FS_LoadFile (namebuffer, (void **)&data, NULL);
369 	if (!data || fileLen <= 0) {
370 		Com_DevPrintf (0, "Snd_LoadSound: Couldn't load %s -- %s\n", namebuffer, (fileLen == -1) ? "not found" : "empty file");
371 		return NULL;
372 	}
373 
374 	// Get WAV info
375 	info = Snd_GetWavinfo (s->name, data, fileLen);
376 	if (snd_isDMA) {
377 		if (info.channels != 1) {
378 			Com_Printf (0, "Snd_LoadSound: %s is a stereo sample\n", s->name);
379 			FS_FreeFile (data);
380 			return NULL;
381 		}
382 		stepscale = (float)info.rate / snd_audioDMA.speed;
383 		len = (info.samples / stepscale) * info.width * info.channels;
384 	}
385 	else if (snd_isAL) {
386 		len = 0;
387 	}
388 
389 	sc = s->cache = Mem_PoolAlloc (len + sizeof (sfxCache_t), cl_soundSysPool, 0);
390 	if (!sc) {
391 		FS_FreeFile (data);
392 		return NULL;
393 	}
394 
395 	if (snd_isDMA) {
396 		sc->length = info.samples;
397 		sc->loopStart = info.loopStart;
398 		sc->speed = info.rate;
399 		sc->width = info.width;
400 		sc->stereo = info.channels;
401 
402 		DMASnd_ResampleSfx (s, sc->speed, sc->width, data + info.dataOfs);
403 	}
404 	else if (snd_isAL) {
405 		ALSnd_CreateBuffer (sc, info.width, info.channels, data + info.dataOfs, info.samples * info.width * info.channels, info.rate);
406 	}
407 
408 	FS_FreeFile (data);
409 	return sc;
410 }
411 
412 /*
413 ===============================================================================
414 
415 	CONSOLE FUNCTIONS
416 
417 ===============================================================================
418 */
419 
420 /*
421 ============
422 Snd_Play_f
423 ============
424 */
Snd_Play_f(void)425 static void Snd_Play_f (void)
426 {
427 	char	name[256];
428 	sfx_t	*sfx;
429 	int		i;
430 
431 	if (!snd_isInitialized) {
432 		Com_Printf (PRNT_WARNING, "Sound system not started\n");
433 		return;
434 	}
435 
436 	i = 1;
437 	while (i < Cmd_Argc ()) {
438 		if (!strrchr (Cmd_Argv (i), '.')) {
439 			Q_snprintfz (name, sizeof (name), "%s.wav", Cmd_Argv (i));
440 		}
441 		else
442 			Q_strncpyz (name, Cmd_Argv (i), sizeof (name));
443 		sfx = Snd_RegisterSound (name);
444 		Snd_StartSound (NULL, cl.playerNum+1, CHAN_AUTO, sfx, 1.0f, 1.0f, 0);
445 		i++;
446 	}
447 }
448 
449 
450 /*
451 ================
452 Snd_Restart_f
453 
454 For queueing a sound restart
455 ================
456 */
Snd_Restart_f(void)457 static void Snd_Restart_f (void)
458 {
459 	snd_queueRestart = qTrue;
460 }
461 
462 
463 /*
464 ============
465 Snd_SoundList_f
466 ============
467 */
Snd_SoundList_f(void)468 static void Snd_SoundList_f (void)
469 {
470 	int			i;
471 	sfx_t		*sfx;
472 	sfxCache_t	*sc;
473 	int			total;
474 	int			size;
475 
476 	if (!snd_isInitialized) {
477 		Com_Printf (PRNT_WARNING, "Sound system not started\n");
478 		return;
479 	}
480 
481 	for (sfx=snd_sfxList, total=0, i=0 ; i<snd_numSFX ; i++, sfx++) {
482 		if (!sfx->touchFrame)
483 			continue;
484 
485 		sc = sfx->cache;
486 		if (sc) {
487 			size = sc->length * sc->width * (sc->stereo + 1);
488 			total += size;
489 			if (sc->loopStart >= 0)
490 				Com_Printf (0, "L");
491 			else
492 				Com_Printf (0, " ");
493 			Com_Printf (0, "(%2db) %6i : %s\n", sc->width*8, size, sfx->name);
494 		}
495 		else {
496 			if (sfx->name[0] == '*')
497 				Com_Printf (0, "  placeholder : %s\n", sfx->name);
498 			else
499 				Com_Printf (0, "  not loaded  : %s\n", sfx->name);
500 		}
501 	}
502 
503 	Com_Printf (0, "Total resident: %i\n", total);
504 }
505 
506 
507 /*
508 =================
509 Snd_SoundInfo_f
510 =================
511 */
Snd_SoundInfo_f(void)512 static void Snd_SoundInfo_f (void)
513 {
514 	if (snd_isDMA) {
515 		Com_Printf (0, "DMA Sound info:\n");
516 		Com_Printf (0, "%5d stereo\n", snd_audioDMA.channels - 1);
517 		Com_Printf (0, "%5d samples\n", snd_audioDMA.samples);
518 		Com_Printf (0, "%5d samplepos\n", snd_audioDMA.samplePos);
519 		Com_Printf (0, "%5d samplebits\n", snd_audioDMA.sampleBits);
520 		Com_Printf (0, "%5d submission_chunk\n", snd_audioDMA.submissionChunk);
521 		Com_Printf (0, "%5d speed\n", snd_audioDMA.speed);
522 		Com_Printf (0, "0x%x dma buffer\n", snd_audioDMA.buffer);
523 	}
524 	else if (snd_isAL) {
525 		Com_Printf (0, "OpenAL Sound info:\n");
526 		Com_Printf (0, "AL_VENDOR: %s\n", snd_audioAL.vendorString);
527 		Com_Printf (0, "AL_RENDERER: %s\n", snd_audioAL.rendererString);
528 		Com_Printf (0, "AL_VERSION: %s\n", snd_audioAL.versionString);
529 		Com_Printf (0, "AL_EXTENSIONS: %s\n", snd_audioAL.extensionString);
530 		Com_Printf (0, "ALC_DEVICE_SPECIFIER: %s\n", snd_audioAL.deviceName);
531 		Com_Printf (0, "%i sources\n", snd_audioAL.numChannels);
532 	}
533 	else {
534 		Com_Printf (PRNT_WARNING, "Sound system not started\n");
535 	}
536 }
537 
538 /*
539 ==============================================================================
540 
541 	SOUND REGISTRATION
542 
543 ==============================================================================
544 */
545 
546 /*
547 ==================
548 Snd_FreeSound
549 ==================
550 */
Snd_FreeSound(sfx_t * sfx)551 static void Snd_FreeSound (sfx_t *sfx)
552 {
553 	sfx_t	*hashSfx;
554 	sfx_t	**prev;
555 
556 	if (!sfx)
557 		return;
558 
559 	// De-link it from the hash tree
560 	prev = &snd_sfxHashList[sfx->hashValue];
561 	for ( ; ; ) {
562 		hashSfx = *prev;
563 		if (!hashSfx)
564 			break;
565 
566 		if (hashSfx == sfx) {
567 			*prev = hashSfx->hashNext;
568 			break;
569 		}
570 		prev = &hashSfx->hashNext;
571 	}
572 
573 	// FIXME: trueName is a goddamned hack
574 	if (sfx->trueName)
575 		Mem_Free (sfx->trueName);
576 
577 	if (sfx->cache) {
578 		// Delete the OpenAL buffer
579 		ALSnd_DeleteBuffer (sfx->cache);
580 
581 		// It is possible to have a leftover from a server that didn't finish loading
582 		Mem_Free (sfx->cache);
583 	}
584 
585 	memset (sfx, 0, sizeof (sfx_t));
586 }
587 
588 
589 /*
590 ==================
591 Snd_FindSpot
592 ==================
593 */
Snd_FindSpot(void)594 static sfx_t *Snd_FindSpot (void)
595 {
596 	int		i;
597 
598 	for (i=0 ; i<snd_numSFX ; i++)
599 		if (!snd_sfxList[i].name[0])
600 			break;
601 
602 	if (i == snd_numSFX) {
603 		if (snd_numSFX == MAX_SFX)
604 			Com_Error (ERR_FATAL, "Snd_FindSpot: MAX_SFX");
605 		snd_numSFX++;
606 	}
607 
608 	return &snd_sfxList[i];
609 }
610 
611 
612 /*
613 ==================
614 Snd_FindName
615 ==================
616 */
Snd_FindName(char * name,qBool create)617 static sfx_t *Snd_FindName (char *name, qBool create)
618 {
619 	sfx_t	*sfx;
620 	char	outName[MAX_QPATH];
621 	uint32	hash;
622 
623 	if (!name) {
624 		Com_Printf (PRNT_ERROR, "Snd_FindName: NULL name\n");
625 		return NULL;
626 	}
627 	if (!name[0]) {
628 		Com_Printf (PRNT_ERROR, "Snd_FindName: empty name\n");
629 		return NULL;
630 	}
631 
632 	if (strlen(name)+1 >= MAX_QPATH)
633 		Com_Error (ERR_FATAL, "Snd_FindName: Sound name too long: %s", name);
634 
635 	// Copy, then normalize the path, but don't strip the extension
636 	Com_NormalizePath (outName, sizeof (outName), name);
637 
638 	// See if already loaded
639 	hash = Com_HashFileName (name, MAX_SFX_HASH);
640 	for (sfx=snd_sfxHashList[hash] ; sfx ; sfx=sfx->hashNext) {
641 		if (!strcmp (sfx->name, outName))
642 			return sfx;
643 	}
644 
645 	if (!create)
646 		return NULL;
647 
648 	// Find a free sfx
649 	sfx = Snd_FindSpot ();
650 
651 	// Fill
652 	memset (sfx, 0, sizeof (sfx_t));
653 	Q_strncpyz (sfx->name, outName, sizeof (sfx->name));
654 	sfx->hashValue = Com_HashFileName (sfx->name, MAX_SFX_HASH);
655 
656 	// Bump
657 	sfx->touchFrame = snd_registrationFrame;
658 
659 	// Link it in
660 	sfx->hashNext = snd_sfxHashList[sfx->hashValue];
661 	snd_sfxHashList[sfx->hashValue] = sfx;
662 
663 	return sfx;
664 }
665 
666 
667 /*
668 ==================
669 Snd_AliasName
670 ==================
671 */
Snd_AliasName(char * aliasName,char * trueName)672 static sfx_t *Snd_AliasName (char *aliasName, char *trueName)
673 {
674 	sfx_t	*sfx;
675 	int		len;
676 
677 	len = strlen (trueName);
678 	if (len+1 >= MAX_QPATH)
679 		Com_Error (ERR_FATAL, "Snd_AliasName: Sound name too long: %s", trueName);
680 
681 	// Find a free sfx
682 	sfx = Snd_FindSpot ();
683 
684 	memset (sfx, 0, sizeof (sfx_t));
685 
686 	// Fill
687 	Q_strncpyz (sfx->name, aliasName, sizeof (sfx->name));
688 	sfx->trueName = Mem_PoolStrDup (trueName, cl_soundSysPool, 0);
689 	sfx->hashValue = Com_HashFileName (sfx->name, MAX_SFX_HASH);
690 
691 	// Bump
692 	sfx->touchFrame = snd_registrationFrame;
693 
694 	// Link it in
695 	sfx->hashNext = snd_sfxHashList[sfx->hashValue];
696 	snd_sfxHashList[sfx->hashValue] = sfx;
697 
698 	return sfx;
699 }
700 
701 
702 /*
703 =====================
704 Snd_BeginRegistration
705 =====================
706 */
Snd_BeginRegistration(void)707 void Snd_BeginRegistration (void)
708 {
709 	snd_registrationFrame++;
710 }
711 
712 
713 /*
714 ==================
715 Snd_RegisterSound
716 ==================
717 */
Snd_RegisterSound(char * name)718 sfx_t *Snd_RegisterSound (char *name)
719 {
720 	sfx_t	*sfx;
721 
722 	if (!snd_isInitialized)
723 		return NULL;
724 
725 	sfx = Snd_FindName (name, qTrue);
726 	Snd_LoadSound (sfx);
727 
728 	return sfx;
729 }
730 
731 
732 /*
733 ===============
734 Snd_RegisterSexedSound
735 ===============
736 */
Snd_RegisterSexedSound(char * base,int entNum)737 static struct sfx_s *Snd_RegisterSexedSound (char *base, int entNum)
738 {
739 	char			model[MAX_QPATH];
740 	char			sexedFilename[MAX_QPATH];
741 	char			maleFilename[MAX_QPATH];
742 	int				n;
743 	struct sfx_s	*sfx;
744 	char			*p;
745 	fileHandle_t	fileNum;
746 
747 	// Determine what model the client is using
748 	model[0] = 0;
749 	n = CS_PLAYERSKINS + entNum - 1;
750 	if (cl.configStrings[n][0]) {
751 		p = strchr (cl.configStrings[n], '\\');
752 		if (p) {
753 			p += 1;
754 			Q_strncpyz (model, p, sizeof (model));
755 			p = strchr (model, '/');
756 			if (p)
757 				*p = 0;
758 		}
759 	}
760 
761 	// If we can't figure it out, they're male
762 	if (!model[0])
763 		Q_strncpyz (model, "male", sizeof (model));
764 
765 	// See if we already know of the model specific sound
766 	Q_snprintfz (sexedFilename, sizeof (sexedFilename), "#players/%s/%s", model, base+1);
767 	sfx = Snd_FindName (sexedFilename, qFalse);
768 
769 	if (!sfx) {
770 		// No, so see if it exists
771 		FS_OpenFile (&sexedFilename[1], &fileNum, FS_MODE_READ_BINARY);
772 		if (fileNum) {
773 			// Yes, close the file and register it
774 			FS_CloseFile (fileNum);
775 			sfx = Snd_RegisterSound (sexedFilename);
776 		}
777 		else {
778 			// No, revert to the male sound
779 			Q_snprintfz (maleFilename, sizeof (maleFilename), "player/male/%s", base+1);
780 			sfx = Snd_AliasName (sexedFilename, maleFilename);
781 		}
782 	}
783 
784 	return sfx;
785 }
786 
787 
788 /*
789 =====================
790 Snd_EndRegistration
791 =====================
792 */
Snd_EndRegistration(void)793 void Snd_EndRegistration (void)
794 {
795 	sfx_t	*sfx;
796 	int		i, released;
797 
798 	// Free untouched sounds and make sure it is paged in
799 	released = 0;
800 	for (i=0, sfx=snd_sfxList ; i<snd_numSFX ; i++, sfx++) {
801 		if (!sfx->name[0])
802 			continue;
803 		if (sfx->touchFrame == snd_registrationFrame)
804 			continue;
805 
806 		Snd_FreeSound (sfx);
807 		released++;
808 	}
809 	Com_Printf (0, "sounds released: %i\n", released);
810 }
811 
812 /*
813 ==============================================================================
814 
815 	INIT / SHUTDOWN
816 
817 ==============================================================================
818 */
819 
820 static void	*cmd_snd_restart;
821 
822 static void	*cmd_play;
823 static void	*cmd_stopSound;
824 static void	*cmd_soundList;
825 static void	*cmd_soundInfo;
826 
827 
828 /*
829 ================
830 Snd_Restart
831 
832 Restart the sound subsystem so it can pick up new parameters and flush all sounds
833 ================
834 */
Snd_Restart(void)835 void Snd_Restart (void)
836 {
837 	Snd_Shutdown ();
838 	Snd_Init ();
839 
840 	Snd_BeginRegistration ();
841 	CL_SoundMediaInit ();
842 	Snd_EndRegistration ();
843 }
844 
845 
846 /*
847 ================
848 Snd_CheckChanges
849 
850 Forces a sound restart now
851 ================
852 */
Snd_CheckChanges(void)853 void Snd_CheckChanges (void)
854 {
855 	if (snd_queueRestart) {
856 		snd_queueRestart = qFalse;
857 		Snd_Restart ();
858 	}
859 }
860 
861 
862 /*
863 ================
864 Snd_Init
865 
866 If already initialized the sound system will restart
867 ================
868 */
Snd_Init(void)869 void Snd_Init (void)
870 {
871 	uint32	initTime;
872 
873 	if (snd_isInitialized)
874 		return;
875 
876 	Com_Printf (0, "\n--------- Sound Initialization ---------\n");
877 
878 	Cvar_GetLatchedVars (CVAR_LATCH_AUDIO);
879 
880 	snd_isInitialized = qFalse;
881 	snd_isDMA = qFalse;
882 	snd_isAL = qFalse;
883 	snd_queueRestart = qFalse;
884 	snd_registrationFrame = 1;
885 
886 	s_initSound			= Cvar_Register ("s_initSound",			"1",			CVAR_ARCHIVE|CVAR_LATCH_AUDIO);
887 	s_volume			= Cvar_Register ("s_volume",			"0.7",			CVAR_ARCHIVE);
888 	s_loadas8bit		= Cvar_Register ("s_loadas8bit",		"0",			CVAR_ARCHIVE|CVAR_LATCH_AUDIO);
889 
890 	s_khz				= Cvar_Register ("s_khz",				"11",			CVAR_ARCHIVE|CVAR_LATCH_AUDIO);
891 	s_mixahead			= Cvar_Register ("s_mixahead",			"0.2",			CVAR_ARCHIVE);
892 	s_show				= Cvar_Register ("s_show",				"0",			CVAR_CHEAT);
893 	s_testsound			= Cvar_Register ("s_testsound",			"0",			0);
894 	s_primary			= Cvar_Register ("s_primary",			"0",			CVAR_ARCHIVE|CVAR_LATCH_AUDIO);	// win32 specific
895 
896 	if (s_initSound->intVal == 2) {
897 		al_allowExtensions	= Cvar_Register ("al_allowExtensions",	"1",			CVAR_ARCHIVE|CVAR_LATCH_AUDIO);
898 		al_device			= Cvar_Register ("al_device",			"",				CVAR_ARCHIVE);
899 		al_dopplerFactor	= Cvar_Register ("al_dopplerFactor",	"1",			CVAR_ARCHIVE);
900 		al_dopplerVelocity	= Cvar_Register ("al_dopplerVelocity",	"16384",		CVAR_ARCHIVE);
901 		al_driver			= Cvar_Register ("al_driver",			AL_DRIVERNAME,	CVAR_ARCHIVE|CVAR_LATCH_AUDIO);
902 		al_errorCheck		= Cvar_Register ("al_errorCheck",		"1",			CVAR_ARCHIVE);
903 		al_ext_eax2			= Cvar_Register ("al_ext_eax2",			"1",			CVAR_ARCHIVE|CVAR_LATCH_AUDIO);
904 		al_gain				= Cvar_Register ("al_gain",				"5",			CVAR_ARCHIVE);
905 		al_minDistance		= Cvar_Register ("al_minDistance",		"100",			CVAR_ARCHIVE);
906 		al_maxDistance		= Cvar_Register ("al_maxDistance",		"8192",			CVAR_ARCHIVE);
907 		al_rollOffFactor	= Cvar_Register ("al_rollOffFactor",	"0.8",			CVAR_ARCHIVE);
908 	}
909 
910 	/*
911 	 * We need to keep the snd_restart command even if the sound subsystem
912 	 * is not started, because there has to be a way to start it.
913 	 */
914 	if (snd_isFirstInit) {
915 		cmd_snd_restart = Cmd_AddCommand ("snd_restart",	Snd_Restart_f,		"Restarts the audio subsystem");
916 		snd_isFirstInit = qFalse;
917 	}
918 
919 	cmd_play		= Cmd_AddCommand ("play",			Snd_Play_f,			"Plays a sound");
920 	cmd_stopSound	= Cmd_AddCommand ("stopsound",		Snd_StopAllSounds,	"Stops all currently playing sounds");
921 	cmd_soundList	= Cmd_AddCommand ("soundlist",		Snd_SoundList_f,	"Prints out a list of loaded sound files");
922 	cmd_soundInfo	= Cmd_AddCommand ("soundinfo",		Snd_SoundInfo_f,	"Prints out information on sound subsystem");
923 
924 	/*
925 	 * Make Snd_Shutdown() abort the startup if necessary (it quits when
926 	 * the subsystem is not initialized, so make it think the opposite).
927 	 */
928 	snd_isInitialized = qTrue;
929 
930 	if (!s_initSound->intVal) {
931 		Com_Printf (0, "...not initializing\n");
932 		Com_Printf (0, "----------------------------------------\n");
933 		Snd_Shutdown();
934 		return;
935 	}
936 
937 	// Initialize sound
938 	initTime = Sys_UMilliseconds ();
939 	if (s_initSound->intVal == 2) {
940 		if (ALSnd_Init ()) {
941 			snd_isAL = qTrue;
942 		}
943 		else {
944 			Com_Printf (PRNT_ERROR, "Snd_Init: Failed to initialize OpenAL!\n");
945 		}
946 	}
947 	if (!snd_isAL) {
948 		if (!DMASnd_Init()) {
949 			Snd_Shutdown();
950 			return;
951 		}
952 		snd_isDMA = qTrue;
953 	}
954 
955 	Snd_StopAllSounds ();
956 
957 	Com_Printf (0, "----------------------------------------\n");
958 
959 	// Check memory integrity
960 	Mem_CheckPoolIntegrity (cl_soundSysPool);
961 
962 	Com_Printf (0, "init time: %ums\n", Sys_UMilliseconds()-initTime);
963 	Com_Printf (0, "----------------------------------------\n");
964 }
965 
966 
967 /*
968 ================
969 Snd_Shutdown
970 ================
971 */
Snd_Shutdown(void)972 void Snd_Shutdown (void)
973 {
974 	uint32	size;
975 
976 	if (!snd_isInitialized)
977 		return;
978 
979 	Cmd_RemoveCommand ("play", cmd_play);
980 	Cmd_RemoveCommand ("stopsound", cmd_stopSound);
981 	Cmd_RemoveCommand ("soundlist", cmd_soundList);
982 	Cmd_RemoveCommand ("soundinfo", cmd_soundInfo);
983 
984 	Com_Printf (0, "\n------------ Sound Shutdown ------------\n");
985 
986 	// Stop all sounds
987 	Snd_StopAllSounds();
988 
989 	// Free all sounds
990 	Snd_FreeSounds ();
991 
992 	// Free all memory
993 	size = Mem_PoolSize (cl_soundSysPool);
994 	Com_Printf (0, "...releasing %u bytes\n", size);
995 	Mem_FreePool (cl_soundSysPool);
996 
997 	// Shutdown the subsystem
998 	if (snd_isDMA) {
999 		DMASnd_Shutdown ();
1000 		snd_isDMA = qFalse;
1001 	}
1002 	else if (snd_isAL) {
1003 		ALSnd_Shutdown ();
1004 		snd_isAL = qFalse;
1005 	}
1006 
1007 	snd_isInitialized = qFalse;
1008 
1009 	Com_Printf (0, "----------------------------------------\n");
1010 }
1011 
1012 
1013 /*
1014 ================
1015 Snd_FreeSounds
1016 ================
1017 */
Snd_FreeSounds(void)1018 void Snd_FreeSounds (void)
1019 {
1020 	int		i;
1021 	sfx_t	*sfx;
1022 
1023 	for (i=0, sfx=snd_sfxList ; i<snd_numSFX ; i++, sfx++) {
1024 		if (!sfx->name[0])
1025 			continue;
1026 		Snd_FreeSound (sfx);
1027 	}
1028 
1029 	snd_numSFX = 0;
1030 	memset (snd_sfxList, 0, sizeof (snd_sfxList));
1031 	memset (snd_sfxHashList, 0, sizeof (snd_sfxHashList));
1032 }
1033 
1034 
1035 /*
1036 ===============================================================================
1037 
1038 	PLAYSOUNDS
1039 
1040 ===============================================================================
1041 */
1042 
1043 /*
1044 =================
1045 Snd_AllocPlaysound
1046 =================
1047 */
Snd_AllocPlaysound(void)1048 static playSound_t *Snd_AllocPlaysound (void)
1049 {
1050 	playSound_t	*ps;
1051 
1052 	ps = snd_freePlays.next;
1053 	if (ps == &snd_freePlays)
1054 		return NULL;	// No free playsounds
1055 
1056 	// Unlink from freelist
1057 	ps->prev->next = ps->next;
1058 	ps->next->prev = ps->prev;
1059 
1060 	return ps;
1061 }
1062 
1063 
1064 /*
1065 =================
1066 Snd_FreePlaysound
1067 =================
1068 */
Snd_FreePlaysound(playSound_t * ps)1069 void Snd_FreePlaysound (playSound_t *ps)
1070 {
1071 	// Unlink from channel
1072 	ps->prev->next = ps->next;
1073 	ps->next->prev = ps->prev;
1074 
1075 	// Add to free list
1076 	ps->next = snd_freePlays.next;
1077 	snd_freePlays.next->prev = ps;
1078 	ps->prev = &snd_freePlays;
1079 	snd_freePlays.next = ps;
1080 }
1081 
1082 /*
1083 ===============================================================================
1084 
1085 	SOUND PLAYING
1086 
1087 ===============================================================================
1088 */
1089 
1090 /*
1091 ====================
1092 Snd_StartSound
1093 
1094 Validates the parms and ques the sound up
1095 If origin is NULL, the sound will be dynamically sourced from the entity
1096 entChannel 0 will never override a playing sound
1097 ====================
1098 */
Snd_StartSound(vec3_t origin,int entNum,entChannel_t entChannel,struct sfx_s * sfx,float volume,float attenuation,float timeOffset)1099 void Snd_StartSound (vec3_t origin, int entNum, entChannel_t entChannel, struct sfx_s *sfx, float volume, float attenuation, float timeOffset)
1100 {
1101 	sfxCache_t	*sc;
1102 	playSound_t	*ps, *sort;
1103 	int			start;
1104 	static int	beginOfs = 0;
1105 
1106 	if (!snd_isInitialized || !snd_isActive)
1107 		return;
1108 	if (!sfx)
1109 		return;
1110 
1111 	if (sfx->name[0] == '*')
1112 		sfx = Snd_RegisterSexedSound (sfx->name, entNum);
1113 
1114 	// Make sure the sound is loaded
1115 	sc = Snd_LoadSound (sfx);
1116 	if (!sc)
1117 		return;		// Couldn't load the sound's data
1118 
1119 	// Make the playSound_t
1120 	ps = Snd_AllocPlaysound ();
1121 	if (!ps)
1122 		return;
1123 
1124 	// Sanity check
1125 	if (entNum < 0 || entNum >= MAX_CS_EDICTS) {
1126 		Com_Printf (PRNT_ERROR, "Snd_StartSound: invalid entNum (%i), forcing 0", entNum);
1127 		entNum = 0;
1128 	}
1129 	if (entChannel < 0) {
1130 		Com_Printf (PRNT_ERROR, "Snd_StartSound: invalid entChannel (%i), forcing 0", entChannel);
1131 		entChannel = 0;
1132 	}
1133 	if (attenuation < ATTN_NONE || attenuation > ATTN_STATIC) {
1134 		Com_Printf (PRNT_ERROR, "Snd_StartSound: invalid attenuation (%i), forcing normal (%i)", attenuation, ATTN_NORM);
1135 		attenuation = ATTN_NORM;
1136 	}
1137 
1138 	// Set the origin type
1139 	if (origin) {
1140 		Vec3Copy (origin, ps->origin);
1141 		ps->type = PSND_FIXED;
1142 	}
1143 	else if (entNum == cl.playerNum+1)
1144 		ps->type = PSND_LOCAL;
1145 	else
1146 		ps->type = PSND_ENTITY;
1147 
1148 	// Volume
1149 	ps->volume = Q_rint (volume * 255);
1150 	ps->volume = clamp (ps->volume, 0, 255);
1151 
1152 	// Other fields
1153 	ps->entNum = entNum;
1154 	ps->entChannel = entChannel;
1155 	ps->attenuation = attenuation;
1156 	ps->sfx = sfx;
1157 
1158 	// Drift beginOfs
1159 	if (snd_isDMA) {
1160 		start = cl.frame.serverTime * 0.001f * snd_audioDMA.speed + beginOfs;
1161 		if (start < snd_dmaPaintedTime) {
1162 			start = snd_dmaPaintedTime;
1163 			beginOfs = start - (cl.frame.serverTime * 0.001f * snd_audioDMA.speed);
1164 		}
1165 		else if (start > snd_dmaPaintedTime + 0.3f * snd_audioDMA.speed) {
1166 			start = snd_dmaPaintedTime + 0.1f * snd_audioDMA.speed;
1167 			beginOfs = start - (cl.frame.serverTime * 0.001f * snd_audioDMA.speed);
1168 		}
1169 		else
1170 			beginOfs -= 10;
1171 
1172 		if (!timeOffset)
1173 			ps->beginTime = snd_dmaPaintedTime;
1174 		else
1175 			ps->beginTime = start + timeOffset * snd_audioDMA.speed;
1176 	}
1177 	else if (snd_isAL) {
1178 		// FIXME: 3000 seems like an odd number, but it comes closest to matching DMA delays...
1179 		ps->beginTime = cls.realTime + (timeOffset * 3000);
1180 	}
1181 
1182 	// Sort into the pending sound list
1183 	for (sort=snd_pendingPlays.next ; sort != &snd_pendingPlays && sort->beginTime < ps->beginTime ; sort=sort->next) ;
1184 
1185 	ps->next = sort;
1186 	ps->prev = sort->prev;
1187 
1188 	ps->next->prev = ps;
1189 	ps->prev->next = ps;
1190 }
1191 
1192 
1193 /*
1194 ==================
1195 Snd_StartLocalSound
1196 ==================
1197 */
Snd_StartLocalSound(struct sfx_s * sfx,float volume)1198 void Snd_StartLocalSound (struct sfx_s *sfx, float volume)
1199 {
1200 	Snd_StartSound (NULL, cl.playerNum+1, CHAN_AUTO, sfx, volume, ATTN_NONE, 0);
1201 }
1202 
1203 
1204 /*
1205 ==================
1206 Snd_StopAllSounds
1207 ==================
1208 */
Snd_StopAllSounds(void)1209 void Snd_StopAllSounds (void)
1210 {
1211 	int		i;
1212 
1213 	if (!snd_isInitialized)
1214 		return;
1215 
1216 	// Clear all the playsounds
1217 	memset (snd_playSounds, 0, sizeof (snd_playSounds));
1218 	snd_freePlays.next = snd_freePlays.prev = &snd_freePlays;
1219 	snd_pendingPlays.next = snd_pendingPlays.prev = &snd_pendingPlays;
1220 
1221 	for (i=0 ; i<MAX_PLAYSOUNDS ; i++) {
1222 		snd_playSounds[i].prev = &snd_freePlays;
1223 		snd_playSounds[i].next = snd_freePlays.next;
1224 		snd_playSounds[i].prev->next = &snd_playSounds[i];
1225 		snd_playSounds[i].next->prev = &snd_playSounds[i];
1226 	}
1227 
1228 	// Hand off to the implementation
1229 	if (snd_isDMA) {
1230 		DMASnd_StopAllSounds ();
1231 	}
1232 	else if (snd_isAL) {
1233 		ALSnd_StopAllSounds ();
1234 	}
1235 }
1236 
1237 /*
1238 ===============================================================================
1239 
1240 	RAW SAMPLING
1241 
1242 	Cinematic streaming and voice over network
1243 
1244 ===============================================================================
1245 */
1246 
1247 /*
1248 ============
1249 Snd_RawStart
1250 ============
1251 */
Snd_RawStart(void)1252 struct channel_s *Snd_RawStart (void)
1253 {
1254 	if (!snd_isInitialized || !snd_isAL)
1255 		return NULL;
1256 
1257 	return ALSnd_RawStart ();
1258 }
1259 
1260 
1261 /*
1262 ============
1263 Snd_RawSamples
1264 ============
1265 */
Snd_RawSamples(struct channel_s * rawChannel,int samples,int rate,int width,int channels,byte * data)1266 void Snd_RawSamples (struct channel_s *rawChannel, int samples, int rate, int width, int channels, byte *data)
1267 {
1268 	if (!snd_isInitialized)
1269 		return;
1270 
1271 	if (snd_isDMA)
1272 		DMASnd_RawSamples (samples, rate, width, channels, data);
1273 	else if (snd_isAL)
1274 		ALSnd_RawSamples (rawChannel, samples, rate, width, channels, data);
1275 }
1276 
1277 
1278 /*
1279 ============
1280 Snd_RawStop
1281 ============
1282 */
Snd_RawStop(struct channel_s * rawChannel)1283 void Snd_RawStop (struct channel_s *rawChannel)
1284 {
1285 	if (!snd_isInitialized || !snd_isAL)
1286 		return;
1287 
1288 	ALSnd_RawStop (rawChannel);
1289 }
1290 
1291 /*
1292 ===============================================================================
1293 
1294 	CHANNEL MIXING
1295 
1296 ===============================================================================
1297 */
1298 
1299 
1300 /*
1301 ============
1302 Snd_Update
1303 
1304 Called once each time through the main loop
1305 ============
1306 */
Snd_Update(refDef_t * rd)1307 void Snd_Update (refDef_t *rd)
1308 {
1309 	if (!snd_isInitialized)
1310 		return;
1311 
1312 	if (snd_isDMA)
1313 		DMASnd_Update (rd);
1314 	else if (snd_isAL)
1315 		ALSnd_Update (rd);
1316 }
1317