[Scummvm-cvs-logs] SF.net SVN: scummvm:[40874] scummvm/trunk/engines/sci/sfx

waltervn at users.sourceforge.net waltervn at users.sourceforge.net
Mon May 25 00:32:21 CEST 2009


Revision: 40874
          http://scummvm.svn.sourceforge.net/scummvm/?rev=40874&view=rev
Author:   waltervn
Date:     2009-05-24 22:32:21 +0000 (Sun, 24 May 2009)

Log Message:
-----------
SCI: Adlib: added support for rhythm channel

Modified Paths:
--------------
    scummvm/trunk/engines/sci/sfx/iterator.cpp
    scummvm/trunk/engines/sci/sfx/softseq/adlib.cpp
    scummvm/trunk/engines/sci/sfx/softseq/adlib.h

Modified: scummvm/trunk/engines/sci/sfx/iterator.cpp
===================================================================
--- scummvm/trunk/engines/sci/sfx/iterator.cpp	2009-05-24 22:10:12 UTC (rev 40873)
+++ scummvm/trunk/engines/sci/sfx/iterator.cpp	2009-05-24 22:32:21 UTC (rev 40874)
@@ -131,12 +131,18 @@
 	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? */
 		}
 	}

Modified: scummvm/trunk/engines/sci/sfx/softseq/adlib.cpp
===================================================================
--- scummvm/trunk/engines/sci/sfx/softseq/adlib.cpp	2009-05-24 22:10:12 UTC (rev 40873)
+++ scummvm/trunk/engines/sci/sfx/softseq/adlib.cpp	2009-05-24 22:32:21 UTC (rev 40874)
@@ -111,6 +111,9 @@
 	_mixer->stopHandle(_mixerSoundHandle);
 
 	delete _opl;
+
+	if (_rhythmKeyMap)
+		delete[] _rhythmKeyMap;
 }
 
 void MidiDriver_Adlib::setVolume(byte volume) {
@@ -124,10 +127,6 @@
 	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::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 @@
 		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::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,10 +467,15 @@
 }
 
 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;
 
 	delta = 0;
@@ -557,6 +565,11 @@
 }
 
 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 @@
 	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,17 +640,8 @@
 		return -1;
 	}
 
-	for (int i = 0; i < 48; i++)
-		_driver->sysEx(res->data + (28 * i), 28);
+	static_cast<MidiDriver_Adlib *>(_driver)->loadResource(res);
 
-	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);
-	}
-
 	return static_cast<MidiDriver_Adlib *>(_driver)->open(resmgr->_sciVersion == SCI_VERSION_0);
 }
 

Modified: scummvm/trunk/engines/sci/sfx/softseq/adlib.h
===================================================================
--- scummvm/trunk/engines/sci/sfx/softseq/adlib.h	2009-05-24 22:10:12 UTC (rev 40873)
+++ scummvm/trunk/engines/sci/sfx/softseq/adlib.h	2009-05-24 22:32:21 UTC (rev 40874)
@@ -31,10 +31,11 @@
 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 @@
 
 	void setVolume(byte volume);
 	void playSwitch(bool play);
+	void loadResource(Resource *res);
 
 private:
 	enum ChannelID {
@@ -102,7 +104,7 @@
 	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 @@
 	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);


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list