diff options
Diffstat (limited to 'sound/mods/rjp1.cpp')
-rw-r--r-- | sound/mods/rjp1.cpp | 582 |
1 files changed, 0 insertions, 582 deletions
diff --git a/sound/mods/rjp1.cpp b/sound/mods/rjp1.cpp deleted file mode 100644 index be376d61a4..0000000000 --- a/sound/mods/rjp1.cpp +++ /dev/null @@ -1,582 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/debug.h" -#include "common/endian.h" - -#include "sound/mods/paula.h" -#include "sound/mods/rjp1.h" -#include "sound/audiostream.h" - -namespace Audio { - -struct Rjp1Channel { - const int8 *waveData; - const int8 *modulatePeriodData; - const int8 *modulateVolumeData; - const int8 *envelopeData; - uint16 volumeScale; - int16 volume; - uint16 modulatePeriodBase; - uint32 modulatePeriodLimit; - uint32 modulatePeriodIndex; - uint16 modulateVolumeBase; - uint32 modulateVolumeLimit; - uint32 modulateVolumeIndex; - uint8 freqStep; - uint32 freqInc; - uint32 freqInit; - const uint8 *noteData; - const uint8 *sequenceOffsets; - const uint8 *sequenceData; - uint8 loopSeqCount; - uint8 loopSeqCur; - uint8 loopSeq2Count; - uint8 loopSeq2Cur; - bool active; - int16 modulatePeriodInit; - int16 modulatePeriodNext; - bool setupNewNote; - int8 envelopeMode; - int8 envelopeScale; - int8 envelopeEnd1; - int8 envelopeEnd2; - int8 envelopeStart; - int8 envelopeVolume; - uint8 currentInstrument; - const int8 *data; - uint16 pos; - uint16 len; - uint16 repeatPos; - uint16 repeatLen; - bool isSfx; -}; - -class Rjp1 : public Paula { -public: - - struct Vars { - int8 *instData; - uint8 *songData[7]; - uint8 activeChannelsMask; - uint8 currentChannel; - int subsongsCount; - int instrumentsCount; - }; - - Rjp1(int rate, bool stereo); - virtual ~Rjp1(); - - bool load(Common::SeekableReadStream *songData, Common::SeekableReadStream *instrumentsData); - void unload(); - - void startPattern(int ch, int pat); - void startSong(int song); - -protected: - - void startSequence(uint8 channelNum, uint8 seqNum); - 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); - void setupNote(Rjp1Channel *channel, int16 freq); - void setupInstrument(Rjp1Channel *channel, uint8 num); - void setRelease(Rjp1Channel *channel); - void modulateVolumeEnvelope(Rjp1Channel *channel); - void setSustain(Rjp1Channel *channel); - void setDecay(Rjp1Channel *channel); - void modulateVolumeWaveform(Rjp1Channel *channel); - void setVolume(Rjp1Channel *channel); - - void stopPaulaChannel(uint8 channel); - void setupPaulaChannel(uint8 channel, const int8 *waveData, uint16 offset, uint16 len, uint16 repeatPos, uint16 repeatLen); - - virtual void interrupt(); - - Vars _vars; - Rjp1Channel _channelsTable[4]; - - static const int16 _periodsTable[]; - static const int _periodsCount; -}; - -Rjp1::Rjp1(int rate, bool stereo) - : Paula(stereo, rate, rate / 50) { - memset(&_vars, 0, sizeof(_vars)); - memset(_channelsTable, 0, sizeof(_channelsTable)); -} - -Rjp1::~Rjp1() { - unload(); -} - -bool Rjp1::load(Common::SeekableReadStream *songData, Common::SeekableReadStream *instrumentsData) { - if (songData->readUint32BE() == MKID_BE('RJP1') && songData->readUint32BE() == MKID_BE('SMOD')) { - for (int i = 0; i < 7; ++i) { - uint32 size = songData->readUint32BE(); - _vars.songData[i] = (uint8 *)malloc(size); - if (!_vars.songData[i]) - return false; - - songData->read(_vars.songData[i], size); - switch (i) { - case 0: - _vars.instrumentsCount = size / 32; - break; - case 1: - break; - case 2: - // sequence index to offsets, 1 per channel - _vars.subsongsCount = size / 4; - break; - case 3: - case 4: - // sequence offsets - break; - case 5: - case 6: - // sequence data - break; - } - } - - if (instrumentsData->readUint32BE() == MKID_BE('RJP1')) { - uint32 size = instrumentsData->size() - 4; - _vars.instData = (int8 *)malloc(size); - if (!_vars.instData) - return false; - - instrumentsData->read(_vars.instData, size); - - } - } - - debug(5, "Rjp1::load() _instrumentsCount = %d _subsongsCount = %d", _vars.instrumentsCount, _vars.subsongsCount); - return true; -} - -void Rjp1::unload() { - for (int i = 0; i < 7; ++i) { - free(_vars.songData[i]); - } - free(_vars.instData); - memset(&_vars, 0, sizeof(_vars)); - 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); - song = 1; - } - const uint8 *p = _vars.songData[2] + (song & 0x3F) * 4; - for (int i = 0; i < 4; ++i) { - uint8 seq = *p++; - if (seq) { - startSequence(i, seq); - } - } - // "start" Paula audiostream - startPaula(); -} - -void Rjp1::startSequence(uint8 channelNum, uint8 seqNum) { - Rjp1Channel *channel = &_channelsTable[channelNum]; - _vars.activeChannelsMask |= 1 << channelNum; - if (seqNum != 0) { - const uint8 *p = READ_BE_UINT32(_vars.songData[3] + seqNum * 4) + _vars.songData[5]; - uint8 seq = *p++; - channel->sequenceOffsets = p; - channel->sequenceData = READ_BE_UINT32(_vars.songData[4] + seq * 4) + _vars.songData[6]; - channel->loopSeqCount = 6; - channel->loopSeqCur = channel->loopSeq2Cur = 1; - channel->active = true; - } else { - channel->active = false; - turnOffChannel(channel); - } -} - -void Rjp1::turnOffChannel(Rjp1Channel *channel) { - stopPaulaChannel(channel - _channelsTable); -} - -void Rjp1::playChannel(Rjp1Channel *channel) { - if (channel->active) { - turnOnChannel(channel); - if (channel->sequenceData) { - playSongSequence(channel); - } - modulateVolume(channel); - modulatePeriod(channel); - } -} - -void Rjp1::turnOnChannel(Rjp1Channel *channel) { - if (channel->setupNewNote) { - channel->setupNewNote = false; - setupPaulaChannel(channel - _channelsTable, channel->data, channel->pos, channel->len, channel->repeatPos, channel->repeatLen); - } -} - -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; - if (channel->loopSeqCur == 0) { - --channel->loopSeq2Cur; - if (channel->loopSeq2Cur == 0) { - bool loop = true; - do { - uint8 code = *p++; - if (code & 0x80) { - if (channel->isSfx) { - loop = executeSfxSequenceOp(channel, code, p); - } else { - loop = executeSongSequenceOp(channel, code, p); - } - } else { - code >>= 1; - if (code < _periodsCount) { - setupNote(channel, _periodsTable[code]); - } - loop = false; - } - } while (loop); - channel->sequenceData = p; - channel->loopSeq2Cur = channel->loopSeq2Count; - } - channel->loopSeqCur = channel->loopSeqCount; - } -} - -void Rjp1::modulateVolume(Rjp1Channel *channel) { - modulateVolumeEnvelope(channel); - modulateVolumeWaveform(channel); - setVolume(channel); -} - -void Rjp1::modulatePeriod(Rjp1Channel *channel) { - if (channel->modulatePeriodData) { - uint32 per = channel->modulatePeriodIndex; - int period = (channel->modulatePeriodData[per] * channel->modulatePeriodInit) / 128; - period = -period; - if (period < 0) { - period /= 2; - } - channel->modulatePeriodNext = period + channel->modulatePeriodInit; - ++per; - if (per == channel->modulatePeriodLimit) { - per = channel->modulatePeriodBase * 2; - } - channel->modulatePeriodIndex = per; - } - if (channel->freqStep != 0) { - channel->freqInit += channel->freqInc; - --channel->freqStep; - } - setChannelPeriod(channel - _channelsTable, channel->freqInit + channel->modulatePeriodNext); -} - -void Rjp1::setupNote(Rjp1Channel *channel, int16 period) { - const uint8 *note = channel->noteData; - if (note) { - channel->modulatePeriodInit = channel->modulatePeriodNext = period; - channel->freqInit = 0; - const int8 *e = (const int8 *)_vars.songData[1] + READ_BE_UINT16(note + 12); - channel->envelopeData = e; - channel->envelopeStart = e[1]; - channel->envelopeScale = e[1] - e[0]; - channel->envelopeEnd2 = e[2]; - channel->envelopeEnd1 = e[2]; - channel->envelopeMode = 4; - channel->data = channel->waveData; - channel->pos = READ_BE_UINT16(note + 16); - channel->len = channel->pos + READ_BE_UINT16(note + 18); - channel->setupNewNote = true; - } -} - -void Rjp1::setupInstrument(Rjp1Channel *channel, uint8 num) { - if (channel->currentInstrument != num) { - channel->currentInstrument = num; - const uint8 *p = _vars.songData[0] + num * 32; - channel->noteData = p; - channel->repeatPos = READ_BE_UINT16(p + 20); - channel->repeatLen = READ_BE_UINT16(p + 22); - channel->volumeScale = READ_BE_UINT16(p + 14); - channel->modulatePeriodBase = READ_BE_UINT16(p + 24); - channel->modulatePeriodIndex = 0; - channel->modulatePeriodLimit = READ_BE_UINT16(p + 26) * 2; - channel->modulateVolumeBase = READ_BE_UINT16(p + 28); - channel->modulateVolumeIndex = 0; - channel->modulateVolumeLimit = READ_BE_UINT16(p + 30) * 2; - channel->waveData = _vars.instData + READ_BE_UINT32(p); - uint32 off = READ_BE_UINT32(p + 4); - if (off) { - channel->modulatePeriodData = _vars.instData + off; - } - off = READ_BE_UINT32(p + 8); - if (off) { - channel->modulateVolumeData = _vars.instData + off; - } - } -} - -void Rjp1::setRelease(Rjp1Channel *channel) { - const int8 *e = channel->envelopeData; - if (e) { - channel->envelopeStart = 0; - channel->envelopeScale = -channel->envelopeVolume; - channel->envelopeEnd2 = e[5]; - channel->envelopeEnd1 = e[5]; - channel->envelopeMode = -1; - } -} - -void Rjp1::modulateVolumeEnvelope(Rjp1Channel *channel) { - if (channel->envelopeMode) { - int16 es = channel->envelopeScale; - if (es) { - int8 m = channel->envelopeEnd1; - if (m == 0) { - es = 0; - } else { - es *= m; - m = channel->envelopeEnd2; - if (m == 0) { - es = 0; - } else { - es /= m; - } - } - } - channel->envelopeVolume = channel->envelopeStart - es; - --channel->envelopeEnd1; - if (channel->envelopeEnd1 == -1) { - switch (channel->envelopeMode) { - case 0: - break; - case 2: - setSustain(channel); - break; - case 4: - setDecay(channel); - break; - case -1: - setSustain(channel); - break; - default: - error("Unhandled envelope mode %d", channel->envelopeMode); - break; - } - return; - } - } - channel->volume = channel->envelopeVolume; -} - -void Rjp1::setSustain(Rjp1Channel *channel) { - channel->envelopeMode = 0; -} - -void Rjp1::setDecay(Rjp1Channel *channel) { - const int8 *e = channel->envelopeData; - if (e) { - channel->envelopeStart = e[3]; - channel->envelopeScale = e[3] - e[1]; - channel->envelopeEnd2 = e[4]; - channel->envelopeEnd1 = e[4]; - channel->envelopeMode = 2; - } -} - -void Rjp1::modulateVolumeWaveform(Rjp1Channel *channel) { - if (channel->modulateVolumeData) { - uint32 i = channel->modulateVolumeIndex; - channel->volume += channel->modulateVolumeData[i] * channel->volume / 128; - ++i; - if (i == channel->modulateVolumeLimit) { - i = channel->modulateVolumeBase * 2; - } - channel->modulateVolumeIndex = i; - } -} - -void Rjp1::setVolume(Rjp1Channel *channel) { - channel->volume = (channel->volume * channel->volumeScale) / 64; - channel->volume = CLIP<int16>(channel->volume, 0, 64); - setChannelVolume(channel - _channelsTable, channel->volume); -} - -void Rjp1::stopPaulaChannel(uint8 channel) { - clearVoice(channel); -} - -void Rjp1::setupPaulaChannel(uint8 channel, const int8 *waveData, uint16 offset, uint16 len, uint16 repeatPos, uint16 repeatLen) { - if (waveData) { - setChannelData(channel, waveData, waveData + repeatPos * 2, len * 2, repeatLen * 2, offset * 2); - } -} - -void Rjp1::interrupt() { - for (int i = 0; i < 4; ++i) { - _vars.currentChannel = i; - playChannel(&_channelsTable[i]); - } -} - -const int16 Rjp1::_periodsTable[] = { - 0x01C5, 0x01E0, 0x01FC, 0x021A, 0x023A, 0x025C, 0x0280, 0x02A6, 0x02D0, - 0x02FA, 0x0328, 0x0358, 0x00E2, 0x00F0, 0x00FE, 0x010D, 0x011D, 0x012E, - 0x0140, 0x0153, 0x0168, 0x017D, 0x0194, 0x01AC, 0x0071, 0x0078, 0x007F, - 0x0087, 0x008F, 0x0097, 0x00A0, 0x00AA, 0x00B4, 0x00BE, 0x00CA, 0x00D6 -}; - -const int Rjp1::_periodsCount = ARRAYSIZE(_periodsTable); - -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)) { - if (num < 0) { - stream->startPattern(3, -num); - } else { - stream->startSong(num); - } - return stream; - } - delete stream; - return 0; -} - -} // End of namespace Audio |