diff options
-rw-r--r-- | engines/queen/sound.cpp | 29 | ||||
-rw-r--r-- | engines/queen/sound.h | 4 | ||||
-rw-r--r-- | sound/mods/rjp1.cpp | 175 | ||||
-rw-r--r-- | sound/mods/rjp1.h | 2 |
4 files changed, 141 insertions, 69 deletions
diff --git a/engines/queen/sound.cpp b/engines/queen/sound.cpp index 8b82f715ca..6f7bbc4b2c 100644 --- a/engines/queen/sound.cpp +++ b/engines/queen/sound.cpp @@ -541,7 +541,7 @@ void AmigaSound::updateMusic() { if (_fluteCount > 0 && (_lastOverride == 40 || _lastOverride == 3)) { --_fluteCount; if (_fluteCount == 0) { - playRandomPatternJungle(); + playPattern("JUNG", 5 + _vm->randomizer.getRandomNumber(6)); _fluteCount = 100; } } @@ -564,8 +564,8 @@ void AmigaSound::playSound(const char *base) { } } -void AmigaSound::playModule(const char *base, int song) { - debug(7, "AmigaSound::playModule(%s, %d)", base, song); +Audio::AudioStream *AmigaSound::loadModule(const char *base, int num) { + debug(7, "AmigaSound::loadModule(%s, %d)", base, num); char name[20]; // load song/pattern data @@ -580,20 +580,29 @@ void AmigaSound::playModule(const char *base, int song) { 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); - } + Audio::AudioStream *stream = Audio::makeRjp1Stream(&sngStr, &insStr, num, _mixer->getOutputRate()); delete[] sngData; delete[] insData; + return stream; +} + +void AmigaSound::playModule(const char *base, int song) { + _mixer->stopHandle(_modHandle); + Audio::AudioStream *stream = loadModule(base, song); + if (stream) { + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_modHandle, stream); + } _fanfareCount = 0; } -void AmigaSound::playRandomPatternJungle() { - // XXX pickup a pattern (songData[4],songData[6]) between 5 and 11 from JUNG.SNG and play it +void AmigaSound::playPattern(const char *base, int pattern) { + _mixer->stopHandle(_patHandle); + Audio::AudioStream *stream = loadModule(base, -pattern); + if (stream) { + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_patHandle, stream); + } } bool AmigaSound::playSpecialSfx(int16 sfx) { diff --git a/engines/queen/sound.h b/engines/queen/sound.h index 3906167193..e2a279c09b 100644 --- a/engines/queen/sound.h +++ b/engines/queen/sound.h @@ -170,13 +170,15 @@ public: protected: void playSound(const char *base); + Audio::AudioStream *loadModule(const char *base, int song); void playModule(const char *base, int song); - void playRandomPatternJungle(); + void playPattern(const char *base, int pattern); bool playSpecialSfx(int16 sfx); int16 _fanfareRestore; int _fanfareCount, _fluteCount; Audio::SoundHandle _modHandle; + Audio::SoundHandle _patHandle; Audio::SoundHandle _sfxHandle; }; diff --git a/sound/mods/rjp1.cpp b/sound/mods/rjp1.cpp index 59b8833607..0eb6b0d16b 100644 --- a/sound/mods/rjp1.cpp +++ b/sound/mods/rjp1.cpp @@ -70,6 +70,7 @@ struct Rjp1Channel { uint16 len; uint16 repeatPos; uint16 repeatLen; + bool isSfx; }; class Rjp1 : public Paula { @@ -90,6 +91,7 @@ public: bool load(Common::SeekableReadStream *songData, Common::SeekableReadStream *instrumentsData); void unload(); + void startPattern(int ch, int pat); void startSong(int song); protected: @@ -98,6 +100,8 @@ protected: void turnOffChannel(Rjp1Channel *channel); void playChannel(Rjp1Channel *channel); void turnOnChannel(Rjp1Channel *channel); + bool executeSfxSequenceOp(Rjp1Channel *channel, uint8 code, const uint8 *&p); + bool executeSongSequenceOp(Rjp1Channel *channel, uint8 code, const uint8 *&p); void playSongSequence(Rjp1Channel *channel); void modulateVolume(Rjp1Channel *channel); void modulatePeriod(Rjp1Channel *channel); @@ -186,6 +190,18 @@ void Rjp1::unload() { memset(_channelsTable, 0, sizeof(_channelsTable)); } +void Rjp1::startPattern(int ch, int pat) { + Rjp1Channel *channel = &_channelsTable[ch]; + _vars.activeChannelsMask |= 1 << ch; + channel->sequenceData = READ_BE_UINT32(_vars.songData[4] + pat * 4) + _vars.songData[6]; + channel->loopSeqCount = 6; + channel->loopSeqCur = channel->loopSeq2Cur = 1; + channel->active = true; + channel->isSfx = true; + // "start" Paula audiostream + startPaula(); +} + void Rjp1::startSong(int song) { if (song == 0 || song >= _vars.subsongsCount) { warning("Invalid subsong number %d, defaulting to 1", song); @@ -241,6 +257,98 @@ void Rjp1::turnOnChannel(Rjp1Channel *channel) { } } +bool Rjp1::executeSfxSequenceOp(Rjp1Channel *channel, uint8 code, const uint8 *&p) { + bool loop = true; + switch (code & 7) { + case 0: + _vars.activeChannelsMask &= ~(1 << _vars.currentChannel); + loop = false; + stopPaula(); + break; + case 1: + setRelease(channel); + loop = false; + break; + case 2: + channel->loopSeqCount = *p++; + break; + case 3: + channel->loopSeq2Count = *p++; + break; + case 4: + code = *p++; + if (code != 0) { + setupInstrument(channel, code); + } + break; + case 7: + loop = false; + break; + } + return loop; +} + +bool Rjp1::executeSongSequenceOp(Rjp1Channel *channel, uint8 code, const uint8 *&p) { + bool loop = true; + const uint8 *offs; + switch (code & 7) { + case 0: + offs = channel->sequenceOffsets; + channel->loopSeq2Count = 1; + while (1) { + code = *offs++; + if (code != 0) { + channel->sequenceOffsets = offs; + p = READ_BE_UINT32(_vars.songData[4] + code * 4) + _vars.songData[6]; + break; + } else { + code = offs[0]; + if (code == 0) { + p = 0; + channel->active = false; + _vars.activeChannelsMask &= ~(1 << _vars.currentChannel); + loop = false; + break; + } else if (code & 0x80) { + code = offs[1]; + offs = READ_BE_UINT32(_vars.songData[3] + code * 4) + _vars.songData[5]; + } else { + offs -= code; + } + } + } + break; + case 1: + setRelease(channel); + loop = false; + break; + case 2: + channel->loopSeqCount = *p++; + break; + case 3: + channel->loopSeq2Count = *p++; + break; + case 4: + code = *p++; + if (code != 0) { + setupInstrument(channel, code); + } + break; + case 5: + channel->volumeScale = *p++; + break; + case 6: + channel->freqStep = *p++; + channel->freqInc = READ_BE_UINT32(p); p += 4; + channel->freqInit = 0; + break; + case 7: + loop = false; + break; + } + return loop; +} + void Rjp1::playSongSequence(Rjp1Channel *channel) { const uint8 *p = channel->sequenceData; --channel->loopSeqCur; @@ -251,61 +359,10 @@ void Rjp1::playSongSequence(Rjp1Channel *channel) { do { uint8 code = *p++; if (code & 0x80) { - const uint8 *offs; - switch (code & 7) { - case 0: - offs = channel->sequenceOffsets; - channel->loopSeq2Count = 1; - while (1) { - code = *offs++; - if (code != 0) { - channel->sequenceOffsets = offs; - p = READ_BE_UINT32(_vars.songData[4] + code * 4) + _vars.songData[6]; - break; - } else { - code = offs[0]; - if (code == 0) { - p = 0; - channel->active = false; - _vars.activeChannelsMask &= ~(1 << _vars.currentChannel); - loop = false; - break; - } else if (code & 0x80) { - code = offs[1]; - offs = READ_BE_UINT32(_vars.songData[3] + code * 4) + _vars.songData[5]; - } else { - offs -= code; - } - } - } - break; - case 1: - setRelease(channel); - loop = false; - break; - case 2: - channel->loopSeqCount = *p++; - break; - case 3: - channel->loopSeq2Count = *p++; - break; - case 4: - code = *p++; - if (code != 0) { - setupInstrument(channel, code); - } - break; - case 5: - channel->volumeScale = *p++; - break; - case 6: - channel->freqStep = *p++; - channel->freqInc = READ_BE_UINT32(p); p += 4; - channel->freqInit = 0; - break; - case 7: - loop = false; - break; + if (channel->isSfx) { + loop = executeSfxSequenceOp(channel, code, p); + } else { + loop = executeSongSequenceOp(channel, code, p); } } else { code >>= 1; @@ -507,10 +564,14 @@ const int16 Rjp1::_periodsTable[] = { const int Rjp1::_periodsCount = ARRAYSIZE(_periodsTable); -AudioStream *makeRjp1Stream(Common::SeekableReadStream *songData, Common::SeekableReadStream *instrumentsData, int song, int rate, bool stereo) { +AudioStream *makeRjp1Stream(Common::SeekableReadStream *songData, Common::SeekableReadStream *instrumentsData, int num, int rate, bool stereo) { Rjp1 *stream = new Rjp1(rate, stereo); if (stream->load(songData, instrumentsData)) { - stream->startSong(song); + if (num < 0) { + stream->startPattern(3, -num); + } else { + stream->startSong(num); + } return stream; } delete stream; diff --git a/sound/mods/rjp1.h b/sound/mods/rjp1.h index d263d11897..2fb54d88a6 100644 --- a/sound/mods/rjp1.h +++ b/sound/mods/rjp1.h @@ -32,7 +32,7 @@ namespace Audio { class AudioStream; -AudioStream *makeRjp1Stream(Common::SeekableReadStream *songData, Common::SeekableReadStream *instrumentsData, int song, int rate = 44100, bool stereo = true); +AudioStream *makeRjp1Stream(Common::SeekableReadStream *songData, Common::SeekableReadStream *instrumentsData, int num, int rate = 44100, bool stereo = true); } // End of namespace Audio |