aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWalter van Niftrik2009-05-24 22:32:21 +0000
committerWalter van Niftrik2009-05-24 22:32:21 +0000
commit8adc9480011757f3c90a718537b0ccf99f70e210 (patch)
tree7a464c3f84ad4d59f5423d2406bff8885c6bf5c6
parenteba025f48f99b1538ebbf71ca5b815e76083b78f (diff)
downloadscummvm-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.cpp8
-rw-r--r--engines/sci/sfx/softseq/adlib.cpp67
-rw-r--r--engines/sci/sfx/softseq/adlib.h12
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);