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

waltervn at users.sourceforge.net waltervn at users.sourceforge.net
Tue May 5 03:51:39 CEST 2009


Revision: 40312
          http://scummvm.svn.sourceforge.net/scummvm/?rev=40312&view=rev
Author:   waltervn
Date:     2009-05-05 01:51:39 +0000 (Tue, 05 May 2009)

Log Message:
-----------
SCI: Support for 0x4e control changes in new adlib driver, and some cleanup.

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

Modified: scummvm/trunk/engines/sci/sfx/player/player.cpp
===================================================================
--- scummvm/trunk/engines/sci/sfx/player/player.cpp	2009-05-04 19:54:53 UTC (rev 40311)
+++ scummvm/trunk/engines/sci/sfx/player/player.cpp	2009-05-05 01:51:39 UTC (rev 40312)
@@ -156,8 +156,12 @@
 	SIMSG_SEND(it, SIMSG_SET_PLAYMASK(mididrv->getPlayMask()));
 	SIMSG_SEND(it, SIMSG_SET_RHYTHM(mididrv->hasRhythmChannel()));
 
-	current_time = Audio::Timestamp(g_system->getMillis(), 1000000 / tempo);
-	wakeup_time = Audio::Timestamp(start_time, SFX_TICKS_PER_SEC);
+	if (play_it == NULL) {
+		// Resync with clock
+		current_time = Audio::Timestamp(g_system->getMillis(), 1000000 / tempo);
+		wakeup_time = Audio::Timestamp(start_time, SFX_TICKS_PER_SEC);
+	}
+
 	play_it = sfx_iterator_combine(play_it, it);
 	play_it_done = 0;
 	mutex->unlock();
@@ -171,9 +175,12 @@
 }
 
 static int player_stop(void) {
+	debug(3, "Player: Stopping song iterator %p", (void *)play_it);
 	mutex->lock();
 	delete play_it;
 	play_it = NULL;
+	for (int i = 0; i < MIDI_CHANNELS; i++)
+		static_cast<MidiDriver *>(mididrv)->send(0xb0 + i, SCI_MIDI_CHANNEL_NOTES_OFF, 0);
 	mutex->unlock();
 
 	return SFX_OK;

Modified: scummvm/trunk/engines/sci/sfx/softseq/adlib.cpp
===================================================================
--- scummvm/trunk/engines/sci/sfx/softseq/adlib.cpp	2009-05-04 19:54:53 UTC (rev 40311)
+++ scummvm/trunk/engines/sci/sfx/softseq/adlib.cpp	2009-05-05 01:51:39 UTC (rev 40312)
@@ -41,7 +41,6 @@
 
 // FIXME: We don't seem to be sending the polyphony init data, so disable this for now
 #define ADLIB_DISABLE_VOICE_MAPPING
-#define ADLIB_SCI1
 
 static const byte registerOffset[MidiDriver_Adlib::kVoices] = {
 	0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12
@@ -75,11 +74,14 @@
 	0x2ae
 };
 
-int MidiDriver_Adlib::open() {
+int MidiDriver_Adlib::open(bool isSCI0) {
 	int rate = _mixer->getOutputRate();
 
 	_stereo = STEREO;
 
+	debug(3, "ADLIB: Starting driver in %s mode", (isSCI0 ? "SCI0" : "SCI1"));
+	_isSCI0 = isSCI0;
+
 	for (int i = 0; i < (isStereo() ? 2 : 1); i++) {
 		_fmopl[i] = makeAdlibOPL(rate);
 
@@ -153,6 +155,11 @@
 			voiceMapping(channel, op2);
 #endif
 			break;
+		case 0x4e:
+			// FIXME: this flag should be set to 0 when a new song is started
+			debug(3, "ADLIB: Setting velocity control flag for channel %i to %i", channel, op2);
+			_channels[channel].enableVelocity = op2;
+			break;
 		case SCI_MIDI_CHANNEL_NOTES_OFF:
 			for (int i = 0; i < kVoices; i++)
 				if ((_voices[i].channel == channel) && (_voices[i].note != -1))
@@ -481,57 +488,66 @@
 
 	setRegister(0xA0 + voice, fre & 0xff);
 	setRegister(0xB0 + voice, (key << 5) | (oct << 2) | (fre >> 8));
-// FIXME
-#ifdef ADLIB_SCI1
-	int velocity = _channels[_voices[voice].channel].volume + 1;
-	velocity = velocity * (velocityMap1[_voices[voice].velocity] + 1) / 64;
-	velocity = velocity * (_masterVolume + 1) / 16;
 
-	if (--velocity < 0)
-		velocity = 0;
-#else
-	int velocity = _masterVolume + 3;
-	if (velocity > 15)
-		velocity = 15;
-	velocity *= 4;
-#endif
-	if (!_playSwitch)
-		velocity = 0;
-
-	setVelocity(voice, velocity);
+	setVelocity(voice);
 }
 
-void MidiDriver_Adlib::setVelocity(int voice, int velocity) {
+void MidiDriver_Adlib::setVelocity(int voice) {
 	AdlibPatch &patch = _patches[_voices[voice].patch];
 	int pan = _channels[_voices[voice].channel].pan;
-	setVelocityReg(registerOffset[voice] + 3, velocity, pan, patch.op[1]);
+	setVelocityReg(registerOffset[voice] + 3, calcVelocity(voice, 1), patch.op[1].kbScaleLevel, pan);
 
 	// In AM mode we need to set the level for both operators
 	if (_patches[_voices[voice].patch].mod.algorithm == 1)
-		setVelocityReg(registerOffset[voice], velocity, pan, patch.op[0]);
+		setVelocityReg(registerOffset[voice], calcVelocity(voice, 0), patch.op[0].kbScaleLevel, pan);
 }
 
-void MidiDriver_Adlib::setVelocityReg(int regOffset, int velocity, int pan, AdlibOperator &op) {
-// FIXME
-#ifdef ADLIB_SCI1
-	int vel = (velocityMap2[velocity] * (63 - op.totalLevel) / 63);
-#else
-	int vel = (velocity / 4 * ((63 - op.totalLevel) / 15));
-#endif
+int MidiDriver_Adlib::calcVelocity(int voice, int op) {
+	if (_isSCI0) {
+		int velocity = _masterVolume;
 
+		if ((velocity > 0) && (velocity < 13))
+			velocity += 3;
+
+		int insVelocity;
+		if (_channels[_voices[voice].channel].enableVelocity)
+			insVelocity = _voices[voice].velocity;
+		else
+			insVelocity = 63 - _patches[_voices[voice].patch].op[op].totalLevel;
+
+		// Note: Later SCI0 has a static table that is close to this formula, but not exactly the same.
+		// Early SCI0 does (velocity * (insVelocity / 15))
+		return velocity * insVelocity / 15;
+	} else {
+		AdlibOperator &oper = _patches[_voices[voice].patch].op[op];
+		int velocity = _channels[_voices[voice].channel].volume + 1;
+		velocity = velocity * (velocityMap1[_voices[voice].velocity] + 1) / 64;
+		velocity = velocity * (_masterVolume + 1) / 16;
+
+		if (--velocity < 0)
+			velocity = 0;
+
+		return velocityMap2[velocity] * (63 - oper.totalLevel) / 63;
+	}
+}
+
+void MidiDriver_Adlib::setVelocityReg(int regOffset, int velocity, int kbScaleLevel, int pan) {
+	if (!_playSwitch)
+		velocity = 0;
+
 	if (isStereo()) {
-		int velLeft = vel;
-		int velRight = vel;
+		int velLeft = velocity;
+		int velRight = velocity;
 
 		if (pan > 0x40)
 			velLeft = velLeft * (0x7f - pan) / 0x3f;
 		else if (pan < 0x40)
 			velRight = velRight * pan / 0x40;
 
-		setRegister(0x40 + regOffset, (op.kbScaleLevel << 6) | (63 - velLeft), kLeftChannel);
-		setRegister(0x40 + regOffset, (op.kbScaleLevel << 6) | (63 - velRight), kRightChannel);
+		setRegister(0x40 + regOffset, (kbScaleLevel << 6) | (63 - velLeft), kLeftChannel);
+		setRegister(0x40 + regOffset, (kbScaleLevel << 6) | (63 - velRight), kRightChannel);
 	} else {
-		setRegister(0x40 + regOffset, (op.kbScaleLevel << 6) | (63 - vel));
+		setRegister(0x40 + regOffset, (kbScaleLevel << 6) | (63 - velocity));
 	}
 }
 
@@ -575,6 +591,8 @@
 }
 
 int MidiPlayer_Adlib::open(ResourceManager *resmgr) {
+	assert(resmgr != NULL);
+
 	// Load up the patch.003 file, parse out the instruments
 	Resource *res = resmgr->findResource(kResourceTypePatch, 3, 0);
 
@@ -583,19 +601,19 @@
 		return -1;
 	}
 
-	if (res->size < 1344) {
-		error("ADLIB: Expected patch.003 of at least %d bytes, got %d", 1344, res->size);
+	if ((res->size != 1344) && (res->size != 2690)) {
+		error("ADLIB: Unsupported patch format (%i bytes)", res->size);
 		return -1;
 	}
 
 	for (int i = 0; i < 48; i++)
 		_driver->sysEx(res->data + (28 * i), 28);
 
-	if (res->size > 1344)
+	if (res->size == 2690)
 		for (int i = 48; i < 96; i++)
 			_driver->sysEx(res->data + 2 + (28 * i), 28);
 
-	return _driver->open();
+	return static_cast<MidiDriver_Adlib *>(_driver)->open(resmgr->_sciVersion == SCI_VERSION_0);
 }
 
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/sfx/softseq/adlib.h
===================================================================
--- scummvm/trunk/engines/sci/sfx/softseq/adlib.h	2009-05-04 19:54:53 UTC (rev 40311)
+++ scummvm/trunk/engines/sci/sfx/softseq/adlib.h	2009-05-05 01:51:39 UTC (rev 40312)
@@ -34,6 +34,27 @@
 		kVoices = 9
 	};
 
+	MidiDriver_Adlib(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15) { }
+	~MidiDriver_Adlib() { }
+
+	// MidiDriver
+	int open(bool isSCI0);
+	void close();
+	void send(uint32 b);
+	MidiChannel *allocateChannel() { return NULL; }
+	MidiChannel *getPercussionChannel() { return NULL; }
+
+	// AudioStream
+	bool isStereo() const { return _stereo; }
+	int getRate() const { return _mixer->getOutputRate(); }
+
+	// MidiDriver_Emulated
+	void generateSamples(int16 *buf, int len);
+
+	void setVolume(byte volume);
+	void playSwitch(bool play);
+
+private:
 	enum ChannelID {
 		kLeftChannel = 1,
 		kRightChannel = 2
@@ -44,18 +65,18 @@
 		bool vibrato;
 		bool envelopeType;
 		bool kbScaleRate;
-		byte frequencyMult;	// (0-15)
-		byte kbScaleLevel;	// (0-3)
-		byte totalLevel;	// (0-63, 0=max, 63=min)
-		byte attackRate;	// (0-15)
-		byte decayRate;		// (0-15)
-		byte sustainLevel;	// (0-15)
-		byte releaseRate;	// (0-15)
-		byte waveForm;		// (0-3)
+		byte frequencyMult;		// (0-15)
+		byte kbScaleLevel;		// (0-3)
+		byte totalLevel;		// (0-63, 0=max, 63=min)
+		byte attackRate;		// (0-15)
+		byte decayRate;			// (0-15)
+		byte sustainLevel;		// (0-15)
+		byte releaseRate;		// (0-15)
+		byte waveForm;			// (0-3)
 	};
 
 	struct AdlibModulator {
-		byte feedback;		// (0-7)
+		byte feedback;			// (0-7)
 		bool algorithm;
 	};
 
@@ -65,50 +86,32 @@
 	};
 
 	struct Channel {
-		uint8 patch;		// Patch setting
-		uint8 volume;		// Channel volume (0-63)
-		uint8 pan;			// Pan setting (0-127, 64 is center)
-		uint8 holdPedal;	// Hold pedal setting (0 to 63 is off, 127 to 64 is on)
-		uint8 extraVoices;	// The number of additional voices this channel optimally needs
-		uint16 pitchWheel;	// Pitch wheel setting (0-16383, 8192 is center)
-		uint8 lastVoice;	// Last voice used for this MIDI channel
+		uint8 patch;			// Patch setting
+		uint8 volume;			// Channel volume (0-63)
+		uint8 pan;				// Pan setting (0-127, 64 is center)
+		uint8 holdPedal;		// Hold pedal setting (0 to 63 is off, 127 to 64 is on)
+		uint8 extraVoices;		// The number of additional voices this channel optimally needs
+		uint16 pitchWheel;		// Pitch wheel setting (0-16383, 8192 is center)
+		uint8 lastVoice;		// Last voice used for this MIDI channel
+		bool enableVelocity;	// Enable velocity control (SCI0)
 
-		Channel() : patch(0), volume(63), pan(64), holdPedal(0), extraVoices(0), pitchWheel(8192), lastVoice(0) { }
+		Channel() : patch(0), volume(63), pan(64), holdPedal(0), extraVoices(0),
+					pitchWheel(8192), lastVoice(0), enableVelocity(false) { }
 	};
 
 	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
-		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
+		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
+		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
 
 		AdlibVoice() : channel(-1), note(-1), patch(-1), velocity(0), isSustained(false), age(0) { }
 	};
 
-	MidiDriver_Adlib(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15) { }
-	~MidiDriver_Adlib() { }
-
-	// MidiDriver
-	int open();
-	void close();
-	void send(uint32 b);
-	MidiChannel *allocateChannel() { return NULL; }
-	MidiChannel *getPercussionChannel() { return NULL; }
-
-	// AudioStream
-	bool isStereo() const { return _stereo; }
-	int getRate() const { return _mixer->getOutputRate(); }
-
-	// MidiDriver_Emulated
-	void generateSamples(int16 *buf, int len);
-
-	void setVolume(byte volume);
-	void playSwitch(bool play);
-
-private:
 	bool _stereo;
+	bool _isSCI0;
 	FM_OPL *_fmopl[2];
 	bool _playSwitch;
 	int _masterVolume;
@@ -122,7 +125,7 @@
 	void voiceOff(int voice);
 	void setPatch(int voice, int patch);
 	void setNote(int voice, int note, bool key);
-	void setVelocity(int voice, int velocity);
+	void setVelocity(int voice);
 	void setOperator(int oper, AdlibOperator &op);
 	void setRegister(int reg, int value, int channels = kLeftChannel | kRightChannel);
 	void renewNotes(int channel, bool key);
@@ -134,7 +137,8 @@
 	void releaseVoices(int channel, int voices);
 	void donateVoices();
 	int findVoiceBasic(int channel);
-	void setVelocityReg(int regOffset, int velocity, int pan, AdlibOperator &op);
+	void setVelocityReg(int regOffset, int velocity, int kbScaleLevel, int pan);
+	int calcVelocity(int voice, int op);
 };
 
 class MidiPlayer_Adlib : public MidiPlayer {


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