1 //**************************************************************************
2 //**
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
9 //**
10 //** $Id: snd_data.cpp 4327 2010-07-24 19:30:53Z firebrand_kh $
11 //**
12 //** Copyright (C) 1999-2006 Jānis Legzdiņš
13 //**
14 //** This program is free software; you can redistribute it and/or
15 //** modify it under the terms of the GNU General Public License
16 //** as published by the Free Software Foundation; either version 2
17 //** of the License, or (at your option) any later version.
18 //**
19 //** This program is distributed in the hope that it will be useful,
20 //** but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 //** GNU General Public License for more details.
23 //**
24 //**************************************************************************
25
26 // HEADER FILES ------------------------------------------------------------
27
28 #include "gamedefs.h"
29 #include "snd_local.h"
30
31 // MACROS ------------------------------------------------------------------
32
33 // TYPES -------------------------------------------------------------------
34
35 #ifdef CLIENT
36 class VRawSampleLoader : public VSampleLoader
37 {
38 public:
39 void Load(sfxinfo_t&, VStream&);
40 };
41 #endif
42
43 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
44
45 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
46
47 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
48
49 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
50
51 // PUBLIC DATA DEFINITIONS -------------------------------------------------
52
53 VSampleLoader* VSampleLoader::List;
54
55 VSoundManager* GSoundManager;
56
57 // PRIVATE DATA DEFINITIONS ------------------------------------------------
58
59 #ifdef CLIENT
60 static VRawSampleLoader RawSampleLoader;
61 #endif
62
63 // CODE --------------------------------------------------------------------
64
65 //==========================================================================
66 //
67 // VSoundManager::VSoundManager
68 //
69 //==========================================================================
70
VSoundManager()71 VSoundManager::VSoundManager()
72 : NumPlayerReserves(0)
73 , CurrentChangePitch(7.0 / 255.0)
74 {
75 memset(AmbientSounds, 0, sizeof(AmbientSounds));
76 }
77
78 //==========================================================================
79 //
80 // VSoundManager::~VSoundManager
81 //
82 //==========================================================================
83
~VSoundManager()84 VSoundManager::~VSoundManager()
85 {
86 guard(VSoundManager::~VSoundManager);
87 for (int i = 0; i < S_sfx.Num(); i++)
88 {
89 if (S_sfx[i].Data)
90 {
91 Z_Free(S_sfx[i].Data);
92 }
93 if (S_sfx[i].Sounds)
94 {
95 delete[] S_sfx[i].Sounds;
96 S_sfx[i].Sounds = NULL;
97 }
98 }
99
100 for (int i = 0; i < NUM_AMBIENT_SOUNDS; i++)
101 {
102 if (AmbientSounds[i])
103 {
104 delete AmbientSounds[i];
105 AmbientSounds[i] = NULL;
106 }
107 }
108
109 for (int i = 0; i < SeqInfo.Num(); i++)
110 {
111 if (SeqInfo[i].Data)
112 {
113 delete[] SeqInfo[i].Data;
114 SeqInfo[i].Data = NULL;
115 }
116 }
117
118 for (VReverbInfo* R = Environments; R;)
119 {
120 VReverbInfo* Next = R->Next;
121 if (!R->Builtin)
122 {
123 delete[] const_cast<char*>(R->Name);
124 R->Name = NULL;
125 delete R;
126 R = NULL;
127 }
128 R = Next;
129 }
130 unguard;
131 }
132
133 //==========================================================================
134 //
135 // VSoundManager::Init
136 //
137 // Loads sound script lump or file, if param -devsnd was specified
138 //
139 //==========================================================================
140
Init()141 void VSoundManager::Init()
142 {
143 guard(VSoundManager::Init);
144 int Lump;
145
146 // Sound 0 is empty sound.
147 AddSoundLump(NAME_None, -1);
148
149 // Add Strife voices.
150 for (Lump = W_IterateNS(-1, WADNS_Voices); Lump >= 0;
151 Lump = W_IterateNS(Lump, WADNS_Voices))
152 {
153 char SndName[16];
154 sprintf(SndName, "svox/%s", *W_LumpName(Lump));
155
156 int id = AddSoundLump(SndName, Lump);
157 S_sfx[id].ChangePitch = 0;
158 }
159
160 // Load script SNDINFO
161 for (Lump = W_IterateNS(-1, WADNS_Global); Lump >= 0;
162 Lump = W_IterateNS(Lump, WADNS_Global))
163 {
164 if (W_LumpName(Lump) == NAME_sndinfo)
165 {
166 ParseSndinfo(new VScriptParser(*W_LumpName(Lump),
167 W_CreateLumpReaderNum(Lump)));
168 }
169 }
170
171 S_sfx.Condense();
172
173 // Load script SNDSEQ
174 memset(SeqTrans, -1, sizeof(SeqTrans));
175 for (int Lump = W_IterateNS(-1, WADNS_Global); Lump >= 0;
176 Lump = W_IterateNS(Lump, WADNS_Global))
177 {
178 if (W_LumpName(Lump) == NAME_sndseq)
179 {
180 ParseSequenceScript(new VScriptParser(*W_LumpName(Lump),
181 W_CreateLumpReaderNum(Lump)));
182 }
183 }
184
185 // Load script REVERBS
186 Environments = NULL;
187 for (Lump = W_IterateNS(-1, WADNS_Global); Lump >= 0;
188 Lump = W_IterateNS(Lump, WADNS_Global))
189 {
190 if (W_LumpName(Lump) == NAME_reverbs)
191 {
192 ParseReverbs(new VScriptParser(*W_LumpName(Lump),
193 W_CreateLumpReaderNum(Lump)));
194 }
195 }
196 unguard;
197 }
198
199 //==========================================================================
200 //
201 // VSoundManager::ParseSndinfo
202 //
203 //==========================================================================
204
ParseSndinfo(VScriptParser * sc)205 void VSoundManager::ParseSndinfo(VScriptParser* sc)
206 {
207 guard(VSoundManager::ParseSndinfo);
208 TArray<int> list;
209
210 while (!sc->AtEnd())
211 {
212 if (sc->Check("$archivepath"))
213 {
214 // $archivepath <directory>
215 // Ignored.
216 sc->ExpectString();
217 }
218 else if (sc->Check("$map"))
219 {
220 // $map <map number> <song name>
221 sc->ExpectNumber();
222 sc->ExpectName();
223 if (sc->Number)
224 {
225 P_PutMapSongLump(sc->Number, sc->Name);
226 }
227 }
228 else if (sc->Check("$registered"))
229 {
230 // $registered
231 // Unused.
232 }
233 else if (sc->Check("$limit"))
234 {
235 // $limit <logical name> <max channels>
236 sc->ExpectString();
237 int sfx = FindOrAddSound(*sc->String);
238 sc->ExpectNumber();
239 S_sfx[sfx].NumChannels = MID(0, sc->Number, 255);
240 }
241 else if (sc->Check("$pitchshift"))
242 {
243 // $pitchshift <logical name> <pitch shift amount>
244 sc->ExpectString();
245 int sfx = FindOrAddSound(*sc->String);
246 sc->ExpectNumber();
247 S_sfx[sfx].ChangePitch = ((1 << MID(0, sc->Number, 7)) - 1) / 255.0;
248 }
249 else if (sc->Check("$pitchshiftrange"))
250 {
251 // $pitchshiftrange <pitch shift amount>
252 sc->ExpectNumber();
253 CurrentChangePitch = ((1 << MID(0, sc->Number, 7)) - 1) / 255.0;
254 }
255 else if (sc->Check("$alias"))
256 {
257 // $alias <name of alias> <name of real sound>
258 sc->ExpectString();
259 int sfxfrom = AddSound(*sc->String, -1);
260 sc->ExpectString();
261 //if (S_sfx[sfxfrom].bPlayerCompat)
262 //{
263 // sfxfrom = S_sfx[sfxfrom].link;
264 //}
265 S_sfx[sfxfrom].Link = FindOrAddSound(*sc->String);
266 }
267 else if (sc->Check("$random"))
268 {
269 // $random <logical name> { <logical name> ... }
270 list.Clear();
271 sc->ExpectString();
272 int id = AddSound(*sc->String, -1);
273 sc->Expect("{");
274 while (!sc->Check("}"))
275 {
276 sc->ExpectString();
277 int sfxto = FindOrAddSound(*sc->String);
278 list.Append(sfxto);
279 }
280 if (list.Num() == 1)
281 {
282 // Only one sound: treat as $alias
283 S_sfx[id].Link = list[0];
284 }
285 else if (list.Num() > 1)
286 {
287 // Only add non-empty random lists
288 S_sfx[id].Link = list.Num();
289 S_sfx[id].Sounds = new int[list.Num()];
290 memcpy(S_sfx[id].Sounds, &list[0], sizeof(int) * list.Num());
291 S_sfx[id].bRandomHeader = true;
292 }
293 }
294 else if (sc->Check("$playersound"))
295 {
296 // $playersound <player class> <gender> <logical name> <lump name>
297 int PClass, Gender, RefId;
298 char FakeName[NAME_SIZE];
299 size_t len;
300 int id;
301
302 ParsePlayerSoundCommon(sc, PClass, Gender, RefId);
303 len = VStr::Length(*PlayerClasses[PClass]);
304 memcpy(FakeName, *PlayerClasses[PClass], len);
305 FakeName[len] = '|';
306 FakeName[len + 1] = Gender + '0';
307 VStr::Cpy(&FakeName[len + 2], *S_sfx[RefId].TagName);
308
309 id = AddSoundLump(FakeName, W_CheckNumForName(
310 VName(*sc->String, VName::AddLower), WADNS_Sounds));
311 FPlayerSound& PlrSnd = PlayerSounds.Alloc();
312 PlrSnd.ClassId = PClass;
313 PlrSnd.GenderId = Gender;
314 PlrSnd.RefId = RefId;
315 PlrSnd.SoundId = id;
316 }
317 else if (sc->Check("$playersounddup"))
318 {
319 // $playersounddup <player class> <gender> <logical name> <target sound name>
320 int PClass, Gender, RefId, TargId;
321
322 ParsePlayerSoundCommon(sc, PClass, Gender, RefId);
323 TargId = FindSound(*sc->String);
324 if (!TargId)
325 {
326 TargId = AddSound(*sc->String, -1);
327 S_sfx[TargId].Link = NumPlayerReserves++;
328 S_sfx[TargId].bPlayerReserve = true;
329 }
330 else if (!S_sfx[TargId].bPlayerReserve)
331 {
332 sc->Error(va("%s is not a player sound", *sc->String));
333 }
334 int AliasTo = FindPlayerSound(PClass, Gender, TargId);
335 FPlayerSound& PlrSnd = PlayerSounds.Alloc();
336 PlrSnd.ClassId = PClass;
337 PlrSnd.GenderId = Gender;
338 PlrSnd.RefId = RefId;
339 PlrSnd.SoundId = AliasTo;
340 }
341 else if (sc->Check("$playeralias"))
342 {
343 // $playeralias <player class> <gender> <logical name> <logical name of existing sound>
344 int PClass, Gender, RefId;
345
346 ParsePlayerSoundCommon(sc, PClass, Gender, RefId);
347 int AliasTo = FindOrAddSound(*sc->String);
348 FPlayerSound& PlrSnd = PlayerSounds.Alloc();
349 PlrSnd.ClassId = PClass;
350 PlrSnd.GenderId = Gender;
351 PlrSnd.RefId = RefId;
352 PlrSnd.SoundId = AliasTo;
353 }
354 else if (sc->Check("$singular"))
355 {
356 // $singular <logical name>
357 sc->ExpectString();
358 int sfx = FindOrAddSound(*sc->String);
359 S_sfx[sfx].bSingular = true;
360 }
361 else if (sc->Check("$ambient"))
362 {
363 // $ambient <num> <logical name> [point [atten] | surround | [world]]
364 // <continuous | random <minsecs> <maxsecs> | periodic <secs>>
365 // <volume>
366 FAmbientSound* ambient, dummy;
367
368 sc->ExpectNumber();
369 if (sc->Number < 0 || sc->Number >= NUM_AMBIENT_SOUNDS)
370 {
371 GCon->Logf("Bad ambient index (%d)", sc->Number);
372 ambient = &dummy;
373 }
374 else if (AmbientSounds[sc->Number])
375 {
376 ambient = AmbientSounds[sc->Number];
377 }
378 else
379 {
380 ambient = new FAmbientSound;
381 AmbientSounds[sc->Number] = ambient;
382 }
383 memset(ambient, 0, sizeof(FAmbientSound));
384
385 sc->ExpectString();
386 ambient->Sound = *sc->String;
387 ambient->Attenuation = 0;
388
389 if (sc->Check("point"))
390 {
391 ambient->Type = SNDTYPE_Point;
392 if (sc->CheckFloat())
393 {
394 if (sc->Float > 0)
395 {
396 ambient->Attenuation = sc->Float;
397 }
398 else
399 {
400 ambient->Attenuation = 1;
401 }
402 }
403 else
404 {
405 ambient->Attenuation = 1;
406 }
407 }
408 else if (sc->Check("surround"))
409 {
410 ambient->Type = SNDTYPE_Surround;
411 ambient->Attenuation = -1;
412 }
413 else if (sc->Check("world"))
414 {
415 // World is an optional keyword
416 }
417
418 if (sc->Check("continuous"))
419 {
420 ambient->Type |= SNDTYPE_Continuous;
421 }
422 else if (sc->Check("random"))
423 {
424 ambient->Type |= SNDTYPE_Random;
425 sc->ExpectFloat();
426 ambient->PeriodMin = sc->Float;
427 sc->ExpectFloat();
428 ambient->PeriodMax = sc->Float;
429 }
430 else if (sc->Check("periodic"))
431 {
432 ambient->Type |= SNDTYPE_Periodic;
433 sc->ExpectFloat();
434 ambient->PeriodMin = sc->Float;
435 }
436 else
437 {
438 sc->ExpectString();
439 GCon->Logf("Unknown ambient type (%s)", *sc->String);
440 }
441
442 sc->ExpectFloat();
443 ambient->Volume = sc->Float;
444 if (ambient->Volume > 1)
445 ambient->Volume = 1;
446 else if (ambient->Volume < 0)
447 ambient->Volume = 0;
448 }
449 else if (sc->Check("$musicvolume"))
450 {
451 sc->ExpectName();
452 VName SongName = sc->Name;
453 sc->ExpectFloat();
454 int i;
455 for (i = 0; i < MusicVolumes.Num(); i++)
456 {
457 if (MusicVolumes[i].SongName == SongName)
458 {
459 MusicVolumes[i].Volume = sc->Float;
460 break;
461 }
462 }
463 if (i == MusicVolumes.Num())
464 {
465 VMusicVolume& V = MusicVolumes.Alloc();
466 V.SongName = SongName;
467 V.Volume = sc->Float;
468 }
469 }
470 else if (sc->Check("$ifdoom") || sc->Check("$ifheretic") ||
471 sc->Check("$ifhexen") || sc->Check("$ifstrife") ||
472 sc->Check("$endif"))
473 {
474 GCon->Log("Conditional SNDINFO commands are not supported");
475 }
476 else if (sc->Check("$volume"))
477 {
478 GCon->Log("$volume is not supported yet.");
479 }
480 else
481 {
482 sc->ExpectString();
483 if (**sc->String == '$')
484 {
485 sc->Error("Unknown command");
486 }
487 VName TagName = *sc->String;
488 sc->ExpectName();
489 AddSound(TagName, W_CheckNumForName(sc->Name, WADNS_Sounds));
490 }
491 }
492 delete sc;
493 sc = NULL;
494 unguard;
495 }
496
497 //==========================================================================
498 //
499 // VSoundManager::AddSoundLump
500 //
501 //==========================================================================
502
AddSoundLump(VName TagName,int Lump)503 int VSoundManager::AddSoundLump(VName TagName, int Lump)
504 {
505 guard(VSoundManager::AddSoundLump);
506 sfxinfo_t S;
507 memset(&S, 0, sizeof(S));
508 S.TagName = TagName;
509 S.Data = NULL;
510 S.Priority = 127;
511 S.NumChannels = 2;
512 S.ChangePitch = CurrentChangePitch;
513 S.LumpNum = Lump;
514 S.Link = -1;
515 return S_sfx.Append(S);
516 unguard;
517 }
518
519 //==========================================================================
520 //
521 // VSoundManager::AddSound
522 //
523 //==========================================================================
524
AddSound(VName TagName,int Lump)525 int VSoundManager::AddSound(VName TagName, int Lump)
526 {
527 guard(VSoundManager::AddSound);
528 int id = FindSound(TagName);
529
530 if (id > 0)
531 {
532 // If the sound has already been defined, change the old definition
533 sfxinfo_t* sfx = &S_sfx[id];
534
535 //if (sfx->bPlayerReserve)
536 //{
537 // SC_ScriptError("Sounds that are reserved for players cannot be reassigned");
538 //}
539 // Redefining a player compatibility sound will redefine the target instead.
540 //if (sfx->bPlayerCompat)
541 //{
542 // sfx = &S_sfx[sfx->link];
543 //}
544 if (sfx->bRandomHeader)
545 {
546 delete[] sfx->Sounds;
547 sfx->Sounds = NULL;
548 }
549 sfx->LumpNum = Lump;
550 sfx->bRandomHeader = false;
551 sfx->Link = -1;
552 }
553 else
554 {
555 // Otherwise, create a new definition.
556 id = AddSoundLump(TagName, Lump);
557 }
558
559 return id;
560 unguard;
561 }
562
563 //==========================================================================
564 //
565 // VSoundManager::FindSound
566 //
567 //==========================================================================
568
FindSound(VName TagName)569 int VSoundManager::FindSound(VName TagName)
570 {
571 guard(VSoundManager::FindSound);
572 for (int i = 0; i < S_sfx.Num(); i++)
573 {
574 if (!VStr::ICmp(*S_sfx[i].TagName, *TagName))
575 {
576 return i;
577 }
578 }
579 return 0;
580 unguard;
581 }
582
583 //==========================================================================
584 //
585 // VSoundManager::FindOrAddSound
586 //
587 //==========================================================================
588
FindOrAddSound(VName TagName)589 int VSoundManager::FindOrAddSound(VName TagName)
590 {
591 guard(VSoundManager::FindOrAddSound);
592 int id = FindSound(TagName);
593 return id ? id : AddSoundLump(TagName, -1);
594 unguard;
595 }
596
597 //==========================================================================
598 //
599 // VSoundManager::ParsePlayerSoundCommon
600 //
601 // Parses the common part of playersound commands in SNDINFO
602 // (player class, gender, and ref id)
603 //
604 //==========================================================================
605
ParsePlayerSoundCommon(VScriptParser * sc,int & PClass,int & Gender,int & RefId)606 void VSoundManager::ParsePlayerSoundCommon(VScriptParser* sc, int& PClass,
607 int& Gender, int& RefId)
608 {
609 guard(VSoundManager::ParsePlayerSoundCommon);
610 sc->ExpectString();
611 PClass = AddPlayerClass(*sc->String);
612 sc->ExpectString();
613 Gender = AddPlayerGender(*sc->String);
614 sc->ExpectString();
615 RefId = FindSound(*sc->String);
616 if (!RefId)
617 {
618 RefId = AddSound(*sc->String, -1);
619 S_sfx[RefId].Link = NumPlayerReserves++;
620 S_sfx[RefId].bPlayerReserve = true;
621 }
622 else if (!S_sfx[RefId].bPlayerReserve)
623 {
624 sc->Error(va("%s has not been reserved for a player sound",
625 *sc->String));
626 }
627 sc->ExpectString();
628 unguard;
629 }
630
631 //==========================================================================
632 //
633 // VSoundManager::AddPlayerClass
634 //
635 //==========================================================================
636
AddPlayerClass(VName CName)637 int VSoundManager::AddPlayerClass(VName CName)
638 {
639 guard(VSoundManager::AddPlayerClass);
640 int idx = FindPlayerClass(CName);
641 return idx == -1 ? PlayerClasses.Append(CName) : idx;
642 unguard;
643 }
644
645 //==========================================================================
646 //
647 // VSoundManager::FindPlayerClass
648 //
649 //==========================================================================
650
FindPlayerClass(VName CName)651 int VSoundManager::FindPlayerClass(VName CName)
652 {
653 guard(VSoundManager::FindPlayerClass);
654 for (int i = 0; i < PlayerClasses.Num(); i++)
655 if (PlayerClasses[i] == CName)
656 return i;
657 return -1;
658 unguard;
659 }
660
661 //==========================================================================
662 //
663 // VSoundManager::AddPlayerGender
664 //
665 //==========================================================================
666
AddPlayerGender(VName GName)667 int VSoundManager::AddPlayerGender(VName GName)
668 {
669 guard(VSoundManager::AddPlayerGender);
670 int idx = FindPlayerGender(GName);
671 return idx == -1 ? PlayerGenders.Append(GName) : idx;
672 unguard;
673 }
674
675 //==========================================================================
676 //
677 // VSoundManager::FindPlayerGender
678 //
679 //==========================================================================
680
FindPlayerGender(VName GName)681 int VSoundManager::FindPlayerGender(VName GName)
682 {
683 guard(VSoundManager::FindPlayerGender);
684 for (int i = 0; i < PlayerGenders.Num(); i++)
685 if (PlayerGenders[i] == GName)
686 return i;
687 return -1;
688 unguard;
689 }
690
691 //==========================================================================
692 //
693 // VSoundManager::FindPlayerSound
694 //
695 //==========================================================================
696
FindPlayerSound(int PClass,int Gender,int RefId)697 int VSoundManager::FindPlayerSound(int PClass, int Gender, int RefId)
698 {
699 guard(VSoundManager::FindPlayerSound);
700 for (int i = 0; i < PlayerSounds.Num(); i++)
701 {
702 if (PlayerSounds[i].ClassId == PClass &&
703 PlayerSounds[i].GenderId == Gender &&
704 PlayerSounds[i].RefId == RefId)
705 {
706 return PlayerSounds[i].SoundId;
707 }
708 }
709 return 0;
710 unguard;
711 }
712
713 //==========================================================================
714 //
715 // VSoundManager::LookupPlayerSound
716 //
717 //==========================================================================
718
LookupPlayerSound(int ClassId,int GenderId,int RefId)719 int VSoundManager::LookupPlayerSound(int ClassId, int GenderId, int RefId)
720 {
721 guard(VSoundManager::LookupPlayerSound);
722 int Id = FindPlayerSound(ClassId, GenderId, RefId);
723 if (Id == 0 || (S_sfx[Id].LumpNum == -1 && S_sfx[Id].Link == -1))
724 {
725 // This sound is unavailable.
726 if (GenderId)
727 {
728 // Try "male"
729 return LookupPlayerSound(ClassId, 0, RefId);
730 }
731 if (ClassId)
732 {
733 // Try the default class.
734 return LookupPlayerSound(0, GenderId, RefId);
735 }
736 }
737 return Id;
738 unguard;
739 }
740
741 //==========================================================================
742 //
743 // VSoundManager::GetSoundID
744 //
745 //==========================================================================
746
GetSoundID(VName Name)747 int VSoundManager::GetSoundID(VName Name)
748 {
749 guard(VSoundManager::GetSoundID);
750 for (int i = 0; i < S_sfx.Num(); i++)
751 {
752 if (!VStr::ICmp(*S_sfx[i].TagName, *Name))
753 {
754 return i;
755 }
756 }
757 GCon->Logf("WARNING! Can't find sound %s", *Name);
758 return 0;
759 unguard;
760 }
761
762 //==========================================================================
763 //
764 // VSoundManager::GetSoundID
765 //
766 //==========================================================================
767
GetSoundID(const char * name)768 int VSoundManager::GetSoundID(const char *name)
769 {
770 guard(VSoundManager::GetSoundID);
771 for (int i = 0; i < S_sfx.Num(); i++)
772 {
773 if (!VStr::ICmp(*S_sfx[i].TagName, name))
774 {
775 return i;
776 }
777 }
778 GCon->Logf("WARNING! Can't find sound named %s", name);
779 return 0;
780 unguard;
781 }
782
783 //==========================================================================
784 //
785 // VSoundManager::ResolveSound
786 //
787 //==========================================================================
788
ResolveSound(int InSoundId)789 int VSoundManager::ResolveSound(int InSoundId)
790 {
791 guard(VSoundManager::ResolveSound);
792 return ResolveSound(0, 0, InSoundId);
793 unguard;
794 }
795
796 //==========================================================================
797 //
798 // VSoundManager::ResolveEntitySound
799 //
800 //==========================================================================
801
ResolveEntitySound(VName ClassName,VName GenderName,VName SoundName)802 int VSoundManager::ResolveEntitySound(VName ClassName, VName GenderName,
803 VName SoundName)
804 {
805 guard(VSoundManager::ResolveEntitySound);
806 int ClassId = FindPlayerClass(ClassName);
807 if (ClassId == -1)
808 ClassId = 0;
809 int GenderId = FindPlayerGender(GenderName);
810 if (GenderId == -1)
811 GenderId = 0;
812 int SoundId = GetSoundID(SoundName);
813 return ResolveSound(ClassId, GenderId, SoundId);
814 unguard;
815 }
816
817 //==========================================================================
818 //
819 // VSoundManager::ResolveSound
820 //
821 //==========================================================================
822
ResolveSound(int ClassID,int GenderID,int InSoundId)823 int VSoundManager::ResolveSound(int ClassID, int GenderID, int InSoundId)
824 {
825 guard(VSoundManager::ResolveSound);
826 int sound_id = InSoundId;
827 while (S_sfx[sound_id].Link != -1)
828 {
829 if (S_sfx[sound_id].bPlayerReserve)
830 {
831 sound_id = LookupPlayerSound(ClassID, GenderID, sound_id);
832 }
833 else if (S_sfx[sound_id].bRandomHeader)
834 {
835 sound_id = S_sfx[sound_id].Sounds[rand() % S_sfx[sound_id].Link];
836 }
837 else
838 {
839 sound_id = S_sfx[sound_id].Link;
840 }
841 }
842 return sound_id;
843 unguard;
844 }
845
846 //==========================================================================
847 //
848 // VSoundManager::IsSoundPresent
849 //
850 //==========================================================================
851
IsSoundPresent(VName ClassName,VName GenderName,VName SoundName)852 bool VSoundManager::IsSoundPresent(VName ClassName, VName GenderName,
853 VName SoundName)
854 {
855 guard(VSoundManager::IsSoundPresent);
856 int SoundId = FindSound(SoundName);
857 if (!SoundId)
858 {
859 return false;
860 }
861 int ClassId = FindPlayerClass(ClassName);
862 if (ClassId == -1)
863 {
864 ClassId = 0;
865 }
866 int GenderId = FindPlayerGender(GenderName);
867 if (GenderId == -1)
868 {
869 GenderId = 0;
870 }
871 return ResolveSound(ClassId, GenderId, SoundId) > 0;
872 unguard;
873 }
874
875 //==========================================================================
876 //
877 // VSoundManager::LoadSound
878 //
879 //==========================================================================
880
LoadSound(int sound_id)881 bool VSoundManager::LoadSound(int sound_id)
882 {
883 guard(VSoundManager::LoadSound);
884 static const char* Exts[] = { "flac", "wav", "raw", NULL };
885
886 if (!S_sfx[sound_id].Data)
887 {
888 int Lump = S_sfx[sound_id].LumpNum;
889 if (S_sfx[sound_id].LumpNum < 0)
890 {
891 GCon->Logf(NAME_Dev, "Sound %s lump not found",
892 *S_sfx[sound_id].TagName);
893 return false;
894 }
895 int FileLump = W_FindLumpByFileNameWithExts(va("sound/%s",
896 *W_LumpName(Lump)), Exts);
897 if (Lump < FileLump)
898 {
899 Lump = FileLump;
900 }
901 VStream* Strm = W_CreateLumpReaderNum(Lump);
902
903 for (VSampleLoader* Ldr = VSampleLoader::List;
904 Ldr && !S_sfx[sound_id].Data; Ldr = Ldr->Next)
905 {
906 Ldr->Load(S_sfx[sound_id], *Strm);
907 }
908 delete Strm;
909 Strm = NULL;
910 if (!S_sfx[sound_id].Data)
911 {
912 GCon->Logf(NAME_Dev, "Failed to load sound %s",
913 *S_sfx[sound_id].TagName);
914 return false;
915 }
916 }
917 S_sfx[sound_id].UseCount++;
918 return true;
919 unguard;
920 }
921
922 //==========================================================================
923 //
924 // VSoundManager::DoneWithLump
925 //
926 //==========================================================================
927
DoneWithLump(int sound_id)928 void VSoundManager::DoneWithLump(int sound_id)
929 {
930 guard(VSoundManager::DoneWithLump);
931 sfxinfo_t &sfx = S_sfx[sound_id];
932 if (!sfx.Data || !sfx.UseCount)
933 {
934 Sys_Error("Empty lump");
935 }
936
937 sfx.UseCount--;
938 if (sfx.UseCount)
939 {
940 // still used
941 return;
942 }
943 Z_Free(sfx.Data);
944 sfx.Data = NULL;
945 unguard;
946 }
947
948 //==========================================================================
949 //
950 // VSoundManager::GetMusicVolume
951 //
952 //==========================================================================
953
GetMusicVolume(VName SongName)954 float VSoundManager::GetMusicVolume(VName SongName)
955 {
956 guard(VSoundManager::GetMusicVolume);
957 for (int i = 0; i < MusicVolumes.Num(); i++)
958 {
959 if (MusicVolumes[i].SongName == SongName)
960 {
961 return MusicVolumes[i].Volume;
962 }
963 }
964 return 1.0;
965 unguard;
966 }
967
968 //==========================================================================
969 //
970 // VSoundManager::GetAmbientSound
971 //
972 //==========================================================================
973
GetAmbientSound(int Idx)974 FAmbientSound* VSoundManager::GetAmbientSound(int Idx)
975 {
976 guardSlow(VSoundManager::GetAmbientSound);
977 if (Idx < 0 || Idx >= NUM_AMBIENT_SOUNDS)
978 {
979 return NULL;
980 }
981 return AmbientSounds[Idx];
982 unguardSlow;
983 }
984
985 //==========================================================================
986 //
987 // VSoundManager::ParseSequenceScript
988 //
989 //==========================================================================
990
ParseSequenceScript(VScriptParser * sc)991 void VSoundManager::ParseSequenceScript(VScriptParser* sc)
992 {
993 guard(VSoundManager::ParseSequenceScript);
994 TArray<vint32> TempData;
995 bool inSequence = false;
996 int SeqId = 0;
997 int DelayOnceIndex = 0;
998 char SeqType = ':';
999
1000 while (!sc->AtEnd())
1001 {
1002 sc->ExpectString();
1003 if (**sc->String == ':' || **sc->String == '[')
1004 {
1005 if (inSequence)
1006 {
1007 sc->Error("SN_InitSequenceScript: Nested Script Error");
1008 }
1009 for (SeqId = 0; SeqId < SeqInfo.Num(); SeqId++)
1010 {
1011 if (SeqInfo[SeqId].Name == *sc->String + 1)
1012 {
1013 Z_Free(SeqInfo[SeqId].Data);
1014 break;
1015 }
1016 }
1017 if (SeqId == SeqInfo.Num())
1018 {
1019 SeqInfo.Alloc();
1020 }
1021 TempData.Clear();
1022 inSequence = true;
1023 DelayOnceIndex = 0;
1024 SeqType = sc->String[0];
1025 SeqInfo[SeqId].Name = *sc->String + 1;
1026 SeqInfo[SeqId].Slot = NAME_None;
1027 SeqInfo[SeqId].Data = NULL;
1028 SeqInfo[SeqId].StopSound = 0;
1029 if (SeqType == '[')
1030 {
1031 TempData.Append(SSCMD_Select);
1032 TempData.Append(0);
1033 sc->SetCMode(true);
1034 }
1035 continue; // parse the next command
1036 }
1037 if (!inSequence)
1038 {
1039 sc->Error("String outside sequence");
1040 continue;
1041 }
1042 sc->UnGet();
1043
1044 if (sc->Check("door"))
1045 {
1046 // door <number>...
1047 AssignSeqTranslations(sc, SeqId, SEQ_Door);
1048 continue;
1049 }
1050 if (sc->Check("platform"))
1051 {
1052 // platform <number>...
1053 AssignSeqTranslations(sc, SeqId, SEQ_Platform);
1054 continue;
1055 }
1056 if (sc->Check("environment"))
1057 {
1058 // environment <number>...
1059 AssignSeqTranslations(sc, SeqId, SEQ_Environment);
1060 continue;
1061 }
1062
1063 if (SeqType == '[')
1064 {
1065 // Selection sequence
1066 if (sc->Check("]"))
1067 {
1068 TempData[1] = (TempData.Num() - 2) / 2;
1069 TempData.Append(SSCMD_End);
1070 SeqInfo[SeqId].Data = new vint32[TempData.Num()];
1071 memcpy(SeqInfo[SeqId].Data, TempData.Ptr(), TempData.Num() *
1072 sizeof(vint32));
1073 inSequence = false;
1074 sc->SetCMode(false);
1075 }
1076 else
1077 {
1078 sc->ExpectNumber();
1079 TempData.Append(sc->Number);
1080 sc->ExpectString();
1081 TempData.Append(VName(*sc->String).GetIndex());
1082 }
1083 continue;
1084 }
1085
1086 if (sc->Check("play"))
1087 {
1088 // play <sound>
1089 sc->ExpectString();
1090 TempData.Append(SSCMD_Play);
1091 TempData.Append(GetSoundID(*sc->String));
1092 }
1093 else if (sc->Check("playuntildone"))
1094 {
1095 // playuntildone <sound>
1096 sc->ExpectString();
1097 TempData.Append(SSCMD_Play);
1098 TempData.Append(GetSoundID(*sc->String));
1099 TempData.Append(SSCMD_WaitUntilDone);
1100 }
1101 else if (sc->Check("playtime"))
1102 {
1103 // playtime <string> <tics>
1104 sc->ExpectString();
1105 TempData.Append(SSCMD_Play);
1106 TempData.Append(GetSoundID(*sc->String));
1107 sc->ExpectNumber();
1108 TempData.Append(SSCMD_Delay);
1109 TempData.Append(sc->Number);
1110 }
1111 else if (sc->Check("playrepeat"))
1112 {
1113 // playrepeat <sound>
1114 sc->ExpectString();
1115 TempData.Append(SSCMD_PlayRepeat);
1116 TempData.Append(GetSoundID(*sc->String));
1117 }
1118 else if (sc->Check("playloop"))
1119 {
1120 // playloop <sound> <count>
1121 sc->ExpectString();
1122 TempData.Append(SSCMD_PlayLoop);
1123 TempData.Append(GetSoundID(*sc->String));
1124 sc->ExpectNumber();
1125 TempData.Append(sc->Number);
1126 }
1127 else if (sc->Check("delay"))
1128 {
1129 // delay <tics>
1130 TempData.Append(SSCMD_Delay);
1131 sc->ExpectNumber();
1132 TempData.Append(sc->Number);
1133 }
1134 else if (sc->Check("delayonce"))
1135 {
1136 // delayonce <tics>
1137 TempData.Append(SSCMD_DelayOnce);
1138 sc->ExpectNumber();
1139 TempData.Append(sc->Number);
1140 TempData.Append(DelayOnceIndex++);
1141 }
1142 else if (sc->Check("delayrand"))
1143 {
1144 // delayrand <tics_from> <tics_to>
1145 TempData.Append(SSCMD_DelayRand);
1146 sc->ExpectNumber();
1147 TempData.Append(sc->Number);
1148 sc->ExpectNumber();
1149 TempData.Append(sc->Number);
1150 }
1151 else if (sc->Check("volume"))
1152 {
1153 // volume <volume>
1154 TempData.Append(SSCMD_Volume);
1155 sc->ExpectFloat();
1156 TempData.Append((vint32)(sc->Float * 100.0));
1157 }
1158 else if (sc->Check("volumerel"))
1159 {
1160 // volumerel <volume_delta>
1161 TempData.Append(SSCMD_VolumeRel);
1162 sc->ExpectFloat();
1163 TempData.Append((vint32)(sc->Float * 100.0));
1164 }
1165 else if (sc->Check("volumerand"))
1166 {
1167 // volumerand <volume_from> <volume_to>
1168 TempData.Append(SSCMD_VolumeRand);
1169 sc->ExpectFloat();
1170 TempData.Append((vint32)(sc->Float * 100.0));
1171 sc->ExpectFloat();
1172 TempData.Append((vint32)(sc->Float * 100.0));
1173 }
1174 else if (sc->Check("attenuation"))
1175 {
1176 // attenuation none|normal|idle|static|surround
1177 TempData.Append(SSCMD_Attenuation);
1178 vint32 Atten = 0;
1179 if (sc->Check("none"))
1180 Atten = 0;
1181 else if (sc->Check("normal"))
1182 Atten = 1;
1183 else if (sc->Check("idle"))
1184 Atten = 2;
1185 else if (sc->Check("static"))
1186 Atten = 3;
1187 else if (sc->Check("surround"))
1188 Atten = -1;
1189 else
1190 sc->Error("Bad attenuation");
1191 TempData.Append(Atten);
1192 }
1193 else if (sc->Check("randomsequence"))
1194 {
1195 // randomsequence
1196 TempData.Append(SSCMD_RandomSequence);
1197 }
1198 else if (sc->Check("restart"))
1199 {
1200 // restart
1201 TempData.Append(SSCMD_Branch);
1202 TempData.Append(TempData.Num() - 1);
1203 }
1204 else if (sc->Check("stopsound"))
1205 {
1206 // stopsound <sound>
1207 sc->ExpectString();
1208 SeqInfo[SeqId].StopSound = GetSoundID(*sc->String);
1209 TempData.Append(SSCMD_StopSound);
1210 }
1211 else if (sc->Check("nostopcutoff"))
1212 {
1213 // nostopcutoff
1214 SeqInfo[SeqId].StopSound = -1;
1215 TempData.Append(SSCMD_StopSound);
1216 }
1217 else if (sc->Check("slot"))
1218 {
1219 // slot <name>...
1220 sc->ExpectString();
1221 SeqInfo[SeqId].Slot = *sc->String;
1222 }
1223 else if (sc->Check("end"))
1224 {
1225 // end
1226 TempData.Append(SSCMD_End);
1227 SeqInfo[SeqId].Data = new vint32[TempData.Num()];
1228 memcpy(SeqInfo[SeqId].Data, TempData.Ptr(), TempData.Num() *
1229 sizeof(vint32));
1230 inSequence = false;
1231 }
1232 else
1233 {
1234 sc->Error("Unknown commmand.");
1235 }
1236 }
1237 delete sc;
1238 sc = NULL;
1239 unguard;
1240 }
1241
1242 //==========================================================================
1243 //
1244 // VSoundManager::AssignSeqTranslations
1245 //
1246 //==========================================================================
1247
AssignSeqTranslations(VScriptParser * sc,int SeqId,seqtype_t SeqType)1248 void VSoundManager::AssignSeqTranslations(VScriptParser* sc, int SeqId,
1249 seqtype_t SeqType)
1250 {
1251 guard(VSoundManager::AssignSeqTranslations);
1252 sc->Crossed = false;
1253
1254 while (sc->GetString() && !sc->Crossed)
1255 {
1256 char* Stopper;
1257 int Num = strtol(*sc->String, &Stopper, 0);
1258 if (*Stopper == 0)
1259 {
1260 SeqTrans[(Num & 63) + SeqType * 64] = SeqId;
1261 }
1262 }
1263
1264 sc->UnGet();
1265 unguard;
1266 }
1267
1268 //==========================================================================
1269 //
1270 // VSoundManager::SetSeqTrans
1271 //
1272 //==========================================================================
1273
SetSeqTrans(VName Name,int Num,int SeqType)1274 void VSoundManager::SetSeqTrans(VName Name, int Num, int SeqType)
1275 {
1276 guard(VSoundManager::SetSeqTrans);
1277 int Idx = FindSequence(Name);
1278 if (Idx != -1)
1279 {
1280 SeqTrans[(Num & 63) + SeqType * 64] = Idx;
1281 }
1282 unguard;
1283 }
1284
1285 //==========================================================================
1286 //
1287 // VSoundManager::GetSeqTrans
1288 //
1289 //==========================================================================
1290
GetSeqTrans(int Num,int SeqType)1291 VName VSoundManager::GetSeqTrans(int Num, int SeqType)
1292 {
1293 guard(VSoundManager::GetSeqTrans);
1294 if (Num < 0)
1295 {
1296 // If not assigned, use 0 as default.
1297 Num = 0;
1298 }
1299 if (SeqTrans[(Num & 63) + SeqType * 64] < 0)
1300 {
1301 return NAME_None;
1302 }
1303 return SeqInfo[SeqTrans[(Num & 63) + SeqType * 64]].Name;
1304 unguard;
1305 }
1306
1307 //==========================================================================
1308 //
1309 // VSoundManager::GetSeqSlot
1310 //
1311 //==========================================================================
1312
GetSeqSlot(VName Name)1313 VName VSoundManager::GetSeqSlot(VName Name)
1314 {
1315 guard(VSoundManager::GetSeqSlot);
1316 int Idx = FindSequence(Name);
1317 if (Idx != -1)
1318 {
1319 return SeqInfo[Idx].Slot;
1320 }
1321 return NAME_None;
1322 unguard;
1323 }
1324
1325 //==========================================================================
1326 //
1327 // VSoundManager::FindSequence
1328 //
1329 //==========================================================================
1330
FindSequence(VName Name)1331 int VSoundManager::FindSequence(VName Name)
1332 {
1333 guard(VSoundManager::FindSequence);
1334 for (int i = 0; i < SeqInfo.Num(); i++)
1335 {
1336 if (SeqInfo[i].Name == Name)
1337 {
1338 return i;
1339 }
1340 }
1341 return -1;
1342 unguard;
1343 }
1344
1345 //==========================================================================
1346 //
1347 // VSoundManager::GetSoundLumpNames
1348 //
1349 //==========================================================================
1350
GetSoundLumpNames(TArray<FReplacedString> & List)1351 void VSoundManager::GetSoundLumpNames(TArray<FReplacedString>& List)
1352 {
1353 guard(VSoundManager::GetSoundLumpNames);
1354 for (int i = 1; i < S_sfx.Num(); i++)
1355 {
1356 if (S_sfx[i].LumpNum < 0)
1357 {
1358 continue;
1359 }
1360 const char* LName = *W_LumpName(S_sfx[i].LumpNum);
1361 if (LName[0] == 'd' && LName[1] == 's')
1362 {
1363 FReplacedString& R = List.Alloc();
1364 R.Index = i;
1365 R.Replaced = false;
1366 R.Old = LName + 2;
1367 }
1368 }
1369 unguard;
1370 }
1371
1372 //==========================================================================
1373 //
1374 // VSoundManager::ReplaceSoundLumpNames
1375 //
1376 //==========================================================================
1377
ReplaceSoundLumpNames(TArray<FReplacedString> & List)1378 void VSoundManager::ReplaceSoundLumpNames(TArray<FReplacedString>& List)
1379 {
1380 guard(VSoundManager::ReplaceSoundLumpNames);
1381 for (int i = 0; i < List.Num(); i++)
1382 {
1383 if (!List[i].Replaced)
1384 {
1385 continue;
1386 }
1387 S_sfx[List[i].Index].LumpNum = W_CheckNumForName(VName(
1388 *(VStr("ds") + List[i].New), VName::AddLower));
1389 }
1390 unguard;
1391 }
1392
1393 #ifdef CLIENT
1394
1395 //==========================================================================
1396 //
1397 // VRawSampleLoader::Load
1398 //
1399 //==========================================================================
1400
Load(sfxinfo_t & Sfx,VStream & Strm)1401 void VRawSampleLoader::Load(sfxinfo_t& Sfx, VStream& Strm)
1402 {
1403 guard(VRawSampleLoader::Load);
1404 // Read header and see if it's a valid raw sample.
1405 vuint16 Unknown;
1406 vuint16 SampleRate;
1407 vuint32 DataSize;
1408
1409 Strm.Seek(0);
1410 Strm << Unknown
1411 << SampleRate
1412 << DataSize;
1413 if (Unknown != 3 || (vint32)DataSize != Strm.TotalSize() - 8)
1414 {
1415 return;
1416 }
1417
1418 Sfx.SampleBits = 8;
1419 Sfx.SampleRate = SampleRate;
1420 Sfx.DataSize = DataSize;
1421 Sfx.Data = Z_Malloc(Sfx.DataSize);
1422 Strm.Serialise(Sfx.Data, Sfx.DataSize);
1423 unguard;
1424 }
1425
1426 #endif
1427