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