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

m_kiewitz at users.sourceforge.net m_kiewitz at users.sourceforge.net
Tue Jun 22 00:07:03 CEST 2010


Revision: 50130
          http://scummvm.svn.sourceforge.net/scummvm/?rev=50130&view=rev
Author:   m_kiewitz
Date:     2010-06-21 22:07:03 +0000 (Mon, 21 Jun 2010)

Log Message:
-----------
SCI: instead of queueing inside midiparser, we are queueing now globally in SciMusic, also some little cleanup

Modified Paths:
--------------
    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

Modified: scummvm/trunk/engines/sci/sound/midiparser_sci.cpp
===================================================================
--- scummvm/trunk/engines/sci/sound/midiparser_sci.cpp	2010-06-21 21:37:00 UTC (rev 50129)
+++ scummvm/trunk/engines/sci/sound/midiparser_sci.cpp	2010-06-21 22:07:03 UTC (rev 50130)
@@ -61,14 +61,20 @@
 	_dataincToAdd = 0;
 	_resetOnPause = false;
 	_pSnd = 0;
-
-	_manualCommandCount = 0;
 }
 
 MidiParser_SCI::~MidiParser_SCI() {
 	unloadMusic();
 }
 
+void MidiParser_SCI::mainThreadBegin() {
+	_mainThreadCalled = true;
+}
+
+void MidiParser_SCI::mainThreadEnd() {
+	_mainThreadCalled = false;
+}
+
 bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, int channelFilterMask, SciVersion soundVersion) {
 	unloadMusic();
 	_track = track;
@@ -107,7 +113,7 @@
 				byte voiceCount = 0;
 				if (_channelUsed[i]) {
 					voiceCount = _pSnd->soundRes->getInitialVoiceCount(i);
-					sendToDriverQueue(0xB0 | i, 0x4B, voiceCount);
+					sendToDriver(0xB0 | i, 0x4B, voiceCount);
 				}
 			}
 		}
@@ -115,7 +121,8 @@
 
 	// Send a velocity off signal to all channels
 	for (int i = 0; i < 15; ++i) {
-		sendToDriverQueue(0xB0 | i, 0x4E, 0);	// Reset velocity
+		if (_channelUsed[i])
+			sendToDriver(0xB0 | i, 0x4E, 0);	// Reset velocity
 	}
 }
 
@@ -145,44 +152,27 @@
 	}
 }
 
-// this is used for scripts sending direct midi commands to us. we verify in that case that the channel is actually
-//  used and actually store the command for getting really sent when being onTimer()
-void MidiParser_SCI::sendToDriverQueue(uint32 b) {
-	byte midiChannel = b & 0xf;
+// this is used for scripts sending midi commands to us. we verify in that case that the channel is actually
+//  used, so that channel remapping will work as well and then send them on
+void MidiParser_SCI::sendFromScriptToDriver(uint32 midi) {
+	byte midiChannel = midi & 0xf;
 
 	if (!_channelUsed[midiChannel]) {
 		// trying to send to an unused channel
 		//  this happens for cmdSendMidi at least in sq1vga right at the start, it's a script issue
 		return;
 	}
-
-	if (_manualCommandCount >= 200)
-		error("driver queue is full");
-	_manualCommands[_manualCommandCount] = b;
-	_manualCommandCount++;
+	sendToDriver(midi);
 }
 
-// This sends the stored commands from queue to driver (is supposed to get called only during onTimer())
-//  at least mt32 emulation doesn't like getting note-on commands from main thread (if we directly send, we would get
-//  a crash during piano scene in lsl5)
-void MidiParser_SCI::sendQueueToDriver() {
-	int curCommand = 0;
+void MidiParser_SCI::sendToDriver(uint32 midi) {
+	byte midiChannel = midi & 0xf;
 
-	while (curCommand < _manualCommandCount) {
-		sendToDriver(_manualCommands[curCommand]);
-		curCommand++;
-	}
-	_manualCommandCount = 0;
-}
-
-void MidiParser_SCI::sendToDriver(uint32 b) {
-	byte midiChannel = b & 0xf;
-
-	if ((b & 0xFFF0) == 0x4EB0) {
+	if ((midi & 0xFFF0) == 0x4EB0) {
 		// this is channel mute only for sci1
 		// it's velocity control for sci0
 		if (_soundVersion >= SCI_VERSION_1_EARLY) {
-			_channelMuted[midiChannel] = b & 0xFF0000 ? true : false;
+			_channelMuted[midiChannel] = midi & 0xFF0000 ? true : false;
 			return; // don't send this to driver at all
 		}
 	}
@@ -194,8 +184,11 @@
 	int16 realChannel = _channelRemap[midiChannel];
 	assert(realChannel != -1);
 
-	b = (b & 0xFFFFFFF0) | realChannel;
-	_driver->send(b);
+	midi = (midi & 0xFFFFFFF0) | realChannel;
+	if (_mainThreadCalled)
+		_music->putMidiCommandInQueue(midi);
+	else
+		_driver->send(midi);
 }
 
 void MidiParser_SCI::parseNextEvent(EventInfo &info) {
@@ -681,7 +674,8 @@
 		case SCI_VERSION_1_LATE:
 			// sending volume change to all used channels
 			for (int i = 0; i < 15; i++)
-				sendToDriverQueue(0xB0 + i, 7, _volume);
+				if (_channelUsed[i])
+					sendToDriver(0xB0 + i, 7, _volume);
 			break;
 
 		default:

Modified: scummvm/trunk/engines/sci/sound/midiparser_sci.h
===================================================================
--- scummvm/trunk/engines/sci/sound/midiparser_sci.h	2010-06-21 21:37:00 UTC (rev 50129)
+++ scummvm/trunk/engines/sci/sound/midiparser_sci.h	2010-06-21 22:07:03 UTC (rev 50130)
@@ -55,6 +55,10 @@
 public:
 	MidiParser_SCI(SciVersion soundVersion, SciMusic *music);
 	~MidiParser_SCI();
+
+	void mainThreadBegin();
+	void mainThreadEnd();
+
 	bool loadMusic(SoundResource::Track *track, MusicEntry *psnd, int channelFilterMask, SciVersion soundVersion);
 	bool loadMusic(byte *, uint32) {
 		return false;
@@ -77,17 +81,12 @@
 	const byte *getMixedData() const { return _mixedData; }
 
 	void tryToOwnChannels();
-	void sendToDriver(uint32 b);
+	void sendFromScriptToDriver(uint32 midi);
+	void sendToDriver(uint32 midi);
 	void sendToDriver(byte status, byte firstOp, byte secondOp) {
 		sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
 	}
-	void sendToDriverQueue(uint32 b);
-	void sendToDriverQueue(byte status, byte firstOp, byte secondOp) {
-		sendToDriverQueue(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
-	}
 
-	void sendQueueToDriver();
-
 protected:
 	void parseNextEvent(EventInfo &info);
 	byte *midiMixChannels();
@@ -96,6 +95,9 @@
 
 	SciMusic *_music;
 
+	// this is set, when main thread calls us -> we send commands to queue instead to driver
+	bool _mainThreadCalled;
+
 	SciVersion _soundVersion;
 	byte *_mixedData;
 	SoundResource::Track *_track;
@@ -112,9 +114,6 @@
 	bool _channelUsed[16];
 	int16 _channelRemap[16];
 	bool _channelMuted[16];
-
-	int _manualCommandCount;
-	uint32 _manualCommands[200];
 };
 
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/sound/music.cpp
===================================================================
--- scummvm/trunk/engines/sci/sound/music.cpp	2010-06-21 21:37:00 UTC (rev 50129)
+++ scummvm/trunk/engines/sci/sound/music.cpp	2010-06-21 22:07:03 UTC (rev 50130)
@@ -46,6 +46,8 @@
 
 	for (int i = 0; i < 16; i++)
 		_usedChannel[i] = 0;
+
+	_queuedCommandCount = 0;
 }
 
 SciMusic::~SciMusic() {
@@ -102,6 +104,49 @@
 	_driverFirstChannel = _pMidiDrv->getFirstChannel();
 }
 
+void SciMusic::miditimerCallback(void *p) {
+	SciMusic *sciMusic = (SciMusic *)p;
+
+	Common::StackLock lock(sciMusic->_mutex);
+	sciMusic->onTimer();
+}
+
+void SciMusic::onTimer() {
+	const MusicList::iterator end = _playList.end();
+	// sending out queued commands that were "sent" via main thread
+	sendMidiCommandsFromQueue();
+
+	for (MusicList::iterator i = _playList.begin(); i != end; ++i)
+		(*i)->onTimer();
+
+	// for sending out fade commands immediately
+	sendMidiCommandsFromQueue();
+}
+
+void SciMusic::putMidiCommandInQueue(byte status, byte firstOp, byte secondOp) {
+	putMidiCommandInQueue(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
+}
+
+void SciMusic::putMidiCommandInQueue(uint32 midi) {
+	if (_queuedCommandCount >= 1000)
+		error("driver queue is full");
+	_queuedCommands[_queuedCommandCount] = midi;
+	_queuedCommandCount++;
+}
+
+// This sends the stored commands from queue to driver (is supposed to get called only during onTimer())
+//  at least mt32 emulation doesn't like getting note-on commands from main thread (if we directly send, we would get
+//  a crash during piano scene in lsl5)
+void SciMusic::sendMidiCommandsFromQueue() {
+	int curCommand = 0;
+
+	while (curCommand < _queuedCommandCount) {
+		_pMidiDrv->send(_queuedCommands[curCommand]);
+		curCommand++;
+	}
+	_queuedCommandCount = 0;
+}
+
 void SciMusic::clearPlayList() {
 	Common::StackLock lock(_mutex);
 
@@ -127,14 +172,6 @@
 	}
 }
 
-
-void SciMusic::miditimerCallback(void *p) {
-	SciMusic *aud = (SciMusic *)p;
-
-	Common::StackLock lock(aud->_mutex);
-	aud->onTimer();
-}
-
 void SciMusic::soundSetSoundOn(bool soundOnFlag) {
 	Common::StackLock lock(_mutex);
 
@@ -219,8 +256,10 @@
 
 			// Find out what channels to filter for SCI0
 			channelFilterMask = pSnd->soundRes->getChannelFilterMask(_pMidiDrv->getPlayId(), _pMidiDrv->hasRhythmChannel());
+
+			pSnd->pMidiParser->mainThreadBegin();
 			pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion);
-
+			pSnd->pMidiParser->mainThreadEnd();
 			_mutex.unlock();
 		}
 	}
@@ -255,12 +294,6 @@
 	}
 }
 
-void SciMusic::onTimer() {
-	const MusicList::iterator end = _playList.end();
-	for (MusicList::iterator i = _playList.begin(); i != end; ++i)
-		(*i)->onTimer();
-}
-
 void SciMusic::soundPlay(MusicEntry *pSnd) {
 	_mutex.lock();
 
@@ -316,18 +349,21 @@
 			                         DisposeAfterUse::NO);
 		}
 	} else {
-		_mutex.lock();
 		if (pSnd->pMidiParser) {
+			_mutex.lock();
+			pSnd->pMidiParser->mainThreadBegin();
 			pSnd->pMidiParser->tryToOwnChannels();
 			pSnd->pMidiParser->setVolume(pSnd->volume);
 			if (pSnd->status == kSoundStopped) {
 				pSnd->pMidiParser->sendInitCommands();
 				pSnd->pMidiParser->jumpToTick(0);
-			} else
+			} else {
 				// Fast forward to the last position and perform associated events when loading
 				pSnd->pMidiParser->jumpToTick(pSnd->ticker, true);
+			}
+			pSnd->pMidiParser->mainThreadEnd();
+			_mutex.unlock();
 		}
-		_mutex.unlock();
 	}
 
 	pSnd->status = kSoundPlaying;
@@ -342,8 +378,10 @@
 
 	if (pSnd->pMidiParser) {
 		_mutex.lock();
+		pSnd->pMidiParser->mainThreadBegin();
 		pSnd->pMidiParser->stop();
 		freeChannels(pSnd);
+		pSnd->pMidiParser->mainThreadEnd();
 		_mutex.unlock();
 	}
 }
@@ -354,7 +392,9 @@
 		_pMixer->setChannelVolume(pSnd->hCurrentAud, volume * 2); // Mixer is 0-255, SCI is 0-127
 	} else if (pSnd->pMidiParser) {
 		_mutex.lock();
+		pSnd->pMidiParser->mainThreadBegin();
 		pSnd->pMidiParser->setVolume(volume);
+		pSnd->pMidiParser->mainThreadEnd();
 		_mutex.unlock();
 	}
 }
@@ -369,13 +409,15 @@
 void SciMusic::soundKill(MusicEntry *pSnd) {
 	pSnd->status = kSoundStopped;
 
-	_mutex.lock();
 	if (pSnd->pMidiParser) {
+		_mutex.lock();
+		pSnd->pMidiParser->mainThreadBegin();
 		pSnd->pMidiParser->unloadMusic();
+		pSnd->pMidiParser->mainThreadEnd();
 		delete pSnd->pMidiParser;
 		pSnd->pMidiParser = NULL;
+		_mutex.unlock();
 	}
-	_mutex.unlock();
 
 	if (pSnd->pStreamAud) {
 		_pMixer->stopHandle(pSnd->hCurrentAud);
@@ -409,8 +451,10 @@
 	} else {
 		if (pSnd->pMidiParser) {
 			_mutex.lock();
+			pSnd->pMidiParser->mainThreadBegin();
 			pSnd->pMidiParser->pause();
 			freeChannels(pSnd);
+			pSnd->pMidiParser->mainThreadEnd();
 			_mutex.unlock();
 		}
 	}
@@ -458,10 +502,12 @@
 
 void SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) {
 	Common::StackLock lock(_mutex);
-	if (pSnd->pMidiParser)
-		pSnd->pMidiParser->sendToDriverQueue(cmd);
-	else
+	if (!pSnd->pMidiParser)
 		error("tried to cmdSendMidi on non midi slot (%04x:%04x)", PRINT_REG(pSnd->soundObj));
+
+	pSnd->pMidiParser->mainThreadBegin();
+	pSnd->pMidiParser->sendFromScriptToDriver(cmd);
+	pSnd->pMidiParser->mainThreadEnd();
 }
 
 void SciMusic::printPlayList(Console *con) {
@@ -567,8 +613,6 @@
 
 	// Only process MIDI streams in this thread, not digital sound effects
 	if (pMidiParser) {
-		// Process manual commands first
-		pMidiParser->sendQueueToDriver();
 		pMidiParser->onTimer();
 		ticker = (uint16)pMidiParser->getTick();
 	}

Modified: scummvm/trunk/engines/sci/sound/music.h
===================================================================
--- scummvm/trunk/engines/sci/sound/music.h	2010-06-21 21:37:00 UTC (rev 50129)
+++ scummvm/trunk/engines/sci/sound/music.h	2010-06-21 22:07:03 UTC (rev 50130)
@@ -132,7 +132,15 @@
 	~SciMusic();
 
 	void init();
+
 	void onTimer();
+	void putMidiCommandInQueue(byte status, byte firstOp, byte secondOp);
+	void putMidiCommandInQueue(uint32 midi);
+private:
+	static void miditimerCallback(void *p);
+	void sendMidiCommandsFromQueue();
+
+public:
 	void clearPlayList();
 	void pauseAll(bool pause);
 	void stopAll();
@@ -209,14 +217,16 @@
 	// Mixed AdLib/MIDI mode: when enabled from the ScummVM sound options screen,
 	// and a sound has a digital track, the sound from the AdLib track is played
 	bool _bMultiMidi;
+
 private:
-	static void miditimerCallback(void *p);
-
 	MusicList _playList;
 	bool _soundOn;
 	byte _masterVolume;
 	MusicEntry *_usedChannel[16];
 
+	int _queuedCommandCount;
+	uint32 _queuedCommands[1000];
+
 	int _driverFirstChannel;
 };
 


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