[Scummvm-cvs-logs] SF.net SVN: scummvm:[49905] scummvm/trunk

m_kiewitz at users.sourceforge.net m_kiewitz at users.sourceforge.net
Wed Jun 16 23:02:58 CEST 2010


Revision: 49905
          http://scummvm.svn.sourceforge.net/scummvm/?rev=49905&view=rev
Author:   m_kiewitz
Date:     2010-06-16 21:02:58 +0000 (Wed, 16 Jun 2010)

Log Message:
-----------
SCI: implement channel remapping for SCI1

Modified Paths:
--------------
    scummvm/trunk/engines/sci/console.cpp
    scummvm/trunk/engines/sci/resource.h
    scummvm/trunk/engines/sci/resource_audio.cpp
    scummvm/trunk/engines/sci/sound/midiparser_sci.cpp
    scummvm/trunk/engines/sci/sound/midiparser_sci.h
    scummvm/trunk/engines/sci/sound/music.cpp
    scummvm/trunk/engines/sci/sound/music.h
    scummvm/trunk/sound/midiparser.cpp
    scummvm/trunk/sound/midiparser.h

Modified: scummvm/trunk/engines/sci/console.cpp
===================================================================
--- scummvm/trunk/engines/sci/console.cpp	2010-06-16 13:10:59 UTC (rev 49904)
+++ scummvm/trunk/engines/sci/console.cpp	2010-06-16 21:02:58 UTC (rev 49905)
@@ -859,7 +859,8 @@
 
 	SciVersion doSoundVersion = _engine->_features->detectDoSoundType();
 	MidiPlayer *player = MidiPlayer_Midi_create(doSoundVersion);
-	MidiParser_SCI *parser = new MidiParser_SCI(doSoundVersion);
+	MidiParser_SCI *parser; // = new MidiParser_SCI(doSoundVersion);
+	// FIXME: add SciMusic object
 	parser->setMidiDriver(player);
 	
 	Common::List<ResourceId> *resources = _engine->getResMan()->listResources(kResourceTypeSound);

Modified: scummvm/trunk/engines/sci/resource.h
===================================================================
--- scummvm/trunk/engines/sci/resource.h	2010-06-16 13:10:59 UTC (rev 49904)
+++ scummvm/trunk/engines/sci/resource.h	2010-06-16 21:02:58 UTC (rev 49905)
@@ -513,7 +513,6 @@
 	Track *getDigitalTrack();
 	int getChannelFilterMask(int hardwareMask, bool wantsRhythm);
 	byte getInitialVoiceCount(byte channel);
-	bool isChannelUsed(byte channel) const { return _channelsUsed & (1 << channel); }
 
 private:
 	SciVersion _soundVersion;
@@ -521,9 +520,6 @@
 	Track *_tracks;
 	Resource *_innerResource;
 	ResourceManager *_resMan;
-	uint16 _channelsUsed;
-
-	void setChannelUsed(byte channel) { _channelsUsed |= (1 << channel); }
 };
 
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/resource_audio.cpp
===================================================================
--- scummvm/trunk/engines/sci/resource_audio.cpp	2010-06-16 13:10:59 UTC (rev 49904)
+++ scummvm/trunk/engines/sci/resource_audio.cpp	2010-06-16 21:02:58 UTC (rev 49905)
@@ -461,8 +461,6 @@
 	byte *dataEnd;
 	Channel *channel, *sampleChannel;
 
-	_channelsUsed = 0;
-
 	switch (_soundVersion) {
 	case SCI_VERSION_0_EARLY:
 	case SCI_VERSION_0_LATE:
@@ -552,7 +550,6 @@
 					channel->data = resource->data + READ_LE_UINT16(data + 2) + 2;
 					channel->size = READ_LE_UINT16(data + 4) - 2; // Not counting channel header
 					channel->number = *(channel->data - 2);
-					setChannelUsed(channel->number);
 					channel->poly = *(channel->data - 1);
 					channel->time = channel->prev = 0;
 					if (channel->number == 0xFE) { // Digital channel

Modified: scummvm/trunk/engines/sci/sound/midiparser_sci.cpp
===================================================================
--- scummvm/trunk/engines/sci/sound/midiparser_sci.cpp	2010-06-16 13:10:59 UTC (rev 49904)
+++ scummvm/trunk/engines/sci/sound/midiparser_sci.cpp	2010-06-16 21:02:58 UTC (rev 49905)
@@ -43,9 +43,10 @@
 
 //  MidiParser_SCI
 //
-MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion) :
+MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion, SciMusic *music) :
 	MidiParser() {
 	_soundVersion = soundVersion;
+	_music = music;
 	_mixedData = NULL;
 	// mididata contains delta in 1/60th second
 	// values of ppqn and tempo are found experimentally and may be wrong
@@ -59,10 +60,6 @@
 	_dataincAdd = false;
 	_dataincToAdd = 0;
 	_resetOnPause = false;
-	_channelsUsed = 0;
-
-	for (int i = 0; i < 16; i++)
-		_channelRemap[i] = i;
 }
 
 MidiParser_SCI::~MidiParser_SCI() {
@@ -78,6 +75,13 @@
 	if (_pSnd)
 		setVolume(psnd->volume);
 
+	for (int i = 0; i < 15; i++) {
+		_channelUsed[i] = false;
+		_channelRemap[i] = -1;
+	}
+	_channelRemap[9] = 9; // never map channel 9, because that's used for percussion
+	_channelRemap[15] = 15; // never map channel 15, because thats used by sierra internally
+
 	if (channelFilterMask) {
 		// SCI0 only has 1 data stream, but we need to filter out channels depending on music hardware selection
 		midiFilterChannels(channelFilterMask);
@@ -128,21 +132,24 @@
 	// Center the pitch wheels and hold pedal in preparation for the next piece of music
 	if (_driver && _pSnd) {
 		for (int i = 0; i < 16; ++i) {
-			if (isChannelUsed(i)) {
-				_driver->send(0xE0 | i, 0, 0x40);	// Reset pitch wheel
-				_driver->send(0xB0 | i, 0x40, 0);	// Reset hold pedal
+			int16 realChannel = _channelRemap[i];
+			if (realChannel != -1) {
+				_driver->send(0xE0 | realChannel, 0, 0x40);	// Reset pitch wheel
+				_driver->send(0xB0 | realChannel, 0x40, 0);	// Reset hold pedal
 			}
 		}
 	}
+}
 
-	for (int i = 0; i < 16; i++)
-		_channelRemap[i] = i;
+void MidiParser_SCI::sendToDriver(uint32 b) {
+	// Channel remapping
+	int16 realChannel = _channelRemap[b & 0xf];
+	assert(realChannel != -1);
+	b = (b & 0xFFFFFFF0) | realChannel;
+	_driver->send(b);
 }
 
 void MidiParser_SCI::parseNextEvent(EventInfo &info) {
-	// Monitor which channels are used by this song
-	setChannelUsed(info.channel());
-
 	// Set signal AFTER waiting for delta, otherwise we would set signal too soon resulting in all sorts of bugs
 	if (_dataincAdd) {
 		_dataincAdd = false;
@@ -334,8 +341,9 @@
 	// Turn off all active notes
 	for (i = 0; i < 128; ++i) {
 		for (j = 0; j < 16; ++j) {
-			if ((_active_notes[i] & (1 << j)) && isChannelUsed(j)){
-				_driver->send(0x80 | j, i, 0);
+			int16 realChannel = _channelRemap[j];
+			if ((_active_notes[i] & (1 << j)) && realChannel != -1){
+				_driver->send(0x80 | realChannel, i, 0);
 			}
 		}
 	}
@@ -353,8 +361,9 @@
 	// support this...).
 
 	for (i = 0; i < 16; ++i) {
-		if (isChannelUsed(i))
-			_driver->send(0xB0 | i, 0x7b, 0); // All notes off
+		int16 realChannel = _channelRemap[i];
+		if (realChannel != -1)
+			_driver->send(0xB0 | realChannel, 0x7b, 0); // All notes off
 	}
 
 	memset(_active_notes, 0, sizeof(_active_notes));
@@ -436,19 +445,23 @@
 		default: // MIDI command
 			if (command & 0x80) {
 				par1 = *channel->data++;
-
-				// TODO: Fix remapping
-
-#if 0
-				// Remap channel. Keep the upper 4 bits (command code) and change
-				// the lower 4 bits (channel)
-				byte remappedChannel = _channelRemap[par1 & 0xF];
-				par1 = (par1 & 0xF0) | (remappedChannel & 0xF);
-#endif
 			} else {// running status
 				par1 = command;
 				command = channel->prev;
 			}
+
+			// remember which channel got used for channel remapping
+			byte midiChannel = command & 0xF;
+			_channelUsed[midiChannel] = true;
+//			int16 realChannel = _channelRemap[midiChannel];
+//			if (realChannel == -1) {
+//				// We don't own this channel yet, so ask SciMusic to get it (or a remapped one)
+//				realChannel = _music->tryToOwnChannel(_pSnd, midiChannel);
+//				_channelRemap[midiChannel] = realChannel;
+//			}
+//			// Map new channel
+//			command = realChannel | (command & 0xF0);
+
 			if (command != global_prev)
 				*outData++ = command; // out command
 			*outData++ = par1;// pout par1
@@ -577,6 +590,17 @@
 	return _mixedData;
 }
 
+// This will get called right before actual playing and will try to own the used channels
+void MidiParser_SCI::tryToOwnChannels() {
+	for (int curChannel = 0; curChannel < 15; curChannel++) {
+		if (_channelUsed[curChannel]) {
+			if (_channelRemap[curChannel] == -1) {
+				_channelRemap[curChannel] = _music->tryToOwnChannel(_pSnd, curChannel);
+			}
+		}
+	}
+}
+
 void MidiParser_SCI::setVolume(byte volume) {
 	// FIXME: This receives values > 127... throw a warning for now and clip the variable
 	if (volume > MUSIC_VOLUME_MAX) {

Modified: scummvm/trunk/engines/sci/sound/midiparser_sci.h
===================================================================
--- scummvm/trunk/engines/sci/sound/midiparser_sci.h	2010-06-16 13:10:59 UTC (rev 49904)
+++ scummvm/trunk/engines/sci/sound/midiparser_sci.h	2010-06-16 21:02:58 UTC (rev 49905)
@@ -53,7 +53,7 @@
  */
 class MidiParser_SCI : public MidiParser {
 public:
-	MidiParser_SCI(SciVersion soundVersion);
+	MidiParser_SCI(SciVersion soundVersion, SciMusic *music);
 	~MidiParser_SCI();
 	bool loadMusic(SoundResource::Track *track, MusicEntry *psnd, int channelFilterMask, SciVersion soundVersion);
 	bool loadMusic(byte *, uint32) {
@@ -73,25 +73,19 @@
 
 	void allNotesOff();
 
-	void remapChannel(byte channel, byte newChannel) {
-		assert(channel < 0xF);		// don't touch special SCI channel 15
-		assert(newChannel < 0xF);	// don't touch special SCI channel 15
-		_channelRemap[channel] = newChannel;
-	}
-
-	void clearUsedChannels() { _channelsUsed = 0; }
-
 	const byte *getMixedData() const { return _mixedData; }
 
-protected:
-	bool isChannelUsed(byte channel) const { return _channelsUsed & (1 << channel); }
-	void setChannelUsed(byte channel) { _channelsUsed |= (1 << channel); }
+	void tryToOwnChannels();
 
+protected:
+	void sendToDriver(uint32 b);
 	void parseNextEvent(EventInfo &info);
 	byte *midiMixChannels();
 	byte *midiFilterChannels(int channelMask);
 	byte midiGetNextChannel(long ticker);
 
+	SciMusic *_music;
+
 	SciVersion _soundVersion;
 	byte *_mixedData;
 	SoundResource::Track *_track;
@@ -105,11 +99,8 @@
 	int16 _dataincToAdd;
 	bool _resetOnPause;
 
-	// A 16-bit mask, containing the channels used
-	// by the currently parsed song
-	uint16 _channelsUsed;
-
-	byte _channelRemap[16];
+	bool _channelUsed[16];
+	int16 _channelRemap[16];
 };
 
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/sound/music.cpp
===================================================================
--- scummvm/trunk/engines/sci/sound/music.cpp	2010-06-16 13:10:59 UTC (rev 49904)
+++ scummvm/trunk/engines/sci/sound/music.cpp	2010-06-16 21:02:58 UTC (rev 49905)
@@ -43,6 +43,9 @@
 	// Reserve some space in the playlist, to avoid expensive insertion
 	// operations
 	_playList.reserve(10);
+
+	for (int i = 0; i < 16; i++)
+		_usedChannel[i] = 0;
 }
 
 SciMusic::~SciMusic() {
@@ -174,20 +177,6 @@
 	Common::sort(_playList.begin(), _playList.end(), musicEntryCompare);
 }
 
-void SciMusic::findUsedChannels() {
-	// Reset list
-	for (int k = 0; k < 16; k++)
-		_usedChannels[k] = false;
-
-	const MusicList::const_iterator end = _playList.end();
-	for (MusicList::const_iterator i = _playList.begin(); i != end; ++i) {
-		for (int channel = 0; channel < 16; channel++) {
-			if ((*i)->soundRes && (*i)->soundRes->isChannelUsed(channel))
-				_usedChannels[channel] = true;
-		}
-	}
-}
-
 void SciMusic::soundInitSnd(MusicEntry *pSnd) {
 	int channelFilterMask = 0;
 	SoundResource::Track *track = pSnd->soundRes->getTrackByType(_pMidiDrv->getPlayId());
@@ -224,34 +213,13 @@
 			_mutex.lock();
 			pSnd->soundType = Audio::Mixer::kMusicSoundType;
 			if (pSnd->pMidiParser == NULL) {
-				pSnd->pMidiParser = new MidiParser_SCI(_soundVersion);
+				pSnd->pMidiParser = new MidiParser_SCI(_soundVersion, this);
 				pSnd->pMidiParser->setMidiDriver(_pMidiDrv);
 				pSnd->pMidiParser->setTimerRate(_dwTempo);
 			}
 
 			pSnd->pauseCounter = 0;
 
-			// TODO: Fix channel remapping. This doesn't quite work... (e.g. no difference in LSL1VGA)
-#if 0
-			// Remap channels
-			findUsedChannels();
-
-			pSnd->pMidiParser->clearUsedChannels();
-
-			for (int i = 0; i < 16; i++) {
-				if (_usedChannels[i] && pSnd->soundRes->isChannelUsed(i)) {
-					int16 newChannel = getNextUnusedChannel();
-					if (newChannel >= 0) {
-						_usedChannels[newChannel] = true;
-						debug("Remapping channel %d to %d\n", i, newChannel);
-						pSnd->pMidiParser->remapChannel(i, newChannel);
-					} else {
-						warning("Attempt to remap channel %d, but no unused channels exist", i);
-					}
-				}
-			}
-#endif
-
 			// Find out what channels to filter for SCI0
 			channelFilterMask = pSnd->soundRes->getChannelFilterMask(_pMidiDrv->getPlayId(), _pMidiDrv->hasRhythmChannel());
 			pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion);
@@ -263,6 +231,24 @@
 	}
 }
 
+// This one checks, if requested channel is available -> in that case give caller that channel
+//  Otherwise look for an unused one
+int16 SciMusic::tryToOwnChannel(MusicEntry *caller, int16 bestChannel) {
+	if (!_usedChannel[bestChannel]) {
+		// currently unused, so give it to caller directly
+		_usedChannel[bestChannel] = caller;
+		return bestChannel;
+	}
+	// otherwise look for unused channel
+	for (int channelNr = 0; channelNr < 15; channelNr++) {
+		if (!_usedChannel[channelNr]) {
+			_usedChannel[channelNr] = caller;
+			return channelNr;
+		}
+	}
+	error("no free channels");
+}
+
 void SciMusic::onTimer() {
 	const MusicList::iterator end = _playList.end();
 	for (MusicList::iterator i = _playList.begin(); i != end; ++i)
@@ -324,6 +310,7 @@
 			                         DisposeAfterUse::NO);
 		}
 	} else {
+		pSnd->pMidiParser->tryToOwnChannels();
 		_mutex.lock();
 		if (pSnd->pMidiParser) {
 			pSnd->pMidiParser->setVolume(pSnd->volume);
@@ -388,6 +375,11 @@
 
 	_mutex.lock();
 	uint sz = _playList.size(), i;
+	// Remove used channels
+	for (i = 0; i < 15; i++) {
+		if (_usedChannel[i] == pSnd)
+			_usedChannel[i] = 0;
+	}
 	// Remove sound from playlist
 	for (i = 0; i < sz; i++) {
 		if (_playList[i] == pSnd) {

Modified: scummvm/trunk/engines/sci/sound/music.h
===================================================================
--- scummvm/trunk/engines/sci/sound/music.h	2010-06-16 13:10:59 UTC (rev 49904)
+++ scummvm/trunk/engines/sci/sound/music.h	2010-06-16 21:02:58 UTC (rev 49905)
@@ -196,6 +196,8 @@
 	// where a deadlock can occur
 	Common::Mutex _mutex;
 
+	int16 tryToOwnChannel(MusicEntry *caller, int16 bestChannel);
+
 protected:
 	void sortPlayList();
 
@@ -210,20 +212,11 @@
 	bool _bMultiMidi;
 private:
 	static void miditimerCallback(void *p);
-	void findUsedChannels();
-	int16 getNextUnusedChannel() const {
-		for (int i = 0; i < 16; i++) {
-			if (!_usedChannels[i])
-				return i;
-		}
 
-		return -1;
-	}
-
 	MusicList _playList;
 	bool _soundOn;
 	byte _masterVolume;
-	bool _usedChannels[16];
+	MusicEntry *_usedChannel[16];
 };
 
 } // End of namespace Sci

Modified: scummvm/trunk/sound/midiparser.cpp
===================================================================
--- scummvm/trunk/sound/midiparser.cpp	2010-06-16 13:10:59 UTC (rev 49904)
+++ scummvm/trunk/sound/midiparser.cpp	2010-06-16 21:02:58 UTC (rev 49905)
@@ -67,6 +67,10 @@
 	}
 }
 
+void MidiParser::sendToDriver(uint32 b) {
+	_driver->send(b);
+}
+
 void MidiParser::setTempo(uint32 tempo) {
 	_tempo = tempo;
 	if (_ppqn)
@@ -127,7 +131,7 @@
 			best = ptr;
 			if (ptr->time_left) {
 				if (recycle)
-					_driver->send(0x80 | channel, note, 0);
+					sendToDriver(0x80 | channel, note, 0);
 				--_hanging_notes_count;
 			}
 			break;
@@ -172,7 +176,7 @@
 		for (i = ARRAYSIZE(_hanging_notes); i; --i, ++ptr) {
 			if (ptr->time_left) {
 				if (ptr->time_left <= _timer_rate) {
-					_driver->send(0x80 | ptr->channel, ptr->note, 0);
+					sendToDriver(0x80 | ptr->channel, ptr->note, 0);
 					ptr->time_left = 0;
 					--_hanging_notes_count;
 				} else {
@@ -232,7 +236,7 @@
 				else
 					activeNote(info.channel(), info.basic.param1, true);
 			}
-			_driver->send(info.event, info.basic.param1, info.basic.param2);
+			sendToDriver(info.event, info.basic.param1, info.basic.param2);
 		}
 
 
@@ -258,7 +262,7 @@
 	for (i = 0; i < 128; ++i) {
 		for (j = 0; j < 16; ++j) {
 			if (_active_notes[i] & (1 << j)) {
-				_driver->send(0x80 | j, i, 0);
+				sendToDriver(0x80 | j, i, 0);
 			}
 		}
 	}
@@ -266,7 +270,7 @@
 	// Turn off all hanging notes
 	for (i = 0; i < ARRAYSIZE(_hanging_notes); i++) {
 		if (_hanging_notes[i].time_left) {
-			_driver->send(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0);
+			sendToDriver(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0);
 			_hanging_notes[i].time_left = 0;
 		}
 	}
@@ -276,7 +280,7 @@
 	// support this...).
 
 	for (i = 0; i < 16; ++i) {
-		_driver->send(0xB0 | i, 0x7b, 0); // All notes off
+		sendToDriver(0xB0 | i, 0x7b, 0); // All notes off
 	}
 
 	memset(_active_notes, 0, sizeof(_active_notes));
@@ -348,7 +352,7 @@
 				for (j = 0; j < 16; ++j) {
 					if (temp_active[i] & (1 << j)) {
 						activeNote(j, i, false);
-						_driver->send(0x80 | j, i, 0);
+						sendToDriver(0x80 | j, i, 0);
 					}
 				}
 			}
@@ -399,7 +403,7 @@
 					else
 						_driver->sysEx(info.ext.data, (uint16)info.length);
 				} else
-					_driver->send(info.event, info.basic.param1, info.basic.param2);
+					sendToDriver(info.event, info.basic.param1, info.basic.param2);
 			}
 
 			parseNextEvent(_next_event);
@@ -441,7 +445,7 @@
 
 		if (_driver) {
 			for (int i = 0; i < 16; ++i) {
-				_driver->send(0xE0 | i, 0, 0x40);
+				sendToDriver(0xE0 | i, 0, 0x40);
 			}
 		}
 	}

Modified: scummvm/trunk/sound/midiparser.h
===================================================================
--- scummvm/trunk/sound/midiparser.h	2010-06-16 13:10:59 UTC (rev 49904)
+++ scummvm/trunk/sound/midiparser.h	2010-06-16 21:02:58 UTC (rev 49905)
@@ -374,6 +374,11 @@
 	void setTempo(uint32 tempo);
 	void onTimer();
 
+	virtual void sendToDriver(uint32 b);
+	void sendToDriver(byte status, byte firstOp, byte secondOp) {
+		sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
+	}
+
 	bool isPlaying() const { return (_position._play_pos != 0); }
 	void stopPlaying();
 


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