diff options
Diffstat (limited to 'engines/queen/sound.cpp')
-rw-r--r-- | engines/queen/sound.cpp | 643 |
1 files changed, 507 insertions, 136 deletions
diff --git a/engines/queen/sound.cpp b/engines/queen/sound.cpp index 917351f3da..e228d6a1dd 100644 --- a/engines/queen/sound.cpp +++ b/engines/queen/sound.cpp @@ -21,45 +21,47 @@ */ #include "common/stdafx.h" +#include "common/config-manager.h" #include "common/endian.h" +#include "common/stream.h" #include "queen/sound.h" - #include "queen/input.h" +#include "queen/logic.h" #include "queen/music.h" #include "queen/queen.h" #include "queen/resource.h" #include "sound/flac.h" +#include "sound/mididrv.h" #include "sound/mp3.h" #include "sound/vorbis.h" #define SB_HEADER_SIZE_V104 110 #define SB_HEADER_SIZE_V110 122 -#define STOP_MUSIC -1 namespace Queen { -class SilentSound : public Sound { +class SilentSound : public PCSound { public: - SilentSound(Audio::Mixer *mixer, QueenEngine *vm) : Sound(mixer, vm) {} + SilentSound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {} protected: void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) { // Do nothing } }; -class SBSound : public Sound { +class SBSound : public PCSound { public: - SBSound(Audio::Mixer *mixer, QueenEngine *vm) : Sound(mixer, vm) {} + SBSound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {} protected: void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle); }; #ifdef USE_MAD -class MP3Sound : public Sound { +class MP3Sound : public PCSound { public: - MP3Sound(Audio::Mixer *mixer, QueenEngine *vm) : Sound(mixer, vm) {} + MP3Sound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {} protected: void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) { _mixer->playInputStream(Audio::Mixer::kSFXSoundType, soundHandle, Audio::makeMP3Stream(f, size)); @@ -68,9 +70,9 @@ protected: #endif #ifdef USE_VORBIS -class OGGSound : public Sound { +class OGGSound : public PCSound { public: - OGGSound(Audio::Mixer *mixer, QueenEngine *vm) : Sound(mixer, vm) {} + OGGSound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {} protected: void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) { _mixer->playInputStream(Audio::Mixer::kSFXSoundType, soundHandle, Audio::makeVorbisStream(f, size)); @@ -79,9 +81,9 @@ protected: #endif #ifdef USE_FLAC -class FLACSound : public Sound { +class FLACSound : public PCSound { public: - FLACSound(Audio::Mixer *mixer, QueenEngine *vm) : Sound(mixer, vm) {}; + FLACSound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {}; protected: void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) { _mixer->playInputStream(Audio::Mixer::kSFXSoundType, soundHandle, Audio::makeFlacStream(f, size)); @@ -90,15 +92,13 @@ protected: #endif // #ifdef USE_FLAC Sound::Sound(Audio::Mixer *mixer, QueenEngine *vm) : - _mixer(mixer), _vm(vm), _sfxToggle(true), _speechToggle(true), _musicToggle(true), _lastOverride(0) { -#ifdef ENABLE_AMIGA_MUSIC - _lastModuleOverride = -1; -#endif + _mixer(mixer), _vm(vm), _sfxToggle(true), _speechToggle(true), _musicToggle(true), + _speechSfxExists(false), _lastOverride(0), _masterVolume(0) { } Sound *Sound::makeSoundInstance(Audio::Mixer *mixer, QueenEngine *vm, uint8 compression) { - if (!mixer->isReady()) - return new SilentSound(mixer, vm); + if (vm->resource()->getPlatform() == Common::kPlatformAmiga) + return new AmigaSound(mixer, vm); switch (compression) { case COMPRESSION_NONE: @@ -130,135 +130,52 @@ Sound *Sound::makeSoundInstance(Audio::Mixer *mixer, QueenEngine *vm, uint8 comp } } -void Sound::waitFinished(bool isSpeech) { - while (_mixer->isSoundHandleActive(isSpeech ? _speechHandle : _sfxHandle)) - _vm->input()->delay(10); -} - -void Sound::playSfx(uint16 sfx) { - if (sfxOn() && sfx != 0) { -#ifndef PALMOS_68K - playSound(_sfxName[sfx - 1], false); -#else - playSound(_sfxName + 10 * (sfx - 1), false); // saved as 8char + /0/0 -#endif - } -} - -void Sound::playSpeech(const char *base) { - if (speechOn()) { - playSound(base, true); - } +void Sound::saveState(byte *&ptr) { + WRITE_BE_UINT16(ptr, _lastOverride); ptr += 2; } -void Sound::playSound(const char *base, bool isSpeech) { - char name[13]; - strcpy(name, base); - // alter filename to add zeros and append ".SB" - for (int i = 0; i < 8; i++) { - if (name[i] == ' ') - name[i] = '0'; - } - strcat(name, ".SB"); - waitFinished(isSpeech); - uint32 size; - Common::File *f = _vm->resource()->findSound(name, &size); - if (f) { - playSoundData(f, size, isSpeech ? &_speechHandle : &_sfxHandle); - _speechSfxExists = isSpeech; - } else { - _speechSfxExists = false; - } +void Sound::loadState(uint32 ver, byte *&ptr) { + _lastOverride = (int16)READ_BE_INT16(ptr); ptr += 2; } -#ifdef ENABLE_AMIGA_MUSIC - -static struct { - const char *name; - uint8 songNum; - uint8 remapSongNumTable[6]; -} amigaMusicData[] = { - { "HOTEL", 1, { 1, 2, 39, 0 } }, - { "HOTEL", 2, { 20, 30, 34, 0 } }, - { "HOTEL", 3, { 19, 0 } }, - { "HOTEL", 4, { 29, 35, 36, 0 } }, - { "JUNG", 1, { 40, 0 } }, - { "JUNG", 2, { 3, 38, 89, 0 } }, - { "TEMPLE", 1, { 54, 0 } }, - { "TEMPLE", 2, { 12, 0 } }, - { "TEMPLE", 3, { 7, 9, 10, 11, 0 } }, - { "TEMPLE", 4, { 31, 0 } }, - { "FLODA", 1, { 16, 0 } }, - { "FLODA", 2, { 17, 0 } }, - { "FLODA", 3, { 13, 0 } }, - { "FLODA", 4, { 41, 0 } }, - { "FLODA", 5, { 30, 43, 0 } }, - { "TITLE", 1, { 67, 88, 203, 0 } }, - { "AWESTRUK", 1, { 37, 52, 90, 196, 0 } }, - { "'JUNGLE'", 1, { 91, 0 } }, - { "FRANK", 1, { 46, 0 } }, - { "BOB", 1, { 6, 0 } }, - { "AZURA", 1, { 44, 53, 204, 0 } }, - { "FORT", 1, { 21, 0 } }, - { "ROCKET", 1, { 32, 194, 195, 0 } }, - { "ROBOT", 1, { 92, 0 } } -}; - -void Sound::playSong(int16 songNum) { - debug(2, "Sound::playSong %d override %d/%d", songNum, _lastModuleOverride, _lastOverride); +PCSound::PCSound(Audio::Mixer *mixer, QueenEngine *vm) + : Sound(mixer, vm) { - const char *moduleName = 0; - for (int i = 0; i < ARRAYSIZE(amigaMusicData) && !moduleName; ++i) { - for (int j = 0; amigaMusicData[i].remapSongNumTable[j] != 0; ++j) { - if (amigaMusicData[i].remapSongNumTable[j] == songNum) { - moduleName = amigaMusicData[i].name; - songNum = amigaMusicData[i].songNum; + int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - if (_lastModuleOverride == i && _lastOverride == songNum) - return; + MidiDriver *driver = MidiDriver::createMidi(midiDriver); + if (native_mt32) + driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - _lastModuleOverride = i; - _lastOverride = songNum; - break; - } - } - } - if (!moduleName) - return; - - _mixer->stopHandle(_musicHandle); - - debug(1, "playAmigaSong name '%s' subsong %d", moduleName, songNum); - - char buf[16]; - sprintf(buf, "%s.SNG", moduleName); - Common::File fsng; - if (!fsng.open(buf)) - return; - - sprintf(buf, "%s.INS", moduleName); - Common::File fins; - if (!fins.open(buf)) - return; + _music = new Music(driver, vm); + _music->hasNativeMT32(native_mt32); +} - Audio::AudioStream *rjp1Stream = Audio::makeRjp1Stream(&fsng, &fins, songNum); - if (rjp1Stream) { - _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, rjp1Stream); - } +PCSound::~PCSound() { + delete _music; } +void PCSound::playSfx(uint16 sfx) { + if (sfxOn() && sfx != 0) { +#ifndef PALMOS_68K + playSound(_sfxName[sfx - 1], false); #else + playSound(_sfxName + 10 * (sfx - 1), false); // saved as 8char + /0/0 +#endif + } +} -void Sound::playSong(int16 songNum) { +void PCSound::playSong(int16 songNum) { if (songNum <= 0) { - _vm->music()->stopSong(); + _music->stopSong(); return; } int16 newTune; if (_vm->resource()->isDemo()) { if (songNum == 17) { - _vm->music()->stopSong(); + _music->stopSong(); return; } newTune = _songDemo[songNum - 1].tuneList[0] - 1; @@ -281,25 +198,58 @@ void Sound::playSong(int16 songNum) { break; // Alter song settings (such as volume) and exit case 2: - _vm->music()->toggleVChange(); + _music->toggleVChange(); default: return; } _lastOverride = songNum; - _vm->music()->queueTuneList(newTune); - _vm->music()->playMusic(); + _music->queueTuneList(newTune); + _music->playMusic(); } -#endif // ENABLE_AMIGA_MUSIC +void PCSound::stopSong() { + _music->stopSong(); +} -void Sound::saveState(byte *&ptr) { - WRITE_BE_UINT16(ptr, _lastOverride); ptr += 2; +void PCSound::playSpeech(const char *base) { + if (speechOn()) { + playSound(base, true); + } } -void Sound::loadState(uint32 ver, byte *&ptr) { - _lastOverride = (int16)READ_BE_INT16(ptr); ptr += 2; +void PCSound::setVolume(int vol) { + _music->setVolume(vol); +} + +int PCSound::volume() { + return _music->volume(); +} + +void PCSound::waitFinished(bool isSpeech) { + while (_mixer->isSoundHandleActive(isSpeech ? _speechHandle : _sfxHandle)) + _vm->input()->delay(10); +} + +void PCSound::playSound(const char *base, bool isSpeech) { + char name[13]; + strcpy(name, base); + // alter filename to add zeros and append ".SB" + for (int i = 0; i < 8; i++) { + if (name[i] == ' ') + name[i] = '0'; + } + strcat(name, ".SB"); + waitFinished(isSpeech); + uint32 size; + Common::File *f = _vm->resource()->findSound(name, &size); + if (f) { + playSoundData(f, size, isSpeech ? &_speechHandle : &_sfxHandle); + _speechSfxExists = isSpeech; + } else { + _speechSfxExists = false; + } } void SBSound::playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) { @@ -328,4 +278,425 @@ void SBSound::playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *so } } +AmigaSound::AmigaSound(Audio::Mixer *mixer, QueenEngine *vm) + : Sound(mixer, vm), _fanfareRestore(0), _fanfareCount(0), _fluteCount(0) { +} + +void AmigaSound::playSfx(uint16 sfx) { + if (_vm->logic()->currentRoom() == 111) { + // lightning sound + playSound("88SSSSSS"); + } +} + +void AmigaSound::playSong(int16 song) { + debug(2, "Sound::playSong %d override %d", song, _lastOverride); + + if (song < 0) { + stopSong(); + return; + } + + // remap song numbers for the Amiga + switch (song) + { + case 1: + case 2: + song = 39; + break; + case 37: + case 52: + case 196: + song = 90; + break; + case 38: + case 89: + song = 3; + break; + case 24: + case 158: + song = 117; + break; + case 71: + case 72: + case 73: + case 75: + song = 133; + break; + case 203: + song = 67; + break; + case 145: + song = 140; + break; + case 53: + case 204: + song = 44; + break; + case 136: + case 142: + case 179: + song = 86; + break; + case 101: + case 102: + case 143: + song = 188; + break; + case 65: + case 62: + song = 69; + break; + case 118: + case 119: + song = 137; + break; + case 130: + case 131: + song = 59; + break; + case 174: + case 175: + song = 57; + break; + case 171: + case 121: + song = 137; + break; + case 138: + case 170: + case 149: + song = 28; + break; + case 122: + case 180: + case 83: + case 98: + song = 83; + break; + case 20: + case 33: + song = 34; + break; + case 29: + case 35: + song = 36; + break; + case 7: + case 9: + case 10: + song = 11; + break; + case 110: + song = 94; + break; + case 111: + song = 95; + break; + case 30: + song = 43; + break; + case 76: + song = 27; + break; + case 194: + case 195: + song = 32; + break; + } + + if (_lastOverride != 32 && _lastOverride != 44) { + if (playSpecialSfx(song)) { + return; + } + } + + if (_lastOverride == song && _mixer->isSoundHandleActive(_modHandle)) { + return; + } + switch (song) { + // hotel + case 39: + playModule("HOTEL", 1); + break; + case 19: + playModule("HOTEL", 3); + break; + case 34: + playModule("HOTEL", 2); + break; + case 36: + playModule("HOTEL", 4); + _fanfareRestore = _lastOverride; + _fanfareCount = 60; + break; + // jungle + case 40: + playModule("JUNG", 1); + _fanfareRestore = _lastOverride; + _fanfareCount = 80; + _fluteCount = 100; + break; + case 3: + playModule("JUNG", 2); + _fluteCount = 100; + break; + // temple + case 54: + playModule("TEMPLE", 1); + break; + case 12: + playModule("TEMPLE", 2); + break; + case 11: + playModule("TEMPLE", 3); + break; + case 31: + playModule("TEMPLE", 4); + _fanfareRestore = _lastOverride; + _fanfareCount = 80; + break; + // floda + case 41: + playModule("FLODA", 4); + _fanfareRestore = _lastOverride; + _fanfareCount = 60; + break; + case 13: + playModule("FLODA", 3); + break; + case 16: + playModule("FLODA", 1); + break; + case 17: + playModule("FLODA", 2); + break; + case 43: + playModule("FLODA", 5); + break; + // end credits + case 67: + playModule("TITLE", 1); + break; + // intro credits + case 88: + playModule("TITLE", 1); + break; + // valley + case 90: + playModule("AWESTRUK", 1); + break; + // confrontation + case 91: + playModule("'JUNGLE'", 1); + break; + // Frank + case 46: + playModule("FRANK", 1); + break; + // trader bob + case 6: + playModule("BOB", 1); + break; + // azura + case 44: + playModule("AZURA", 1); + break; + // amazon fortress + case 21: + playModule("FORT", 1); + break; + // rocket + case 32: + playModule("ROCKET", 1); + break; + // robot + case 92: + playModule("ROBOT", 1); + break; + default: + // song not available in the amiga version + return; + } + _lastOverride = song; +} + +void AmigaSound::stopSfx() { + _mixer->stopHandle(_sfxHandle); +} + +void AmigaSound::stopSong() { + _mixer->stopHandle(_modHandle); + _fanfareCount = _fluteCount = 0; +} + +void AmigaSound::updateMusic() { + if (_fanfareCount > 0) { + --_fanfareCount; + if (_fanfareCount == 0) { + playSong(_fanfareRestore); + } + } + if (_fluteCount > 0 && (_lastOverride == 40 || _lastOverride == 3)) { + --_fluteCount; + if (_fluteCount == 0) { +// playPattern(3, 5 + (getRandomNumber() & 7)); + _fluteCount = 100; + } + } +} + +void AmigaSound::playSound(const char *base) { + char soundName[20]; + sprintf(soundName, "%s.AMR", base); + + uint32 soundSize; + Common::File *f = _vm->resource()->findSound(soundName, &soundSize); + if (f) { + uint8 *soundData = (uint8 *)malloc(soundSize); + if (soundData) { + f->read(soundData, soundSize); + byte flags = Audio::Mixer::FLAG_AUTOFREE; + _mixer->playRaw(Audio::Mixer::kSFXSoundType, &_sfxHandle, soundData, soundSize, 11025, flags); + } + } +} + +void AmigaSound::playModule(const char *base, int song) { + char name[20]; + + // load song/pattern data + uint32 sngDataSize; + sprintf(name, "%s.SNG", base); + uint8 *sngData = _vm->resource()->loadFile(name, 0, &sngDataSize); + Common::MemoryReadStream sngStr(sngData, sngDataSize); + + // load instruments/wave data + uint32 insDataSize; + sprintf(name, "%s.INS", base); + uint8 *insData = _vm->resource()->loadFile(name, 0, &insDataSize); + Common::MemoryReadStream insStr(insData, insDataSize); + + _mixer->stopHandle(_modHandle); + Audio::AudioStream *stream = Audio::makeRjp1Stream(&sngStr, &insStr, song, _mixer->getOutputRate()); + if (stream) { + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_modHandle, stream); + } + + delete[] sngData; + delete[] insData; + + _fanfareCount = 0; +} + +bool AmigaSound::playSpecialSfx(int16 sfx) { + switch (sfx) { + case 5: // normal volume + break; + case 15: // soft volume + break; + case 14: // medium volume + break; + case 25: // open door + playSound("116BSSSS"); + break; + case 26: // close door + playSound("105ASSSS"); + break; + case 56: // light switch + playSound("27SSSSSS"); + break; + case 57: // hydraulic doors open + playSound("96SSSSSS"); + break; + case 58: // hydraulic doors close + playSound("97SSSSSS"); + break; + case 59: // metallic door slams + playSound("105SSSSS"); + break; + case 63: // oracle rezzes in + playSound("132SSSSS"); + break; + case 27: // cloth slide 1 + playSound("135SSSSS"); + break; + case 83: // splash + playSound("18SSSSSS"); + break; + case 85: // agression enhancer + playSound("138BSSSS"); + break; + case 68: // dino ray + playSound("138SSSSS"); + break; + case 140: // dino transformation + playSound("55BSSSSS"); + break; + case 141: // experimental laser + playSound("55SSSSSS"); + break; + case 94: // plane hatch open + playSound("3SSSSSSS"); + break; + case 95: // plane hatch close + playSound("4SSSSSSS"); + break; + case 117: // oracle rezzes out + playSound("70SSSSSS"); + break; + case 124: // dino horn + playSound("103SSSSS"); + break; + case 127: // punch + playSound("128SSSSS"); + break; + case 128: // body hits ground + playSound("129SSSSS"); + break; + case 137: // explosion + playSound("88SSSSSS"); + break; + case 86: // stone door grind 1 + playSound("1001SSSS"); + break; + case 188: // stone door grind 2 + playSound("1002SSSS"); + break; + case 28: // cloth slide 2 + playSound("1005SSSS"); + break; + case 151: // rattle bars + playSound("115SSSSS"); + break; + case 152: // door dissolves + playSound("56SSSSSS"); + break; + case 153: // altar slides + playSound("85SSSSSS"); + break; + case 166 : // pull lever + playSound("1008SSSS"); + break; + case 182: // zap Frank + playSound("1023SSSS"); + break; + case 69: // splorch + playSound("137ASSSS"); + break; + case 70: // robot laser + playSound("61SSSSSS"); + break; + case 133: // pick hits stone + playSound("71SSSSSS"); + break; + case 165: // press button + playSound("1007SSSS"); + break; + default: + return false; + } + return true; +} + } //End of namespace Queen |