From 1c5722f014d1f5a34c79d8d1cb7f5ed86e0b822d Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 14 Feb 2015 15:58:47 +0100 Subject: SCI: Allow channel remapping from audio thread too --- engines/sci/sound/midiparser_sci.cpp | 12 +++++++---- engines/sci/sound/music.cpp | 42 ++++++++++++++++++++++-------------- engines/sci/sound/music.h | 7 ++++-- 3 files changed, 39 insertions(+), 22 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 7ebe47633a..25facacced 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -487,8 +487,11 @@ void MidiParser_SCI::trackState(uint32 b) { s._sustain = (op2 != 0); break; case 0x4B: // voices - if (s._voices != op2) - warning("Voice change (%d to %d) without remapping", s._voices, op2); + if (s._voices != op2) { + // CHECKME: Should we directly call remapChannels() if _mainThreadCalled? + debugC(2, kDebugLevelSound, "Dynamic voice change (%d to %d)", s._voices, op2); + _music->needsRemap(); + } s._voices = op2; _pSnd->_chan[channel]._voices = op2; // Also sync our MusicEntry break; @@ -500,8 +503,9 @@ void MidiParser_SCI::trackState(uint32 b) { bool m = op2; if (_pSnd->_chan[channel]._mute != m) { _pSnd->_chan[channel]._mute = m; - // TODO: If muting/unmuting a channel, remap channels. - warning("Mute change without immediate remapping (mainThread = %d)", _mainThreadCalled); + // CHECKME: Should we directly call remapChannels() if _mainThreadCalled? + _music->needsRemap(); + debugC(2, kDebugLevelSound, "Dynamic mute change (mainThread = %d)", _mainThreadCalled); } } break; diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index dab02c9eb7..37bf6a7b1b 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -145,6 +145,7 @@ void SciMusic::init() { _currentlyPlayingSample = NULL; _timeCounter = 0; + _needsRemap = false; } void SciMusic::miditimerCallback(void *p) { @@ -159,6 +160,11 @@ void SciMusic::onTimer() { // sending out queued commands that were "sent" via main thread sendMidiCommandsFromQueue(); + // remap channels, if requested + if (_needsRemap) + remapChannels(false); + _needsRemap = false; + for (MusicList::iterator i = _playList.begin(); i != end; ++i) (*i)->onTimer(); } @@ -920,12 +926,12 @@ int ChannelRemapping::lowestPrio() const { } -void SciMusic::remapChannels() { +void SciMusic::remapChannels(bool mainThread) { if (_soundVersion <= SCI_VERSION_0_LATE) return; - // NB: This function should only be called from the main thread, - // with _mutex locked + // NB: This function should only be called with _mutex locked + // Make sure to set the mainThread argument correctly. ChannelRemapping *map = determineChannelMap(); @@ -978,9 +984,9 @@ void SciMusic::remapChannels() { for (int j = 0; j < 16; ++j) { if (!channelMapped[j]) { - song->pMidiParser->mainThreadBegin(); + if (mainThread) song->pMidiParser->mainThreadBegin(); song->pMidiParser->remapChannel(j, -1); - song->pMidiParser->mainThreadEnd(); + if (mainThread) song->pMidiParser->mainThreadEnd(); #ifdef DEBUG_REMAP if (channelUsed[j]) debug(" Unmapping song %d, channel %d", songIndex, j); @@ -1012,9 +1018,9 @@ void SciMusic::remapChannels() { #ifdef DEBUG_REMAP debug(" Mapping (dontRemap) song %d, channel %d to device channel %d", songIndex, _channelMap[i]._channel, i); #endif - _channelMap[i]._song->pMidiParser->mainThreadBegin(); + if (mainThread) _channelMap[i]._song->pMidiParser->mainThreadBegin(); _channelMap[i]._song->pMidiParser->remapChannel(_channelMap[i]._channel, i); - _channelMap[i]._song->pMidiParser->mainThreadEnd(); + if (mainThread) _channelMap[i]._song->pMidiParser->mainThreadEnd(); } } @@ -1067,9 +1073,9 @@ void SciMusic::remapChannels() { #ifdef DEBUG_REMAP debug(" Mapping song %d, channel %d to device channel %d", songIndex, _channelMap[j]._channel, j); #endif - _channelMap[j]._song->pMidiParser->mainThreadBegin(); + if (mainThread) _channelMap[j]._song->pMidiParser->mainThreadBegin(); _channelMap[j]._song->pMidiParser->remapChannel(_channelMap[j]._channel, j); - _channelMap[j]._song->pMidiParser->mainThreadEnd(); + if (mainThread) _channelMap[j]._song->pMidiParser->mainThreadEnd(); break; } } @@ -1079,7 +1085,7 @@ void SciMusic::remapChannels() { // And finally, stop any empty channels for (int i = _driverLastChannel; i >= _driverFirstChannel; --i) { if (!_channelMap[i]._song && currentMap[i]._song) - resetDeviceChannel(i); + resetDeviceChannel(i, mainThread); } delete map; @@ -1307,14 +1313,18 @@ ChannelRemapping *SciMusic::determineChannelMap() { return map; } -void SciMusic::resetDeviceChannel(int devChannel) { - // NB: This function should only be called from the main thread - +void SciMusic::resetDeviceChannel(int devChannel, bool mainThread) { assert(devChannel >= 0 && devChannel <= 0x0F); - putMidiCommandInQueue(0x0040B0 | devChannel); // sustain off - putMidiCommandInQueue(0x007BB0 | devChannel); // notes off - putMidiCommandInQueue(0x004BB0 | devChannel); // release voices + if (mainThread) { + putMidiCommandInQueue(0x0040B0 | devChannel); // sustain off + putMidiCommandInQueue(0x007BB0 | devChannel); // notes off + putMidiCommandInQueue(0x004BB0 | devChannel); // release voices + } else { + _pMidiDrv->send(0x0040B0 | devChannel); // sustain off + _pMidiDrv->send(0x007BB0 | devChannel); // notes off + _pMidiDrv->send(0x004BB0 | devChannel); // release voices + } } diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index 8770748c3d..a610f32d89 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -228,6 +228,8 @@ public: byte getCurrentReverb(); + void needsRemap() { _needsRemap = true; } + virtual void saveLoadWithSerializer(Common::Serializer &ser); // Mutex for music code. Used to guard access to the song playlist, to the @@ -249,9 +251,9 @@ protected: bool _useDigitalSFX; // remapping: - void remapChannels(); + void remapChannels(bool mainThread = true); ChannelRemapping *determineChannelMap(); - void resetDeviceChannel(int devChannel); + void resetDeviceChannel(int devChannel, bool mainThread); private: MusicList _playList; @@ -260,6 +262,7 @@ private: MusicEntry *_usedChannel[16]; int8 _channelRemap[16]; int8 _globalReverb; + bool _needsRemap; DeviceChannelUsage _channelMap[16]; -- cgit v1.2.3