1 /* Patrick 5/6/97 -------------------------------------------------------------
2   AvP sound management source
3   ----------------------------------------------------------------------------*/
4 
5 #define DB_LEVEL 1
6 
7 #include <stdio.h>
8 
9 #include "3dc.h"
10 #include "module.h"
11 #include "inline.h"
12 #include "stratdef.h"
13 #include "gamedef.h"
14 
15 #include "psndplat.h"
16 #define UseLocalAssert Yes
17 #include "ourasert.h"
18 #include "db.h"
19 #include "showcmds.h"
20 #include "avp_userprofile.h"
21 #include "cdplayer.h"
22 
23 /* Patrick 5/6/97 -------------------------------------------------------------
24   Internal globals
25   ----------------------------------------------------------------------------*/
26 int SoundSwitchedOn = 0;
27 static int SoundInitialised = 0;
28 static int GlobalVolume = VOLUME_DEFAULT;
29 extern int DebuggingCommandsActive;
30 
31 
32 int EffectsSoundVolume=VOLUME_DEFAULT;
33 
34 static int MasterVolumeFadeLevel;
35 static enum FADE_STATUS_ID {FADE_STATUS_READY, FADE_STATUS_UP, FADE_STATUS_DOWN, FADE_STATUS_DOWN_FAST} MasterVolumeFadeStatus = FADE_STATUS_READY;
36 
37 
38 static unsigned int Sound_MaxActive_HW = 0;
39 
40 static void HandleFadingLevel(void);
41 
42 /* Patrick 5/6/97 -------------------------------------------------------------
43   Internal functions
44   ----------------------------------------------------------------------------*/
45 static int FindFreeActiveSound(unsigned int min, unsigned int max);
46 static int FindLowerPriorityActiveSound(ACTIVESOUNDPRIORITY testPriority, unsigned int min, unsigned int max);
47 
48 /* Patrick 5/6/97 -------------------------------------------------------------
49   External refernces
50   ----------------------------------------------------------------------------*/
51 extern int NormalFrameTime;
52 extern int GlobalFrameCounter;
53 
54 
55 /* Patrick 5/6/97 -------------------------------------------------------------
56   Sound system functions
57   ----------------------------------------------------------------------------*/
SoundSys_Start(void)58 void SoundSys_Start(void)
59 {
60 	int i;
61 
62 	/* if we have already switched on, so do nothing */
63 	if(SoundSwitchedOn) return;
64 	/* we are not switched on, but we are initialised, so do nothing */
65 	if(SoundInitialised) return;
66 
67 	/* initialise game sounds and active instances*/
68 	for(i=0;i<SID_MAXIMUM;i++) GameSounds[i] = BlankGameSound;
69 	for(i=0;i<SOUND_MAXACTIVE;i++) ActiveSounds[i] = BlankActiveSound;
70 
71 	/* try to initialise sound, and turn on */
72 	SoundInitialised = PlatStartSoundSys();
73 	Sound_MaxActive_HW = SOUND_MAXACTIVE_SW + PlatMaxHWSounds();
74 	if(Sound_MaxActive_HW > SOUND_MAXACTIVE)
75 	{
76 		Sound_MaxActive_HW = SOUND_MAXACTIVE;
77 	}
78 	SoundSys_SwitchOn();
79 
80 	/* cancel any fades */
81 
82 
83 	/* set global volume */
84 	GlobalVolume = VOLUME_DEFAULT;
85 	PlatChangeGlobalVolume(VOLUME_DEFAULT);
86 
87 
88 }
89 
SoundSys_End(void)90 void SoundSys_End(void)
91 {
92 	/* end only if we are initialised, regardless of whether we are switched on */
93 	if(!SoundInitialised) return;
94 
95 	/* stop and remove all sounds */
96 	SoundSys_RemoveAll();
97 
98 	/* switch off, and de-initillise */
99 	PlatEndSoundSys();
100 	SoundSys_SwitchOff();
101 	SoundInitialised = 0; /* forces call to Soundsys_Start to re-start sound system */
102 }
103 
SoundSys_Management(void)104 void SoundSys_Management(void)
105 {
106 	int i;
107 	int numActive = 0;
108 	int num3dUpdates = 0;
109 
110 	if(!SoundSwitchedOn) return;
111 
112 	/* go through all the active sounds */
113 	for(i=0;i<SOUND_MAXACTIVE;i++)
114 	{
115 		if(ActiveSounds[i].soundIndex==SID_NOSOUND) continue; /* empty slot */
116 		numActive++;
117 
118 		if(PlatSoundHasStopped(i) && !ActiveSounds[i].paused)
119 		{
120 			Sound_Stop(i);
121 			continue;
122 		}
123 		if(ActiveSounds[i].threedee)
124 		{
125 			PlatDo3dSound(i);
126 			num3dUpdates++;
127 		}
128 	}
129 
130 	HandleFadingLevel();
131 
132 	{
133 		int requestedVolume = MUL_FIXED(EffectsSoundVolume,MasterVolumeFadeLevel);
134 		if (requestedVolume != GlobalVolume)
135 		{
136 			SoundSys_ChangeVolume(requestedVolume);
137 		}
138 
139 	}
140 	CheckCDVolume();
141 
142 	PlatUpdatePlayer();
143 	if (ShowDebuggingText.Sounds)
144 	{
145 		int i = Sound_MaxActive_HW;
146 		PrintDebuggingText("Number of Active Sounds %u \n", SoundNumActiveVoices());
147 		//display a list of all sounds being played as well
148 		while(i-- > 0)
149 		{
150 			if(ActiveSounds[i].soundIndex != SID_NOSOUND)
151 			{
152 				PrintDebuggingText("%s\n",GameSounds[ActiveSounds[i].soundIndex].wavName);
153 			}
154 		}
155 
156 	}
157 
158    	if(WARPSPEED_CHEATMODE || JOHNWOO_CHEATMODE || DebuggingCommandsActive)
159    		UpdateSoundFrequencies();
160 }
161 
SoundSys_ResetFadeLevel(void)162 extern void SoundSys_ResetFadeLevel(void)
163 {
164 	MasterVolumeFadeLevel = ONE_FIXED;
165 	MasterVolumeFadeStatus = FADE_STATUS_READY;
166 }
167 
SoundSys_FadeIn(void)168 extern void SoundSys_FadeIn(void)
169 {
170 	/* always fade in from silence ? */
171 	MasterVolumeFadeLevel = ONE_FIXED/2;
172 	MasterVolumeFadeStatus = FADE_STATUS_UP;
173 }
SoundSys_FadeOut(void)174 extern void SoundSys_FadeOut(void)
175 {
176 	MasterVolumeFadeStatus = FADE_STATUS_DOWN;
177 }
SoundSys_FadeOutFast(void)178 extern void SoundSys_FadeOutFast(void)
179 {
180 	MasterVolumeFadeStatus = FADE_STATUS_DOWN_FAST;
181 }
HandleFadingLevel(void)182 static void HandleFadingLevel(void)
183 {
184 	switch (MasterVolumeFadeStatus)
185 	{
186 		default:
187 		case FADE_STATUS_READY:
188 			break;
189 
190 		case FADE_STATUS_UP:
191 		{
192 			MasterVolumeFadeLevel+=NormalFrameTime/2;
193 			if (MasterVolumeFadeLevel>ONE_FIXED)
194 			{
195 				MasterVolumeFadeLevel = ONE_FIXED;
196 				MasterVolumeFadeStatus = FADE_STATUS_READY;
197 			}
198 			break;
199 		}
200 		case FADE_STATUS_DOWN:
201 		{
202 			MasterVolumeFadeLevel-=NormalFrameTime/8;
203 			if (MasterVolumeFadeLevel<0)
204 			{
205 				MasterVolumeFadeLevel = 0;
206 				MasterVolumeFadeStatus = FADE_STATUS_READY;
207 			}
208 			break;
209 		}
210 		case FADE_STATUS_DOWN_FAST:
211 		{
212 			MasterVolumeFadeLevel-=NormalFrameTime;
213 			if (MasterVolumeFadeLevel<0)
214 			{
215 				MasterVolumeFadeLevel = 0;
216 				MasterVolumeFadeStatus = FADE_STATUS_READY;
217 			}
218 			break;
219 		}
220 	}
221 }
SoundSys_PauseOn(void)222 void SoundSys_PauseOn(void)
223 {
224 	int i;
225 
226 	/* if we're not switched on, should be nothing playing */
227 	if(!SoundSwitchedOn) return;
228 
229 	for(i=0;i<SOUND_MAXACTIVE;i++)
230 	{
231 		if(ActiveSounds[i].soundIndex!=SID_NOSOUND) ActiveSounds[i].paused = 1;
232 	}
233 }
234 
SoundSys_PauseOff(void)235 void SoundSys_PauseOff(void)
236 {
237 	int i;
238 
239 	/* if we're not switched on, should be nothing playing */
240 	if(!SoundSwitchedOn) return;
241 
242 	for(i=0;i<SOUND_MAXACTIVE;i++)
243 	{
244 		if(ActiveSounds[i].soundIndex!=SID_NOSOUND) ActiveSounds[i].paused = 0;
245 	}
246 }
247 
SoundSys_StopAll(void)248 void SoundSys_StopAll(void)
249 {
250 	int i;
251 
252 	/* if we're not switched on, should be nothing playing */
253 	if(!SoundSwitchedOn) return;
254 
255 	for(i=0;i<SOUND_MAXACTIVE;i++)
256 	{
257 		if(ActiveSounds[i].soundIndex!=SID_NOSOUND) Sound_Stop(i);
258 	}
259 }
260 
SoundSys_RemoveAll(void)261 void SoundSys_RemoveAll(void)
262 {
263 	int i;
264 
265 	/* if we are not initialised, there should be no sounds loaded or playing.
266 	if we are switched off, we should still unload them all */
267 	if(!SoundInitialised) return;
268 
269 	/* make sure there are no sounds playing */
270 	SoundSys_StopAll();
271 
272 	/* deallocate all sounds */
273 	for(i=0;i<SID_MAXIMUM;i++)
274 	{
275 		if(GameSounds[i].loaded)
276 		{
277 			LOCALASSERT(GameSounds[i].activeInstances==0);
278 			PlatEndGameSound(i);
279 			GameSounds[i] = BlankGameSound;
280 		}
281 	}
282 }
283 
SoundSys_SwitchOn(void)284 void SoundSys_SwitchOn(void)
285 {
286 	/* if already switched on, nothing to do*/
287 	if(SoundSwitchedOn) return;
288 	/* if not initialised, can't switch on */
289 	if(!SoundInitialised) return;
290 
291 	SoundSwitchedOn = 1;
292 	/* initialise global volume controls */
293 	GlobalVolume = VOLUME_DEFAULT;
294 	MasterVolumeFadeLevel = ONE_FIXED;
295 	MasterVolumeFadeStatus = FADE_STATUS_READY;
296 }
297 
SoundSys_SwitchOff(void)298 void SoundSys_SwitchOff(void)
299 {
300 	/* if already switched off, nothing to do*/
301 	if(!SoundSwitchedOn) return;
302 
303 	SoundSys_StopAll();
304 	SoundSwitchedOn = 0;
305 }
306 
SoundSys_IsOn(void)307 int SoundSys_IsOn(void)
308 {
309 	return SoundSwitchedOn;
310 }
311 
SoundSys_ChangeVolume(int volume)312 void SoundSys_ChangeVolume(int volume)
313 {
314 	int newVolume, ok;
315 
316 	if(!SoundSwitchedOn) return;
317 	/* validate argument */
318 	newVolume = volume;
319 	if(newVolume>VOLUME_MAX) newVolume = VOLUME_MAX;
320 	if(newVolume<VOLUME_MIN) newVolume = VOLUME_MIN;
321 
322 	if (newVolume==GlobalVolume) return;
323 
324 	/* set global volume */
325 	GlobalVolume = newVolume;
326 	/* call the platform function: if we get back an error, ignore it */
327 	ok = PlatChangeGlobalVolume(newVolume);
328 }
329 
330 
331 /* Patrick 5/6/97 -------------------------------------------------------------
332   Functions for playing and controlling individual sounds
333   ----------------------------------------------------------------------------*/
Sound_Play(SOUNDINDEX soundNumber,char * format,...)334 void Sound_Play(SOUNDINDEX soundNumber, char *format, ...)
335 {
336 	int newIndex;
337 	int loop = 0;
338 	int	*externalRef = NULL;
339 	ACTIVESOUNDPRIORITY priority = ASP_Minimum;
340 	SOUND3DDATA * p_3ddata = 0;
341 	VECTORCH * worldPosn = 0;
342 	int volume;
343 	int pitch;
344 	int marine_ignore;
345 	int reverb_off = 0;
346 	int soundStartPosition = 0;
347 
348 	{
349 		extern int PlaySounds;
350 		if (!PlaySounds) return;
351 	}
352 
353 	if(!SoundSwitchedOn) return;
354 
355 
356 	/* check soundIndex for bounds, whether it has been loaded, and number of instances */
357 	if((soundNumber<0)||(soundNumber>=SID_MAXIMUM)) return;
358 	if(!(GameSounds[soundNumber].loaded)) return;
359 	if(!(GameSounds[soundNumber].activeInstances<SOUND_MAXINSTANCES)) return;
360 
361 	db_logf5(("About to play sound %i", soundNumber));
362 
363 	/* initialise volume and pitch from game sound data */
364 	volume = GameSounds[soundNumber].volume;
365 	pitch = GameSounds[soundNumber].pitch;
366 	marine_ignore=0;
367 
368 	/* examine the format string: if it is null, ignore it */
369 	if(format)
370 	{
371 		char *nextChar = format;
372 		va_list argPtr;
373 
374 		va_start(argPtr,format);
375 		while(*nextChar!='\0')
376 		{
377 			switch(*nextChar)
378 			{
379 				case('d'):
380 				{
381 					worldPosn = va_arg(argPtr,VECTORCH*);
382 					break;
383 				}
384 				case('n'):
385 				{
386 					p_3ddata = va_arg(argPtr,SOUND3DDATA*);
387 					break;
388 				}
389 				case('e'):
390 				{
391 					externalRef = va_arg(argPtr,int*);
392 					break;
393 				}
394 				case('l'):
395 				{
396 					loop = 1;
397 					priority = ASP_Maximum;
398 					break;
399 				}
400 				case('h'):
401 				{
402 					priority = ASP_Maximum;
403 					break;
404 				}
405 				case('v'):
406 				{
407 					volume = va_arg(argPtr,int);
408 					if(volume>VOLUME_MAX) volume=VOLUME_MAX;
409 					if(volume<VOLUME_MIN) volume=VOLUME_MIN;
410 					break;
411 				}
412 				case('p'):
413 				{
414 					pitch = va_arg(argPtr,int);;
415 					if(pitch>PITCH_MAX) pitch=PITCH_MAX;
416 					if(pitch<PITCH_MIN) pitch=PITCH_MIN;
417 					break;
418 				}
419 				case('m'):
420 				{
421 					marine_ignore=1;
422 					break;
423 				}
424 				case('r'):
425 				{
426 					reverb_off = 1;
427 					break;
428 				}
429 				case('P'):
430 				{
431 					soundStartPosition = va_arg(argPtr,int);;
432 					break;
433 				}
434 				default:
435 				{
436 					break;
437 				}
438 			}
439 			nextChar++;
440 		}
441 		va_end(argPtr);
442 	}
443 
444 	/* check for invalid parameter combinations */
445 	if((loop)&&(externalRef==NULL))
446 	{
447 		db_log5("SoundPlay bad params.");
448 		return;
449 	}
450 
451 	/* Deal with resource allocation. */
452 	{
453 		/* Range of active buffers to search. */
454 		unsigned int min, max;
455 		if(GameSounds[soundNumber].flags & SAMPLE_IN_SW)
456 		{
457 			min = 0;
458 			max = SOUND_MAXACTIVE_SW;
459 		}
460 		else
461 		{
462 			min = SOUND_MAXACTIVE_SW + 1;
463 			max = Sound_MaxActive_HW;
464 		}
465 
466 		/* find free active sound slot */
467 		newIndex = FindFreeActiveSound(min, max);
468 		if(newIndex==SOUND_NOACTIVEINDEX && !(GameSounds[soundNumber].flags & SAMPLE_IN_SW))
469 		{
470 			//failed to find a free hardware slot , so try software slot instead.
471 			//mainly to cope with cards that can load sounds into hardware , but can't play them there
472 			newIndex = FindFreeActiveSound(0, SOUND_MAXACTIVE_SW);
473 
474 		}
475 		if(newIndex==SOUND_NOACTIVEINDEX)
476 		{
477 			db_log3("Having to stop another sound.");
478 			/* try to find an existing sound with a lower priority */
479 			newIndex = FindLowerPriorityActiveSound(priority, min, max);
480 			if(newIndex==SOUND_NOACTIVEINDEX && !(GameSounds[soundNumber].flags & SAMPLE_IN_SW))
481 			{
482 				//failed to find a free hardware slot , so try software slot instead.
483 				//mainly to cope with cards that can load sounds into hardware , but can't play them there
484 				newIndex = FindLowerPriorityActiveSound(priority, 0, SOUND_MAXACTIVE_SW);
485 
486 			}
487 
488 			if(newIndex==SOUND_NOACTIVEINDEX)
489 			{
490 				db_log3("Failed to find a lower priority sound.");
491 				return; /* give up */
492 			}
493 
494 			/* remove it, and use it's slot */
495 			db_log3("Stopping a lower priority sound.");
496 			Sound_Stop(newIndex);
497 		}
498 		else
499 		{
500 			db_log3("Found a free slot.");
501 		}
502 	}
503 
504 	/* fill out the active sound */
505 	ActiveSounds[newIndex].soundIndex = soundNumber;
506 	ActiveSounds[newIndex].priority = priority;
507 	ActiveSounds[newIndex].volume = volume;
508 	ActiveSounds[newIndex].pitch = pitch;
509 	ActiveSounds[newIndex].externalRef = externalRef;
510 	ActiveSounds[newIndex].loop = 1;
511 	ActiveSounds[newIndex].marine_ignore=marine_ignore;
512 	ActiveSounds[newIndex].reverb_off=reverb_off;
513 	if(loop) ActiveSounds[newIndex].loop = 1;
514 	else ActiveSounds[newIndex].loop = 0;
515 
516 #if 0
517 fprintf(stderr, "PSND: Play: new = %d. num = %d, p = %d, v = %d, pi = %d, l = %d, mi = %d, rev = %d\n", newIndex, soundNumber, priority, volume, pitch, loop, marine_ignore, reverb_off);
518 fprintf(stderr, "PSND: Play: %d %d %s l:%d\n", newIndex, soundNumber, GameSounds[soundNumber].wavName, loop);
519 #endif
520 
521 	if(worldPosn)
522 	{
523 		VECTORCH zeroPosn = {0,0,0};
524 		ActiveSounds[newIndex].threedeedata.position = *worldPosn;
525 		ActiveSounds[newIndex].threedeedata.velocity = zeroPosn;
526 		ActiveSounds[newIndex].threedeedata.inner_range = 0;
527 		ActiveSounds[newIndex].threedeedata.outer_range = 32000;
528 
529 		ActiveSounds[newIndex].threedee = 1;
530 	}
531 	else if (p_3ddata)
532 	{
533 		ActiveSounds[newIndex].threedeedata = *p_3ddata;
534 		ActiveSounds[newIndex].threedee = 1;
535 	}
536 	else
537 	{
538 		VECTORCH zeroPosn = {0,0,0};
539 		ActiveSounds[newIndex].threedeedata.position = zeroPosn;
540 		ActiveSounds[newIndex].threedeedata.velocity = zeroPosn;
541 		ActiveSounds[newIndex].threedee = 0;
542 	}
543 
544 	/* try and play the sound */
545 	{
546 		int ok = PlatPlaySound(newIndex);
547 		if(ok==SOUND_PLATFORMERROR)
548 		{
549 			/* the sound failed to play: any platform cleanups should have been done,
550 			so just bank the sound slot */
551 			ActiveSounds[newIndex] = BlankActiveSound;
552 			db_log5("Error: PlatPlaySound failed.");
553 			return;
554 		}
555 	}
556 
557 	/* finally, update the game sound instances, and external reference */
558 	GameSounds[soundNumber].activeInstances++;
559 	if(externalRef) *externalRef = newIndex;
560 
561 /* only will happen because of savegames */
562 //	if(soundStartPosition && ActiveSounds[newIndex].dsBufferP)
563 //	{
564 //		//sound starts part of the way in
565 //		IDirectSoundBuffer_SetCurrentPosition(ActiveSounds[newIndex].dsBufferP,soundStartPosition);
566 //	}
567 #if 0 /* TODO */
568 	if (soundStartPosition)
569 		fprintf(stderr, "Sound_Play: sound starts part of the way in (%d)\n", soundStartPosition);
570 #endif
571 }
572 
Sound_Stop(int activeSoundNumber)573 void Sound_Stop(int activeSoundNumber)
574 {
575 	SOUNDINDEX soundNo;
576 	int buf;
577 
578 	if(!SoundSwitchedOn) return;
579 	/* validate argument */
580 	if(activeSoundNumber<0) return;
581 	if(activeSoundNumber>=SOUND_MAXACTIVE) return;
582 
583 	/* Check there's a sound in this slot */
584 	if(ActiveSounds[activeSoundNumber].soundIndex == SID_NOSOUND) return;
585 
586 	/* update game sound instances, and external reference */
587 	soundNo = ActiveSounds[activeSoundNumber].soundIndex;
588 	GameSounds[soundNo].activeInstances--;
589 	db_assert1((GameSounds[soundNo].activeInstances>=0)&&
590 				(GameSounds[soundNo].activeInstances<SOUND_MAXINSTANCES));
591 	if(ActiveSounds[activeSoundNumber].externalRef)
592 		*(ActiveSounds[activeSoundNumber].externalRef) = SOUND_NOACTIVEINDEX;
593 
594 	/* stop the sound: it may have already stopped, of course, but never mind */
595 
596 	PlatStopSound(activeSoundNumber);
597 
598 #if 0
599 fprintf(stderr, "PSND: Stop: %d %d %s\n", activeSoundNumber, soundNo, GameSounds[soundNo].wavName);
600 #endif
601 
602 	/* release the active sound slot */
603 	buf = ActiveSounds[activeSoundNumber].ds3DBufferP;
604 	ActiveSounds[activeSoundNumber] = BlankActiveSound;
605 	ActiveSounds[activeSoundNumber].ds3DBufferP = buf;
606 }
607 
Sound_ChangeVolume(int activeSoundNumber,int volume)608 void Sound_ChangeVolume(int activeSoundNumber, int volume)
609 {
610 	int newVolume;
611 	if(!SoundSwitchedOn) return;
612 
613 	/* validate argument */
614 	if(activeSoundNumber<0) return;
615 	if(activeSoundNumber>=SOUND_MAXACTIVE) return;
616 	/* Check there's a sound in this slot */
617 	if(ActiveSounds[activeSoundNumber].soundIndex == SID_NOSOUND) return;
618 
619 	/* validate other argument */
620 	newVolume = volume;
621 	if(newVolume>VOLUME_MAX) newVolume = VOLUME_MAX;
622 	if(newVolume<VOLUME_MIN) newVolume = VOLUME_MAX;
623 
624 	/* check the new volume is different from the old one */
625 	if(volume==(ActiveSounds[activeSoundNumber].volume)) return;
626 
627 	/* set volume field in active sound */
628 	ActiveSounds[activeSoundNumber].volume = newVolume;
629 
630 	/* if we're a 2d sound, just change the volume, but if we're 3d
631 	then call 3d update instead */
632 	if(ActiveSounds[activeSoundNumber].threedee) PlatDo3dSound(activeSoundNumber);
633 	else PlatChangeSoundVolume(activeSoundNumber,ActiveSounds[activeSoundNumber].volume);
634 }
635 
Sound_ChangePitch(int activeSoundNumber,int pitch)636 void Sound_ChangePitch(int activeSoundNumber, int pitch)
637 {
638 	int newPitch;
639 	if(!SoundSwitchedOn) return;
640 
641 	/* validate argument */
642 	if(activeSoundNumber<0) return;
643 	if(activeSoundNumber>=SOUND_MAXACTIVE) return;
644 	/* Check there's a sound in this slot */
645 	if(ActiveSounds[activeSoundNumber].soundIndex == SID_NOSOUND) return;
646 
647 	/* validate other argument */
648 	newPitch = pitch;
649 	if(newPitch>PITCH_MAX) newPitch = PITCH_MAX;
650 	if(newPitch<PITCH_MIN) newPitch = PITCH_MAX;
651 
652 	/* check the new pitch is different from the old one */
653 	if(pitch==(ActiveSounds[activeSoundNumber].pitch)) return;
654 
655 	/* set pitch field in active sound, and change it... */
656 	ActiveSounds[activeSoundNumber].pitch = newPitch;
657 	PlatChangeSoundPitch(activeSoundNumber,ActiveSounds[activeSoundNumber].pitch);
658 }
659 
Sound_Update3d(int activeSoundNumber,VECTORCH * posn)660 void Sound_Update3d(int activeSoundNumber, VECTORCH* posn)
661 {
662 	if(!SoundSwitchedOn) return;
663 
664 	/* validate argument */
665 	if(activeSoundNumber<0) return;
666 	if(activeSoundNumber>=SOUND_MAXACTIVE) return;
667 
668 	/* Check there's a sound in this slot */
669 	if(ActiveSounds[activeSoundNumber].soundIndex == SID_NOSOUND) return;
670 
671 	ActiveSounds[activeSoundNumber].threedeedata.position = *posn;
672 }
673 
Sound_UpdateNew3d(int activeSoundNumber,SOUND3DDATA * s3d)674 void Sound_UpdateNew3d(int activeSoundNumber, SOUND3DDATA * s3d)
675 {
676 	if(!SoundSwitchedOn) return;
677 
678 	/* validate argument */
679 	if(activeSoundNumber<0) return;
680 	if(activeSoundNumber>=SOUND_MAXACTIVE) return;
681 
682 	/* Check there's a sound in this slot */
683 	if(ActiveSounds[activeSoundNumber].soundIndex == SID_NOSOUND) return;
684 
685 	ActiveSounds[activeSoundNumber].threedeedata = *s3d;
686 
687 }
688 
SoundNumActiveVoices()689 unsigned int SoundNumActiveVoices()
690 {
691 	int i = Sound_MaxActive_HW;
692 	int num_active = 0;
693 
694 	while(i-- > 0)
695 	{
696 		if(ActiveSounds[i].soundIndex != SID_NOSOUND)
697 		{
698 			num_active++;
699 		}
700 	}
701 
702 	return num_active;
703 }
704 
705 /* Patrick 5/6/97 -------------------------------------------------------------
706   Internal support functions
707   ----------------------------------------------------------------------------*/
FindFreeActiveSound(unsigned int min,unsigned int max)708 static int FindFreeActiveSound(unsigned int min, unsigned int max)
709 {
710 	int i;
711 	for(i = min; (i < max); i++)
712 	{
713 		if(ActiveSounds[i].soundIndex == SID_NOSOUND) return i;
714 	}
715 	return SOUND_NOACTIVEINDEX;
716 }
717 
FindLowerPriorityActiveSound(ACTIVESOUNDPRIORITY testPriority,unsigned int min,unsigned int max)718 static int FindLowerPriorityActiveSound(ACTIVESOUNDPRIORITY testPriority, unsigned int min, unsigned int max)
719 {
720 	int i;
721 	for(i = min; (i < max); i++)
722 	{
723 		if((ActiveSounds[i].soundIndex != SID_NOSOUND)&&
724 		   (ActiveSounds[i].priority < testPriority)) return i;
725 	}
726 	return SOUND_NOACTIVEINDEX;
727 }
728 
729 
730 
731 static SOUNDINDEX GetSoundIndexFromNameAndIndex(const char* name,SOUNDINDEX index);
732 
733 #include "savegame.h"
734 
735 typedef struct sound_save_block
736 {
737 	SAVE_BLOCK_HEADER header;
738 
739 	int fileNameLength;
740 
741 	SOUNDINDEX soundIndex;
742 	ACTIVESOUNDPRIORITY priority;
743 	int volume;
744 	int	pitch;
745 	unsigned int loop :1;
746 	unsigned int threedee :1;
747 	unsigned int paused :1;
748 	unsigned int marine_ignore	:1;
749 	unsigned int reverb_off :1;
750 	unsigned int externalRef :1;
751 	SOUND3DDATA threedeedata;
752 	int position;
753 }SOUND_SAVE_BLOCK;
754 
755 //defines for load/save macros
756 #define SAVELOAD_BLOCK block
757 #define SAVELOAD_BEHAV sound
758 
Load_SoundState(int * soundHandle)759 void Load_SoundState(int* soundHandle)
760 {
761 	SOUND_SAVE_BLOCK* block;
762 	const char* name;
763 	SOUNDINDEX soundIndex;
764 
765 	if(!soundHandle) return;
766 	block = (SOUND_SAVE_BLOCK*)GetNextBlockIfOfType(SaveBlock_SoundState);
767 	if(!block) return ;
768 
769 	name = (const char*)(block+1);
770 	//stop the current sound
771 	if(*soundHandle == SOUND_NOACTIVEINDEX)
772 	{
773 		Sound_Stop(*soundHandle);
774 	}
775 
776 	//check the size
777 	if(block->header.size != sizeof(*block) + block->fileNameLength) return;
778 
779 	soundIndex = GetSoundIndexFromNameAndIndex(name,block->soundIndex);
780 	if(soundIndex==SID_NOSOUND) return;
781 
782 	{
783 		char playOptions[20]="evpP";
784 
785 		if(block->loop) strcat(playOptions,"l");
786 		if(block->marine_ignore) strcat(playOptions,"m");
787 		if(block->reverb_off) strcat(playOptions,"r");
788 		if(block->priority == ASP_Maximum) strcat(playOptions,"h");
789 
790 		if(block->threedee)
791 		{
792 			strcat(playOptions,"n");
793 			Sound_Play(soundIndex,playOptions,soundHandle,block->volume,block->pitch,block->position,&block->threedeedata);
794 		}
795 		else
796 		{
797 			Sound_Play(soundIndex,playOptions,soundHandle,block->volume,block->pitch,block->position);
798 		}
799 
800 	}
801 
802 
803 }
804 
805 
Save_SoundState(int * soundHandle)806 void Save_SoundState(int* soundHandle)
807 {
808 
809 	if(!soundHandle) return;
810 
811 
812 	if(*soundHandle == SOUND_NOACTIVEINDEX)
813 	{
814 		SAVE_BLOCK_HEADER* header;
815 		GET_SAVE_BLOCK_POINTER(header);
816 
817 		//fill in the header
818 		header->size = sizeof(*header);
819 		header->type = SaveBlock_SoundState;
820 	}
821 	else
822 	{
823 		ACTIVESOUNDSAMPLE* sound = &ActiveSounds[*soundHandle];
824 
825 		SOUND_SAVE_BLOCK* block;
826 		const char* name = GameSounds[sound->soundIndex].wavName;
827 		int name_length = strlen(name) + 1;
828 
829 	   	block = GetPointerForSaveBlock(sizeof(*block)+name_length);
830 
831 		//fill in the header
832 		block->header.size = sizeof(*block) + name_length;
833 		block->header.type = SaveBlock_SoundState;
834 
835 
836 
837 		COPYELEMENT_SAVE(soundIndex)
838 		COPYELEMENT_SAVE(priority)
839 		COPYELEMENT_SAVE(volume)
840 		COPYELEMENT_SAVE(pitch)
841 		COPYELEMENT_SAVE(loop)
842 		COPYELEMENT_SAVE(threedee)
843 		COPYELEMENT_SAVE(paused)
844 		COPYELEMENT_SAVE(marine_ignore)
845 		COPYELEMENT_SAVE(reverb_off)
846 		COPYELEMENT_SAVE(threedeedata)
847 		block->externalRef = 1;
848 
849 		block->position = 0;
850 	   	block->fileNameLength = name_length;
851 
852 		//the volume in the active sound list is scaled differently from the volume used
853 		//by Sound_Play
854 		block->volume<<=7;
855 		block->volume/=VOLUME_PLAT2DSCALE;
856 
857 /* only for savegames */
858 //		if(sound->dsBufferP)
859 //			IDirectSoundBuffer_GetCurrentPosition(sound->dsBufferP,(LPDWORD)&block->position,NULL);
860 //		else
861 			block->position = 0;
862 #if 0 /* TODO */
863 fprintf(stderr, "Save_SoundState: GetCurrentPosition!\n");
864 #endif
865 		strcpy((char*)(block+1),name);
866 
867 	}
868 
869 }
870 
Load_SoundState_NoRef(SAVE_BLOCK_HEADER * header)871 void Load_SoundState_NoRef(SAVE_BLOCK_HEADER* header)
872 {
873 	SOUND_SAVE_BLOCK* block = (SOUND_SAVE_BLOCK*) header;
874 	const char* name = (const char*)(block+1);
875 	SOUNDINDEX soundIndex;
876 
877 	//check the size
878 	if(block->header.size != sizeof(*block) + block->fileNameLength) return;
879 
880 	//only load if the sound doesn't require an external reference
881 	if(block->externalRef) return;
882 
883 
884 	soundIndex = GetSoundIndexFromNameAndIndex(name,block->soundIndex);
885 	if(soundIndex==SID_NOSOUND) return;
886 
887 	{
888 		char playOptions[20]="vpP";
889 
890 		if(block->marine_ignore) strcat(playOptions,"m");
891 		if(block->reverb_off) strcat(playOptions,"r");
892 		if(block->priority == ASP_Maximum) strcat(playOptions,"h");
893 
894 		if(block->threedee)
895 		{
896 			strcat(playOptions,"n");
897 			Sound_Play(soundIndex,playOptions,block->volume,block->pitch,block->position,&block->threedeedata);
898 		}
899 		else
900 		{
901 			Sound_Play(soundIndex,playOptions,block->volume,block->pitch,block->position);
902 		}
903 	}
904 }
905 
Save_SoundsWithNoReference()906 void Save_SoundsWithNoReference()
907 {
908 	int i;
909 
910 	for(i=0;i<SOUND_MAXACTIVE;i++)
911 	{
912 		if(ActiveSounds[i].soundIndex != SID_NOSOUND)
913 		{
914 			if(!ActiveSounds[i].externalRef)
915 			{
916 				ACTIVESOUNDSAMPLE* sound = &ActiveSounds[i];
917 				SOUND_SAVE_BLOCK* block;
918 
919 				const char* name = GameSounds[sound->soundIndex].wavName;
920 				int name_length = strlen(name) + 1;
921 
922 				block = GetPointerForSaveBlock(sizeof(*block)+name_length);
923 
924 				//fill in the header
925 				block->header.size = sizeof(*block) + name_length;
926 				block->header.type = SaveBlock_SoundState;
927 
928 
929 				COPYELEMENT_SAVE(soundIndex)
930 				COPYELEMENT_SAVE(priority)
931 				COPYELEMENT_SAVE(volume)
932 				COPYELEMENT_SAVE(pitch)
933 				COPYELEMENT_SAVE(loop)
934 				COPYELEMENT_SAVE(threedee)
935 				COPYELEMENT_SAVE(paused)
936 				COPYELEMENT_SAVE(marine_ignore)
937 				COPYELEMENT_SAVE(reverb_off)
938 				COPYELEMENT_SAVE(threedeedata)
939 				block->externalRef = 0;
940 
941 				block->position = 0;
942 				block->fileNameLength = name_length;
943 
944 				//the volume in the active sound list is scaled differently from the volume used
945 				//by Sound_Play
946 				block->volume<<=7;
947 				block->volume/=VOLUME_PLAT2DSCALE;
948 
949 /* savegames */
950 //				if(sound->dsBufferP)
951 //					IDirectSoundBuffer_GetCurrentPosition(sound->dsBufferP,(LPDWORD)&block->position,NULL);
952 //				else
953 					block->position = 0;
954 #if 0 /* TODO */
955 				fprintf(stderr, "Save_SoundsWithNoReference: GetCurrentPosition!\n");
956 #endif
957 
958 				strcpy((char*)(block+1),name);
959 			}
960 		}
961 	}
962 }
963 
964 
GetSoundIndexFromNameAndIndex(const char * name,SOUNDINDEX index)965 static SOUNDINDEX GetSoundIndexFromNameAndIndex(const char* name,SOUNDINDEX index)
966 {
967 	int i;
968 	if(index>=0 && index<SID_MAXIMUM)
969 	{
970 		if(GameSounds[index].loaded)
971 		{
972 			if(!strcmp(GameSounds[index].wavName,name)) return index;
973 		}
974 
975 	}
976 
977 	for(i=0;i<SID_MAXIMUM;i++)
978 	{
979 		if(GameSounds[i].loaded)
980 		{
981 			if(!strcmp(GameSounds[i].wavName,name)) return (SOUNDINDEX) i;
982 		}
983 	}
984 	return SID_NOSOUND;
985 }
986