diff options
author | Walter van Niftrik | 2009-05-24 22:32:21 +0000 |
---|---|---|
committer | Walter van Niftrik | 2009-05-24 22:32:21 +0000 |
commit | 8adc9480011757f3c90a718537b0ccf99f70e210 (patch) | |
tree | 7a464c3f84ad4d59f5423d2406bff8885c6bf5c6 | |
parent | eba025f48f99b1538ebbf71ca5b815e76083b78f (diff) | |
download | scummvm-rg350-8adc9480011757f3c90a718537b0ccf99f70e210.tar.gz scummvm-rg350-8adc9480011757f3c90a718537b0ccf99f70e210.tar.bz2 scummvm-rg350-8adc9480011757f3c90a718537b0ccf99f70e210.zip |
SCI: Adlib: added support for rhythm channel
svn-id: r40874
-rw-r--r-- | engines/sci/sfx/iterator.cpp | 8 | ||||
-rw-r--r-- | engines/sci/sfx/softseq/adlib.cpp | 67 | ||||
-rw-r--r-- | engines/sci/sfx/softseq/adlib.h | 12 |
3 files changed, 57 insertions, 30 deletions
diff --git a/engines/sci/sfx/iterator.cpp b/engines/sci/sfx/iterator.cpp index de362a79b7..96bdee84b5 100644 --- a/engines/sci/sfx/iterator.cpp +++ b/engines/sci/sfx/iterator.cpp @@ -131,12 +131,18 @@ void SongIteratorChannel::resetSynthChannels() { tell_synth_func *tell = sfx_get_player_tell_func(); for (int i = 0; i < MIDI_CHANNELS; i++) { - if (saw_notes & (1 << i)) { + if (playmask & (1 << i)) { buf[0] = 0xe0 | i; /* Pitch bend */ buf[1] = 0x80; /* Wheel center */ buf[2] = 0x40; if (tell) tell(3, buf); + + buf[0] = 0xb0 | i; // Set control + buf[1] = 0x40; // Hold pedal + buf[2] = 0x00; // Off + if (tell) + tell(3, buf); /* TODO: Reset other controls? */ } } diff --git a/engines/sci/sfx/softseq/adlib.cpp b/engines/sci/sfx/softseq/adlib.cpp index 778903cb6d..d788ea38d8 100644 --- a/engines/sci/sfx/softseq/adlib.cpp +++ b/engines/sci/sfx/softseq/adlib.cpp @@ -111,6 +111,9 @@ void MidiDriver_Adlib::close() { _mixer->stopHandle(_mixerSoundHandle); delete _opl; + + if (_rhythmKeyMap) + delete[] _rhythmKeyMap; } void MidiDriver_Adlib::setVolume(byte volume) { @@ -124,10 +127,6 @@ void MidiDriver_Adlib::send(uint32 b) { byte op1 = (b >> 8) & 0xff; byte op2 = (b >> 16) & 0xff; - // FIXME: Remove this hack after adding support for the rhythm channel - if (channel == 9) - return; - switch (command) { case 0x80: noteOff(channel, op1); @@ -201,14 +200,12 @@ void MidiDriver_Adlib::generateSamples(int16 *data, int len) { } } -void MidiDriver_Adlib::sysEx(const byte *msg, uint16 length) { +void MidiDriver_Adlib::loadInstrument(const byte *ins) { AdlibPatch patch; - assert(length == 28); - // Set data for the operators for (int i = 0; i < 2; i++) { - const byte *op = msg + i * 13; + const byte *op = ins + i * 13; patch.op[i].kbScaleLevel = op[0] & 0x3; patch.op[i].frequencyMult = op[1] & 0xf; patch.op[i].attackRate = op[3] & 0xf; @@ -221,12 +218,12 @@ void MidiDriver_Adlib::sysEx(const byte *msg, uint16 length) { patch.op[i].vibrato = op[10]; patch.op[i].kbScaleRate = op[11]; } - patch.op[0].waveForm = msg[26] & 0x3; - patch.op[1].waveForm = msg[27] & 0x3; + patch.op[0].waveForm = ins[26] & 0x3; + patch.op[1].waveForm = ins[27] & 0x3; // Set data for the modulator - patch.mod.feedback = msg[2] & 0x7; - patch.mod.algorithm = !msg[12]; // Flag is inverted + patch.mod.feedback = ins[2] & 0x7; + patch.mod.algorithm = !ins[12]; // Flag is inverted _patches.push_back(patch); } @@ -442,10 +439,16 @@ void MidiDriver_Adlib::noteOff(int channel, int note) { void MidiDriver_Adlib::voiceOn(int voice, int note, int velocity) { int channel = _voices[voice].channel; - int patch = _channels[channel].patch; + int patch; _voices[voice].age = 0; + if (channel == 9) { + patch = CLIP(note, 27, 88) + 101; + } else { + patch = _channels[channel].patch; + } + // Set patch if different from current patch if ((patch != _voices[voice].patch) && _playSwitch) { _voices[voice].patch = patch; @@ -464,9 +467,14 @@ void MidiDriver_Adlib::voiceOff(int voice) { } void MidiDriver_Adlib::setNote(int voice, int note, bool key) { + int channel = _voices[voice].channel; int n, fre, oct; float delta; - int bend = _channels[_voices[voice].channel].pitchWheel; + int bend = _channels[channel].pitchWheel; + + if ((channel == 9) && _rhythmKeyMap) { + note = _rhythmKeyMap[CLIP(note, 27, 88) - 27]; + } _voices[voice].note = note; @@ -557,6 +565,11 @@ void MidiDriver_Adlib::setVelocityReg(int regOffset, int velocity, int kbScaleLe } void MidiDriver_Adlib::setPatch(int voice, int patch) { + if ((patch < 0) || ((uint)patch >= _patches.size())) { + warning("ADLIB: Invalid patch %i requested", patch); + return; + } + AdlibModulator &mod = _patches[patch].mod; // Set the common settings for both operators @@ -596,6 +609,21 @@ void MidiDriver_Adlib::playSwitch(bool play) { renewNotes(-1, play); } +void MidiDriver_Adlib::loadResource(Resource *res) { + for (int i = 0; i < 48; i++) + loadInstrument(res->data + (28 * i)); + + if (res->size == 2690) { + for (int i = 48; i < 96; i++) + loadInstrument(res->data + 2 + (28 * i)); + } else if (res->size == 5382) { + for (int i = 48; i < 190; i++) + loadInstrument(res->data + (28 * i)); + _rhythmKeyMap = new byte[kRhythmKeys]; + memcpy(_rhythmKeyMap, res->data + 5320, kRhythmKeys); + } +} + int MidiPlayer_Adlib::open(ResourceManager *resmgr) { assert(resmgr != NULL); @@ -612,16 +640,7 @@ int MidiPlayer_Adlib::open(ResourceManager *resmgr) { return -1; } - for (int i = 0; i < 48; i++) - _driver->sysEx(res->data + (28 * i), 28); - - if (res->size == 2690) { - for (int i = 48; i < 96; i++) - _driver->sysEx(res->data + 2 + (28 * i), 28); - } else if (res->size == 5382) { - for (int i = 48; i < 190; i++) - _driver->sysEx(res->data + (28 * i), 28); - } + static_cast<MidiDriver_Adlib *>(_driver)->loadResource(res); return static_cast<MidiDriver_Adlib *>(_driver)->open(resmgr->_sciVersion == SCI_VERSION_0); } diff --git a/engines/sci/sfx/softseq/adlib.h b/engines/sci/sfx/softseq/adlib.h index 3195920508..13cf1e2d95 100644 --- a/engines/sci/sfx/softseq/adlib.h +++ b/engines/sci/sfx/softseq/adlib.h @@ -31,10 +31,11 @@ namespace Sci { class MidiDriver_Adlib : public MidiDriver_Emulated { public: enum { - kVoices = 9 + kVoices = 9, + kRhythmKeys = 62 }; - MidiDriver_Adlib(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15) { } + MidiDriver_Adlib(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15), _rhythmKeyMap(0) { } ~MidiDriver_Adlib() { } // MidiDriver @@ -53,6 +54,7 @@ public: void setVolume(byte volume); void playSwitch(bool play); + void loadResource(Resource *res); private: enum ChannelID { @@ -102,7 +104,7 @@ private: struct AdlibVoice { int8 channel; // MIDI channel that this voice is assigned to or -1 int8 note; // Currently playing MIDI note or -1 - int8 patch; // Currently playing patch or -1 + int patch; // Currently playing patch or -1 uint8 velocity; // Note velocity bool isSustained; // Flag indicating a note that is being sustained by the hold pedal uint16 age; // Age of the current note @@ -117,10 +119,10 @@ private: int _masterVolume; Channel _channels[MIDI_CHANNELS]; AdlibVoice _voices[kVoices]; + byte *_rhythmKeyMap; Common::Array<AdlibPatch> _patches; - void sysEx(const byte *msg, uint16 length); - AdlibPatch *loadPatch(byte *data); + void loadInstrument(const byte *ins); void voiceOn(int voice, int note, int velocity); void voiceOff(int voice); void setPatch(int voice, int patch); |