From f63d00d4c6ab7a037aa1d7103c6de7e40d6e803e Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 4 Jun 2014 18:51:15 +0200 Subject: SCUMM: Slightly refactor music playback in AD player. --- engines/scumm/players/player_ad.cpp | 207 ++++++++++++++++++++---------------- engines/scumm/players/player_ad.h | 2 + 2 files changed, 116 insertions(+), 93 deletions(-) diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp index 5abeaf2ca6..f7f5bb3e1c 100644 --- a/engines/scumm/players/player_ad.cpp +++ b/engines/scumm/players/player_ad.cpp @@ -463,116 +463,137 @@ void Player_AD::updateMusic() { } while (true) { - uint command = _musicData[_curOffset++]; - if (command == 0xFF) { - // META EVENT - // Get the command number. - command = _musicData[_curOffset++]; - if (command == 47) { - // End of track - if (_loopFlag) { - // In case the track is looping jump to the start. - _curOffset = _musicLoopStart; - _nextEventTimer = 0; - continue; - } else { - // Otherwise completely stop playback. - stopMusic(); - } + if (parseCommand()) { + // We received an EOT command. In case there's no music playing + // we know there was no looping enabled. Thus, we stop further + // handling. Otherwise we will just continue parsing. It is + // important to note that we need to parse a command directly + // at the new position, i.e. there is no time value we need to + // parse. + if (_soundPlaying == -1) { return; - } else if (command == 88) { - // This is proposedly a debug information insertion. The CMS - // player code handles this differently, but is still using - // the same resources... - _curOffset += 5; - } else if (command == 81) { - // Change tempo. This is used exclusively in Loom. - const uint timing = _musicData[_curOffset + 2] | (_musicData[_curOffset + 1] << 8); - _musicTicks = 0x73000 / timing; - command = _musicData[_curOffset++]; - _curOffset += command; } else { - // In case an unknown meta event occurs just skip over the - // data by using the length supplied. - command = _musicData[_curOffset++]; - _curOffset += command; + continue; } - } else { - if (command >= 0x90) { - // NOTE ON - // Extract the channel number and save it in command. - command -= 0x90; + } - const uint instrOffset = _instrumentOffset[command]; - if (instrOffset) { - if (_musicData[instrOffset + 13] != 0) { - setupRhythm(_musicData[instrOffset + 13], instrOffset); - } else { - // Priority 256 makes sure we always prefer music - // channels over SFX channels. - int channel = allocateHWChannel(256); - if (channel != -1) { - setupChannel(channel, _musicData + instrOffset); - _voiceChannels[channel].lastEvent = command + 0x90; - _voiceChannels[channel].frequency = _musicData[_curOffset]; - setupFrequency(channel, _musicData[_curOffset]); - } - } - } + // In case there is a delay till the next event stop handling. + if (_musicData[_curOffset] != 0) { + break; + } + ++_curOffset; + } + + _nextEventTimer = parseVLQ(); + _nextEventTimer >>= (_vm->_game.id == GID_LOOM) ? 2 : 1; + if (!_nextEventTimer) { + _nextEventTimer = 1; + } +} + +bool Player_AD::parseCommand() { + uint command = _musicData[_curOffset++]; + if (command == 0xFF) { + // META EVENT + // Get the command number. + command = _musicData[_curOffset++]; + if (command == 47) { + // End of track + if (_loopFlag) { + // In case the track is looping jump to the start. + _curOffset = _musicLoopStart; + _nextEventTimer = 0; } else { - // NOTE OFF - const uint note = _musicData[_curOffset]; - command += 0x10; - - // Find the output channel which plays the note. - uint channel = 0xFF; - for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) { - if (_voiceChannels[i].frequency == note && _voiceChannels[i].lastEvent == command) { - channel = i; - break; + // Otherwise completely stop playback. + stopMusic(); + } + return true; + } else if (command == 88) { + // This is proposedly a debug information insertion. The CMS + // player code handles this differently, but is still using + // the same resources... + _curOffset += 5; + } else if (command == 81) { + // Change tempo. This is used exclusively in Loom. + const uint timing = _musicData[_curOffset + 2] | (_musicData[_curOffset + 1] << 8); + _musicTicks = 0x73000 / timing; + command = _musicData[_curOffset++]; + _curOffset += command; + } else { + // In case an unknown meta event occurs just skip over the + // data by using the length supplied. + command = _musicData[_curOffset++]; + _curOffset += command; + } + } else { + if (command >= 0x90) { + // NOTE ON + // Extract the channel number and save it in command. + command -= 0x90; + + const uint instrOffset = _instrumentOffset[command]; + if (instrOffset) { + if (_musicData[instrOffset + 13] != 0) { + setupRhythm(_musicData[instrOffset + 13], instrOffset); + } else { + // Priority 256 makes sure we always prefer music + // channels over SFX channels. + int channel = allocateHWChannel(256); + if (channel != -1) { + setupChannel(channel, _musicData + instrOffset); + _voiceChannels[channel].lastEvent = command + 0x90; + _voiceChannels[channel].frequency = _musicData[_curOffset]; + setupFrequency(channel, _musicData[_curOffset]); } } + } + } else { + // NOTE OFF + const uint note = _musicData[_curOffset]; + command += 0x10; + + // Find the output channel which plays the note. + uint channel = 0xFF; + for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) { + if (_voiceChannels[i].frequency == note && _voiceChannels[i].lastEvent == command) { + channel = i; + break; + } + } - if (channel != 0xFF) { - // In case a output channel playing the note was found, - // stop it. - noteOff(channel); - } else { - // In case there is no such note this will disable the - // rhythm instrument played on the channel. - command -= 0x90; - const uint instrOffset = _instrumentOffset[command]; - if (instrOffset && _musicData[instrOffset + 13] != 0) { - const uint rhythmInstr = _musicData[instrOffset + 13]; - if (rhythmInstr < 6) { - _mdvdrState &= _mdvdrTable[rhythmInstr] ^ 0xFF; - writeReg(0xBD, _mdvdrState); - } + if (channel != 0xFF) { + // In case a output channel playing the note was found, + // stop it. + noteOff(channel); + } else { + // In case there is no such note this will disable the + // rhythm instrument played on the channel. + command -= 0x90; + const uint instrOffset = _instrumentOffset[command]; + if (instrOffset && _musicData[instrOffset + 13] != 0) { + const uint rhythmInstr = _musicData[instrOffset + 13]; + if (rhythmInstr < 6) { + _mdvdrState &= _mdvdrTable[rhythmInstr] ^ 0xFF; + writeReg(0xBD, _mdvdrState); } } } - - _curOffset += 2; } - // In case there is a delay till the next event stop handling. - if (_musicData[_curOffset] != 0) { - break; - } - ++_curOffset; + _curOffset += 2; } - _nextEventTimer = _musicData[_curOffset++]; - if (_nextEventTimer & 0x80) { - _nextEventTimer -= 0x80; - _nextEventTimer <<= 7; - _nextEventTimer |= _musicData[_curOffset++]; - } + return false; +} - _nextEventTimer >>= (_vm->_game.id == GID_LOOM) ? 2 : 1; - if (!_nextEventTimer) { - _nextEventTimer = 1; +uint Player_AD::parseVLQ() { + uint vlq = _musicData[_curOffset++]; + if (vlq & 0x80) { + vlq -= 0x80; + vlq <<= 7; + vlq |= _musicData[_curOffset++]; } + return vlq; } void Player_AD::noteOff(uint channel) { diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h index d061c1acdd..3807ebc7e0 100644 --- a/engines/scumm/players/player_ad.h +++ b/engines/scumm/players/player_ad.h @@ -111,6 +111,8 @@ private: void startMusic(); void stopMusic(); void updateMusic(); + bool parseCommand(); + uint parseVLQ(); void noteOff(uint channel); void setupFrequency(uint channel, int8 frequency); void setupRhythm(uint rhythmInstr, uint instrOffset); -- cgit v1.2.3