1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 *
22 * Based on the original sources
23 * Faery Tale II -- The Halls of the Dead
24 * (c) 1993-1996 The Wyrmkeep Entertainment Co.
25 */
26
27 #include "common/config-manager.h"
28 #include "audio/audiostream.h"
29 #include "audio/mididrv.h"
30 #include "audio/decoders/raw.h"
31
32 #include "saga2/saga2.h"
33 #include "saga2/audio.h"
34 #include "saga2/fta.h"
35 #include "saga2/shorten.h"
36 #include "saga2/hresmgr.h"
37 #include "saga2/music.h"
38 #include "saga2/annoy.h"
39 #include "saga2/player.h"
40
41 namespace Saga2 {
42
43 static const StaticPoint32 VeryFarAway = {32767, 32766};
44
45 const uint32 fullVolumeDist = 75;
46 const uint32 offVolumeDist = 200;
47
48 const uint32 baseMusicID = MKTAG('M', 'I', 'L', 'O'),
49 goodMusicID = MKTAG('M', 'I', 'H', 'I'),
50 soundID = MKTAG('L', 'O', 'U', 'D'),
51 loopedID = MKTAG('L', 'O', 'O', 'P'),
52 voiceID = MKTAG('T', 'A', 'L', 'K');
53
54 extern hResource *soundResFile; // script resources
55 extern hResource *voiceResFile; // script resources
56
57 hResContext *voiceRes, *musicRes, *soundRes, *loopRes, *longRes;
58
59 bool haveKillerSoundCard(void);
60 void writeConfig(void);
61 void disableBGLoop(bool s = true);
62 void enableBGLoop(void);
63 void audioStressTest(void);
64 extern GameObject *getViewCenterObject(void);
65 void playSoundAt(uint32 s, Location playAt);
66 void playSoundAt(uint32 s, Point32 playAt);
67 bool sayVoiceAt(uint32 s[], Location l);
68 bool sayVoiceAt(uint32 s[], Point32 l);
69 void playLoopAt(uint32 s, Location l);
70 void playLoopAt(uint32 s, Point32 l);
71
72 bool bufCheckResID(hResContext *hrc, uint32 s);
73 bool hResCheckResID(hResContext *hrc, uint32 s);
74 bool hResCheckResID(hResContext *hrc, uint32 s[]);
75
76 /* ===================================================================== *
77 ATTENUATOR routines
78 * ===================================================================== */
79
80 //-----------------------------------------------------------------------
81 // our distance based volume attenuator
82
volumeFromDist(Point32 loc,byte maxVol)83 static byte volumeFromDist(Point32 loc, byte maxVol) {
84 TilePoint tp(loc.x, loc.y, 0);
85 uint32 dist = tp.quickHDistance();
86 if (dist < fullVolumeDist) {
87 return ABS(maxVol);
88 } else if (dist < offVolumeDist) {
89 return ABS((int)(maxVol * ((int)((offVolumeDist - fullVolumeDist) - (dist - fullVolumeDist))) / (offVolumeDist - fullVolumeDist)));
90 }
91 return 0;
92 }
93
94 /* ===================================================================== *
95 Module code
96 * ===================================================================== */
97
98 //-----------------------------------------------------------------------
99 // after system initialization - startup code
100
startAudio(void)101 void startAudio(void) {
102 uint32 musicID = haveKillerSoundCard() ? goodMusicID : baseMusicID;
103
104 musicRes = soundResFile->newContext(musicID, "music resource");
105 if (musicRes == NULL)
106 error("Musicians on Strike (No music resource context)!\n");
107
108 soundRes = soundResFile->newContext(soundID, "sound resource");
109 if (soundRes == NULL)
110 error("No sound effect resource context!\n");
111
112 longRes = soundResFile->newContext(soundID, "long sound resource");
113 if (longRes == NULL)
114 error("No sound effect resource context!\n");
115
116 loopRes = soundResFile->newContext(loopedID, "loops resource");
117 if (loopRes == NULL)
118 error("No loop effect resource context!\n");
119
120 voiceRes = voiceResFile->newContext(voiceID, "voice resource");
121 if (voiceRes == NULL)
122 error("Laryngitis Error (No voice resource context)!\n");
123
124 g_vm->_audio->initAudioInterface(musicRes);
125
126 // kludgy in memory click sounds
127 g_vm->_audio->_clickSizes[0] = 0;
128 g_vm->_audio->_clickSizes[1] = soundRes->size(MKTAG('C', 'L', 'K', 1));
129 g_vm->_audio->_clickSizes[2] = soundRes->size(MKTAG('C', 'L', 'K', 2));
130 g_vm->_audio->_clickData[0] = NULL;
131 g_vm->_audio->_clickData[1] = (uint8 *)LoadResource(soundRes, MKTAG('C', 'L', 'K', 1), "Click 1");
132 g_vm->_audio->_clickData[2] = (uint8 *)LoadResource(soundRes, MKTAG('C', 'L', 'K', 2), "Click 2");
133 }
134
cleanupAudio()135 void cleanupAudio() {
136 if (g_vm->_audio) {
137 delete g_vm->_audio;
138 g_vm->_audio = nullptr;
139
140 delete musicRes;
141 musicRes = nullptr;
142
143 delete soundRes;
144 soundRes = nullptr;
145
146 delete longRes;
147 longRes = nullptr;
148
149 delete loopRes;
150 loopRes = nullptr;
151
152 delete voiceRes;
153 voiceRes = nullptr;
154 }
155 }
156
157 //-----------------------------------------------------------------------
158 // audio event loop
159
160
audioEventLoop(void)161 void audioEventLoop(void) {
162 if (g_vm->_audio->playFlag())
163 g_vm->_audio->playMe();
164
165 audioEnvironmentCheck();
166 }
167
168 /* ===================================================================== *
169 Assorted code
170 * ===================================================================== */
171
makeCombatSound(uint8 cs,Location l)172 void makeCombatSound(uint8 cs, Location l) {
173 playSoundAt(MKTAG('C', 'B', 'T', cs), l);
174 }
175
makeGruntSound(uint8 cs,Location l)176 void makeGruntSound(uint8 cs, Location l) {
177 playSoundAt(MKTAG('G', 'N', 'T', cs), l);
178 }
179
180
181 //-----------------------------------------------------------------------
182 // check for higher quality MIDI card
183
haveKillerSoundCard(void)184 bool haveKillerSoundCard(void) {
185 MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
186 MusicType driverType = MidiDriver::getMusicType(dev);
187
188 switch (driverType) {
189 case MT_ADLIB:
190 case MT_MT32:
191 return true;
192
193 default:
194 return false;
195 }
196 }
197
198 //-----------------------------------------------------------------------
199 // unwritten music toggler
200
toggleMusic(void)201 void toggleMusic(void) {
202 }
203
204 /* ===================================================================== *
205 Audio hooks for videos
206 * ===================================================================== */
207
208 //-----------------------------------------------------------------------
209 // suspend & resume calls
210
211
suspendLoops(void)212 void suspendLoops(void) {
213 disableBGLoop(false);
214 }
215
resumeLoops(void)216 void resumeLoops(void) {
217 if (loopRes)
218 enableBGLoop();
219 }
220
suspendMusic(void)221 void suspendMusic(void) {
222 audioEnvironmentSuspend(true);
223 }
224
resumeMusic(void)225 void resumeMusic(void) {
226 if (musicRes)
227 audioEnvironmentSuspend(false);
228 }
229
suspendAudio(void)230 void suspendAudio(void) {
231 if (g_vm->_audio) {
232 suspendMusic();
233 suspendLoops();
234 g_vm->_audio->suspend();
235 }
236 }
237
resumeAudio(void)238 void resumeAudio(void) {
239 if (g_vm->_audio) {
240 if (soundRes != NULL || voiceRes != NULL) {
241 g_vm->_audio->resume();
242 resumeLoops();
243 resumeMusic();
244 }
245 }
246 }
247
248 //-----------------------------------------------------------------------
249 // UI volume change hook
250
volumeChanged(void)251 void volumeChanged(void) {
252 if (g_vm->_audio->getVolume(kVolSfx))
253 resumeLoops();
254 else
255 suspendLoops();
256
257 if (g_vm->_audio->getVolume(kVolMusic)) {
258 resumeMusic();
259
260 g_vm->_audio->_music->syncSoundSettings();
261 } else
262 suspendMusic();
263 }
264
265 /* ===================================================================== *
266 main audio playback routines
267 * ===================================================================== */
268
translateLocation(Location playAt)269 Point32 translateLocation(Location playAt) {
270 GameObject *go = getViewCenterObject();
271 Location cal = Location(go->getWorldLocation(), go->IDParent());
272
273 if (playAt.context == cal.context) {
274 Point32 p = Point32(playAt.u - cal.u, playAt.v - cal.v);
275 return p;
276 }
277 return VeryFarAway;
278 }
279
280 //-----------------------------------------------------------------------
281 // MIDI playback
282
playMusic(uint32 s)283 void playMusic(uint32 s) {
284 debugC(1, kDebugSound, "playMusic(%s)", tag2strP(s));
285
286 if (hResCheckResID(musicRes, s)) {
287 g_vm->_audio->playMusic(s, 1);
288 } else
289 g_vm->_audio->stopMusic();
290 }
291
292 //-----------------------------------------------------------------------
293 // in memory sfx
294
playMemSound(uint32 s)295 void playMemSound(uint32 s) {
296 debugC(1, kDebugSound, "playMemSound(%s)", tag2strP(s));
297
298 Audio::AudioStream *aud = Audio::makeRawStream(g_vm->_audio->_clickData[s], g_vm->_audio->_clickSizes[s], 22050, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN, DisposeAfterUse::NO);
299
300 g_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType, &g_vm->_audio->_clickSoundHandle, aud);
301 }
302
303 //-----------------------------------------------------------------------
304 // on disk sfx
305
playSound(uint32 s)306 void playSound(uint32 s) {
307 debugC(1, kDebugSound, "playSound(%s)", tag2strP(s));
308
309 if (hResCheckResID(soundRes, s))
310 g_vm->_audio->queueSound(s, 1, Here);
311 }
312
313 //-----------------------------------------------------------------------
314 // on disk sfx (x2 buffered)
315
playLongSound(uint32 s)316 void playLongSound(uint32 s) {
317 debugC(1, kDebugSound, "playLongSound(%s)", tag2strP(s));
318
319 if (hResCheckResID(longRes, s))
320 g_vm->_audio->queueVoice(s);
321 else
322 g_vm->_audio->stopVoice();
323 }
324
325 //-----------------------------------------------------------------------
326 // on disk voice (x2 buffered)
327
playVoice(uint32 s)328 void playVoice(uint32 s) {
329 debugC(1, kDebugSound, "playVoice(%s)", tag2strP(s));
330
331 if (hResCheckResID(voiceRes, s)) {
332 if (s)
333 g_vm->_audio->queueVoice(s, Here);
334 else
335 g_vm->_audio->stopVoice();
336 }
337 }
338
339 //-----------------------------------------------------------------------
340 // supplemental interface for speech
341
sayVoice(uint32 s[])342 bool sayVoice(uint32 s[]) {
343 debugCN(1, kDebugSound, "sayVoice([%s", tag2strP(s[0]));
344
345 for (uint32 i = 1; s[i]; i++)
346 debugCN(1, kDebugSound, ", %s", tag2strP(s[i]));
347
348 debugC(1, kDebugSound, "])");
349
350 bool worked = false;
351
352 if (hResCheckResID(voiceRes, s)) {
353 g_vm->_audio->queueVoice(s, Here);
354 if (g_vm->_audio->talking())
355 worked = true;
356 }
357
358 return worked;
359 }
360
361 //-----------------------------------------------------------------------
362 // main loop playback
363
_playLoop(uint32 s)364 void _playLoop(uint32 s) {
365 if (s == g_vm->_audio->currentLoop())
366 return;
367
368 g_vm->_audio->stopLoop();
369
370 if (!s)
371 return;
372
373 g_vm->_audio->playLoop(s, 0, Here);
374 }
375
376 //-----------------------------------------------------------------------
377 // loop playback that disables background loops
378
playLoop(uint32 s)379 void playLoop(uint32 s) {
380 if (s) {
381 } else {
382 _playLoop(s);
383 }
384 }
385
386
387 //-----------------------------------------------------------------------
388 // attenuated sound players
389
playSoundAt(uint32 s,Point32 p)390 void playSoundAt(uint32 s, Point32 p) {
391 debugC(1, kDebugSound, "playSoundAt(%s, %d,%d)", tag2strP(s), p.x, p.y);
392
393 if (hResCheckResID(soundRes, s))
394 g_vm->_audio->queueSound(s, 1, p);
395 }
396
playSoundAt(uint32 s,Location playAt)397 void playSoundAt(uint32 s, Location playAt) {
398 Point32 p = translateLocation(playAt);
399 if (p != VeryFarAway)
400 playSoundAt(s, p);
401 }
402
403 //-----------------------------------------------------------------------
404 // voice playback w/ attenuation
405
sayVoiceAt(uint32 s[],Point32 p)406 bool sayVoiceAt(uint32 s[], Point32 p) {
407 debugCN(1, kDebugSound, "sayVoiceAt([%s", tag2strP(s[0]));
408
409 for (uint32 i = 1; s[i]; i++)
410 debugCN(1, kDebugSound, ", %s", tag2strP(s[i]));
411
412 debugC(1, kDebugSound, "], %d,%d)", p.x, p.y);
413
414 g_vm->_audio->queueVoice(s, p);
415
416 return true;
417 }
418
sayVoiceAt(uint32 s[],Location playAt)419 bool sayVoiceAt(uint32 s[], Location playAt) {
420 Point32 p = translateLocation(playAt);
421 if (p != VeryFarAway)
422 return sayVoiceAt(s, p);
423 return false;
424 }
425
426 //-----------------------------------------------------------------------
427 // loop playback w/ attenuation
428
playLoopAt(uint32 s,Point32 loc)429 void playLoopAt(uint32 s, Point32 loc) {
430 debugC(1, kDebugSound, "playLoopAt(%s, %d,%d)", tag2strP(s), loc.x, loc.y);
431
432 if (hResCheckResID(loopRes, s))
433 g_vm->_audio->playLoop(s, 0, loc);
434 else
435 g_vm->_audio->stopLoop();
436 }
437
438 void addAuxTheme(Location loc, uint32 lid);
439 void killAuxTheme(uint32 lid);
440 void killAllAuxThemes(void);
441
playLoopAt(uint32 s,Location playAt)442 void playLoopAt(uint32 s, Location playAt) {
443 debugC(1, kDebugSound, "playLoopAt(%s, %d,%d,%d)", tag2strP(s), playAt.u, playAt.v, playAt.z);
444
445 if (s) {
446 addAuxTheme(playAt, s);
447 } else {
448 killAllAuxThemes();
449 }
450 }
451
452 //-----------------------------------------------------------------------
453 // loop attenuation
454
moveLoop(Point32 loc)455 void moveLoop(Point32 loc) {
456 g_vm->_audio->setLoopPosition(loc);
457 }
458
moveLoop(Location loc)459 void moveLoop(Location loc) {
460 Point32 p = translateLocation(loc);
461 if (p != VeryFarAway) {
462 moveLoop(p);
463 }
464 }
465
466 //-----------------------------------------------------------------------
467 // supplemental interface check for speech
468
stillDoingVoice(uint32 sampno)469 bool stillDoingVoice(uint32 sampno) {
470 bool result = g_vm->_audio->saying(sampno);
471
472 debugC(1, kDebugSound, "stillDoingVoice(%s) -> %d", tag2strP(sampno), result);
473
474 return result;
475 }
476
stillDoingVoice(uint32 s[])477 bool stillDoingVoice(uint32 s[]) {
478 uint32 *p = s;
479
480 while (*p) {
481 if (g_vm->_audio->saying(*p++))
482 return true;
483 }
484
485 return false;
486 }
487
488 /* ===================================================================== *
489 SAGA compatible audio playback routines
490 * ===================================================================== */
491
492 //-----------------------------------------------------------------------
493 // derive an ID from SAGA string
494
parse_res_id(char IDstr[])495 uint32 parse_res_id(char IDstr[]) {
496 uint32 a[5] = {0, 0, 0, 0, 0};
497 uint32 a2;
498 uint32 i, j;
499 assert(IDstr != NULL);
500 if (strlen(IDstr)) {
501 for (i = 0, j = 0; i < strlen(IDstr); i++) {
502 if (IDstr[i] == ':') {
503 a2 = atoi(IDstr + i + 1);
504 return MKTAG(a[0], a[1], a[2], a2);
505 } else {
506 a[j++] = IDstr[i];
507 }
508 }
509 }
510 return MKTAG(a[0], a[1], a[2], a[3]);
511 }
512
513 //-----------------------------------------------------------------------
514 // playback aliases
515
PlaySound(char IDstr[])516 void PlaySound(char IDstr[]) {
517 if (IDstr == NULL)
518 playSound(0);
519 else
520 playSound(parse_res_id(IDstr));
521 }
522
PlayLongSound(char IDstr[])523 void PlayLongSound(char IDstr[]) {
524 if (IDstr == NULL)
525 playLongSound(0);
526 else
527 playLongSound(parse_res_id(IDstr));
528 }
529
PlayVoice(char IDstr[])530 void PlayVoice(char IDstr[]) {
531 if (IDstr == NULL)
532 playVoice(0);
533 else
534 playVoice(parse_res_id(IDstr));
535 }
536
PlayLoop(char IDstr[])537 void PlayLoop(char IDstr[]) {
538 if (IDstr == NULL)
539 playLoop(0);
540 else
541 playLoop(parse_res_id(IDstr));
542 }
543
PlayLoopAt(char IDstr[],Location l)544 void PlayLoopAt(char IDstr[], Location l) {
545 if (IDstr == NULL)
546 playLoop(0);
547 else
548 playLoopAt(parse_res_id(IDstr), l);
549 }
550
PlayMusic(char IDstr[])551 void PlayMusic(char IDstr[]) {
552 if (IDstr == NULL)
553 playMusic(0);
554 else
555 playMusic(parse_res_id(IDstr));
556 }
557
558 ////////////////////////////////////////////////////////////////
559
initAudio()560 bool initAudio() {
561 g_vm->_audio = new AudioInterface();
562 return true;
563 }
564
AudioInterface()565 AudioInterface::AudioInterface() {
566 _music = nullptr;
567 _mixer = g_system->getMixer();
568
569 memset(_clickSizes, 0, sizeof(_clickSizes));
570 memset(_clickData, 0, sizeof(_clickData));
571 }
572
~AudioInterface()573 AudioInterface::~AudioInterface() {
574 delete _music;
575 free(_clickData[1]);
576 free(_clickData[2]);
577 }
578
initAudioInterface(hResContext * musicContext)579 void AudioInterface::initAudioInterface(hResContext *musicContext) {
580 _music = new Music(musicContext);
581 }
582
playFlag(void)583 bool AudioInterface::playFlag(void) {
584 debugC(5, kDebugSound, "AudioInterface::playFlag()");
585 if (_speechQueue.size() == 0 && !_mixer->isSoundHandleActive(_speechSoundHandle))
586 _currentSpeech.seg = 0;
587
588 return _speechQueue.size() > 0 || _sfxQueue.size() > 0;
589 }
590
playMe(void)591 void AudioInterface::playMe(void) {
592 if (_speechQueue.size() > 0 && !_mixer->isSoundHandleActive(_speechSoundHandle)) {
593 SoundInstance si = _speechQueue.front();
594 _speechQueue.pop_front();
595
596 _currentSpeech = si;
597
598 Common::SeekableReadStream *stream = loadResourceToStream(voiceRes, si.seg, "voice data");
599 Audio::AudioStream *aud = makeShortenStream(*stream);
600 byte vol = g_vm->_speechVoice ? volumeFromDist(si.loc, getVolume(kVolVoice)) : 0;
601
602 _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechSoundHandle, aud, -1, vol);
603
604 delete stream;
605 }
606
607 if (_sfxQueue.size() > 0) {
608 SoundInstance si = _sfxQueue.pop();
609
610 Common::SeekableReadStream *stream = loadResourceToStream(soundRes, si.seg, "sound data");
611 Audio::AudioStream *aud = Audio::makeRawStream(stream, 22050, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
612 byte vol = volumeFromDist(si.loc, getVolume(kVolSfx));
613
614 _mixer->playStream(Audio::Mixer::kSFXSoundType, &_sfxSoundHandle, aud, -1, vol);
615 }
616 }
617
playMusic(uint32 s,int16 loopFactor,Point32 where)618 void AudioInterface::playMusic(uint32 s, int16 loopFactor, Point32 where) {
619 _music->play(s, loopFactor ? MUSIC_LOOP : MUSIC_NORMAL);
620
621 _currentMusic.seg = s;
622 _currentMusic.loop = loopFactor;
623 _currentMusic.loc = where;
624 }
625
stopMusic(void)626 void AudioInterface::stopMusic(void) {
627 _music->stop();
628 }
629
queueSound(uint32 s,int16 loopFactor,Point32 where)630 void AudioInterface::queueSound(uint32 s, int16 loopFactor, Point32 where) {
631 SoundInstance si;
632
633 si.seg = s;
634 si.loop = loopFactor;
635 si.loc = where;
636
637 _sfxQueue.push(si);
638 }
639
playLoop(uint32 s,int16 loopFactor,Point32 where)640 void AudioInterface::playLoop(uint32 s, int16 loopFactor, Point32 where) {
641 _currentLoop.seg = s;
642 _currentLoop.loop = loopFactor;
643 _currentLoop.loc = where;
644
645 Common::SeekableReadStream *stream = loadResourceToStream(loopRes, s, "loop data");
646 Audio::SeekableAudioStream *aud = Audio::makeRawStream(stream, 22050, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
647 Audio::AudioStream *laud = Audio::makeLoopingAudioStream(aud, loopFactor);
648 byte vol = volumeFromDist(where, getVolume(kVolSfx));
649
650 _mixer->playStream(Audio::Mixer::kSFXSoundType, &g_vm->_audio->_loopSoundHandle, laud, -1, vol);
651 }
652
stopLoop(void)653 void AudioInterface::stopLoop(void) {
654 _mixer->stopHandle(_loopSoundHandle);
655 }
656
setLoopPosition(Point32 newLoc)657 void AudioInterface::setLoopPosition(Point32 newLoc) {
658 if (_currentLoop.loc == newLoc)
659 return;
660
661 _currentLoop.loc = newLoc;
662 byte vol = volumeFromDist(newLoc, getVolume(kVolSfx));
663
664 _mixer->setChannelVolume(_loopSoundHandle, vol);
665 }
666
queueVoice(uint32 s,Point32 where)667 void AudioInterface::queueVoice(uint32 s, Point32 where) {
668 SoundInstance si;
669
670 si.seg = s;
671 si.loop = false;
672 si.loc = where;
673
674 _speechQueue.push_back(si);
675 }
676
queueVoice(uint32 s[],Point32 where)677 void AudioInterface::queueVoice(uint32 s[], Point32 where) {
678 SoundInstance si;
679
680 uint32 *p = s;
681 while (*p) {
682 si.seg = *p;
683 si.loop = false;
684 si.loc = where;
685
686 _speechQueue.push_back(si);
687 p++;
688 }
689 }
690
stopVoice(void)691 void AudioInterface::stopVoice(void) {
692 _mixer->stopHandle(_speechSoundHandle);
693 }
694
talking(void)695 bool AudioInterface::talking(void) {
696 return _mixer->isSoundHandleActive(_speechSoundHandle);
697 }
698
saying(uint32 s)699 bool AudioInterface::saying(uint32 s) {
700 if (_currentSpeech.seg == s)
701 return true;
702
703 for (Common::List<SoundInstance>::iterator it = _speechQueue.begin(); it != _speechQueue.end(); ++it)
704 if ((*it).seg == s)
705 return true;
706
707 return false;
708 }
709
getVolume(VolumeTarget src)710 byte AudioInterface::getVolume(VolumeTarget src) {
711 switch (src) {
712 case kVolMusic:
713 return ConfMan.getInt("music_volume");
714
715 case kVolSfx:
716 return ConfMan.getInt("sfx_volume");
717
718 case kVolVoice:
719 return ConfMan.getInt("speech_volume");
720 }
721
722 return 0;
723 }
724
suspend(void)725 void AudioInterface::suspend(void) {
726 _mixer->pauseAll(true);
727 }
728
resume(void)729 void AudioInterface::resume(void) {
730 _mixer->pauseAll(false);
731 }
732
bufCheckResID(hResContext * hrc,uint32 s)733 bool bufCheckResID(hResContext *hrc, uint32 s) {
734 return s != 0;
735 }
736
hResCheckResID(hResContext * hrc,uint32 s)737 bool hResCheckResID(hResContext *hrc, uint32 s) {
738 if (hrc != NULL)
739 return hrc->seek(s);
740 return false;
741 }
742
hResCheckResID(hResContext * hrc,uint32 s[])743 bool hResCheckResID(hResContext *hrc, uint32 s[]) {
744 if (s != NULL) {
745 if (s[0] == 0)
746 return false;
747
748 for (int i = 0; s[i]; i++) {
749 if (!hResCheckResID(hrc, s[i]))
750 return false;
751 }
752 }
753 return true;
754 }
755
756 } // end of namespace Saga2
757