From d556dcc57bf50a03d81ab7a1ef59a9e5758465bf Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Fri, 16 Jun 2017 16:32:16 -0500 Subject: SCI: Switch SCI2 games to use Audio32 Upon investigation of Sound code across SCI32 games, it was determined that there are actually (at least) 3 different revisions, not just a single SCI2.1 version. This patch only changes the parts of Sound code that are relevant to the correct use of Audio32. Fixes Trac#9736, Trac#9756, Trac#9767, Trac#9791. --- engines/sci/sound/audio32.cpp | 21 ++++++++++++++-- engines/sci/sound/midiparser_sci.cpp | 47 +++++++++--------------------------- engines/sci/sound/music.cpp | 12 ++++++--- engines/sci/sound/soundcmd.cpp | 37 +++++++++------------------- 4 files changed, 51 insertions(+), 66 deletions(-) (limited to 'engines/sci/sound') diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp index 5e75095e5a..cfbab8b055 100644 --- a/engines/sci/sound/audio32.cpp +++ b/engines/sci/sound/audio32.cpp @@ -114,7 +114,9 @@ Audio32::Audio32(ResourceManager *resMan) : _monitoredBufferSize(0), _numMonitoredSamples(0) { - if (getSciVersion() < SCI_VERSION_3) { + if (getSciVersion() < SCI_VERSION_2_1_EARLY) { + _channels.resize(10); + } else if (getSciVersion() < SCI_VERSION_3) { _channels.resize(5); } else { _channels.resize(8); @@ -311,7 +313,22 @@ int Audio32::readBuffer(Audio::st_sample_t *const buffer, const int numSamples) Audio::st_volume_t leftVolume, rightVolume; if (channel.pan == -1 || !isStereo()) { - leftVolume = rightVolume = channel.volume * Audio::Mixer::kMaxChannelVolume / kMaxVolume; + int volume = channel.volume; + if (getSciVersion() == SCI_VERSION_2) { + // NOTE: In SSCI, audio is decompressed into a temporary + // buffer, then the samples in that buffer are looped over, + // shifting each sample right 3, 2, or 1 bits to reduce the + // volume. + if (volume > 0 && volume <= 42) { + volume = 15; + } else if (volume > 42 && volume <= 84) { + volume = 31; + } else if (volume > 84 && volume < kMaxVolume) { + volume = 63; + } + } + + leftVolume = rightVolume = volume * Audio::Mixer::kMaxChannelVolume / kMaxVolume; } else { // TODO: This should match the SCI3 algorithm, // which seems to halve the volume of each diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index a25ce2887b..bdd0d1b36e 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -752,18 +752,12 @@ bool MidiParser_SCI::processEvent(const EventInfo &info, bool fireEvents) { case kUpdateCue: if (!_jumpingToTick) { int inc; - switch (_soundVersion) { - case SCI_VERSION_0_EARLY: - case SCI_VERSION_0_LATE: + if (_soundVersion <= SCI_VERSION_0_LATE) { inc = info.basic.param2; - break; - case SCI_VERSION_1_EARLY: - case SCI_VERSION_1_LATE: - case SCI_VERSION_2_1_EARLY: + } else if (_soundVersion >= SCI_VERSION_1_EARLY && _soundVersion <= SCI_VERSION_2_1_MIDDLE) { inc = 1; - break; - default: - error("unsupported _soundVersion"); + } else { + error("Unsupported _soundVersion %s", getSciVersionDesc(_soundVersion)); } _pSnd->dataInc += inc; debugC(4, kDebugLevelSound, "datainc %04x", inc); @@ -895,22 +889,14 @@ void MidiParser_SCI::allNotesOff() { void MidiParser_SCI::setMasterVolume(byte masterVolume) { assert(masterVolume <= MUSIC_MASTERVOLUME_MAX); _masterVolume = masterVolume; - switch (_soundVersion) { - case SCI_VERSION_0_EARLY: - case SCI_VERSION_0_LATE: + if (_soundVersion <= SCI_VERSION_0_LATE) { // update driver master volume setVolume(_volume); - break; - - case SCI_VERSION_1_EARLY: - case SCI_VERSION_1_LATE: - case SCI_VERSION_2_1_EARLY: + } else if (_soundVersion >= SCI_VERSION_1_EARLY && _soundVersion <= SCI_VERSION_2_1_MIDDLE) { // directly set master volume (global volume is merged with channel volumes) ((MidiPlayer *)_driver)->setVolume(masterVolume); - break; - - default: - error("MidiParser_SCI::setVolume: Unsupported soundVersion"); + } else { + error("MidiParser_SCI::setVolume: Unsupported soundVersion %s", getSciVersionDesc(_soundVersion)); } } @@ -918,26 +904,17 @@ void MidiParser_SCI::setVolume(byte volume) { assert(volume <= MUSIC_VOLUME_MAX); _volume = volume; - switch (_soundVersion) { - case SCI_VERSION_0_EARLY: - case SCI_VERSION_0_LATE: { + if (_soundVersion <= SCI_VERSION_0_LATE) { // SCI0 adlib driver doesn't support channel volumes, so we need to go this way int16 globalVolume = _volume * _masterVolume / MUSIC_VOLUME_MAX; ((MidiPlayer *)_driver)->setVolume(globalVolume); - break; - } - - case SCI_VERSION_1_EARLY: - case SCI_VERSION_1_LATE: - case SCI_VERSION_2_1_EARLY: + } else if (_soundVersion >= SCI_VERSION_1_EARLY && _soundVersion <= SCI_VERSION_2_1_MIDDLE) { // Send previous channel volumes again to actually update the volume for (int i = 0; i < 15; i++) if (_channelRemap[i] != -1) sendToDriver(0xB0 + i, 7, _channelVolume[i]); - break; - - default: - error("MidiParser_SCI::setVolume: Unsupported soundVersion"); + } else { + error("MidiParser_SCI::setVolume: Unsupported soundVersion %s", getSciVersionDesc(_soundVersion)); } } diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 987983a7f9..ae89ee832b 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -215,7 +215,7 @@ void SciMusic::pauseAll(bool pause) { #ifdef ENABLE_SCI32 // The entire DAC will have been paused by the caller; // do not pause the individual samples too - if (_soundVersion >= SCI_VERSION_2_1_EARLY && (*i)->isSample) { + if (_soundVersion >= SCI_VERSION_2 && (*i)->isSample) { continue; } #endif @@ -483,7 +483,11 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { if (pSnd->isSample) { #ifdef ENABLE_SCI32 - if (_soundVersion >= SCI_VERSION_2_1_EARLY) { + if (_soundVersion >= SCI_VERSION_2) { + // TODO: Sound number, loop state, and volume come from soundObj + // in SSCI. Getting them from MusicEntry could cause a bug if the + // soundObj was updated by a game script and not copied back to + // MusicEntry. g_sci->_audio32->restart(ResourceId(kResourceTypeAudio, pSnd->resourceId), true, pSnd->loop != 0 && pSnd->loop != 1, pSnd->volume, pSnd->soundObj, false); return; } else @@ -567,7 +571,7 @@ void SciMusic::soundStop(MusicEntry *pSnd) { pSnd->isQueued = false; if (pSnd->isSample) { #ifdef ENABLE_SCI32 - if (_soundVersion >= SCI_VERSION_2_1_EARLY) { + if (_soundVersion >= SCI_VERSION_2) { g_sci->_audio32->stop(ResourceId(kResourceTypeAudio, pSnd->resourceId), pSnd->soundObj); } else { #endif @@ -642,7 +646,7 @@ void SciMusic::soundKill(MusicEntry *pSnd) { if (pSnd->isSample) { #ifdef ENABLE_SCI32 - if (_soundVersion >= SCI_VERSION_2_1_EARLY) { + if (_soundVersion >= SCI_VERSION_2) { g_sci->_audio32->stop(ResourceId(kResourceTypeAudio, pSnd->resourceId), pSnd->soundObj); } else { #endif diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 07e01fb759..f7cb6cda5c 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -48,7 +48,7 @@ SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segM // resource number, but it's totally unrelated to the menu music). // The GK1 demo (very late SCI1.1) does the same thing // TODO: Check the QFG4 demo - _useDigitalSFX = (getSciVersion() >= SCI_VERSION_2 || g_sci->getGameId() == GID_GK1DEMO || ConfMan.getBool("prefer_digitalsfx")); + _useDigitalSFX = (_soundVersion >= SCI_VERSION_2 || g_sci->getGameId() == GID_GK1DEMO || ConfMan.getBool("prefer_digitalsfx")); _music = new SciMusic(_soundVersion, _useDigitalSFX); _music->init(); @@ -100,8 +100,8 @@ void SoundCommandParser::initSoundResource(MusicEntry *newSound) { if (_useDigitalSFX || !newSound->soundRes) { int sampleLen; #ifdef ENABLE_SCI32 - if (_soundVersion >= SCI_VERSION_2_1_EARLY) { - newSound->isSample = g_sci->getResMan()->testResource(ResourceId(kResourceTypeAudio, newSound->resourceId)); + if (_soundVersion >= SCI_VERSION_2) { + newSound->isSample = g_sci->getResMan()->testResource(ResourceId(kResourceTypeAudio, newSound->resourceId)) != nullptr; } else { #endif newSound->pStreamAud = _audio->getAudioStream(newSound->resourceId, 65535, &sampleLen); @@ -316,8 +316,8 @@ reg_t SoundCommandParser::kDoSoundPause(EngineState *s, int argc, reg_t *argv) { reg_t obj = argv[0]; const bool shouldPause = argc > 1 ? argv[1].toUint16() : false; if ( - (_soundVersion < SCI_VERSION_2_1_EARLY && !obj.getSegment()) || - (_soundVersion >= SCI_VERSION_2_1_EARLY && obj.isNull()) + (_soundVersion < SCI_VERSION_2 && !obj.getSegment()) || + (_soundVersion >= SCI_VERSION_2 && obj.isNull()) ) { _music->pauseAll(shouldPause); #ifdef ENABLE_SCI32 @@ -501,7 +501,7 @@ void SoundCommandParser::processUpdateCues(reg_t obj) { if (musicSlot->isSample) { #ifdef ENABLE_SCI32 - if (_soundVersion >= SCI_VERSION_2_1_EARLY) { + if (_soundVersion >= SCI_VERSION_2) { const int position = g_sci->_audio32->getPosition(ResourceId(kResourceTypeAudio, musicSlot->resourceId), musicSlot->soundObj); if (position == -1) { @@ -717,9 +717,8 @@ reg_t SoundCommandParser::kDoSoundSetVolume(EngineState *s, int argc, reg_t *arg // SSCI unconditionally sets volume if it is digital audio if (_soundVersion >= SCI_VERSION_2_1_EARLY && musicSlot->isSample) { _music->soundSetVolume(musicSlot, value); - } + } else #endif - if (musicSlot->volume != value) { musicSlot->volume = value; _music->soundSetVolume(musicSlot, value); @@ -783,27 +782,15 @@ reg_t SoundCommandParser::kDoSoundSetLoop(EngineState *s, int argc, reg_t *argv) return s->r_acc; } -#ifdef ENABLE_SCI32 - if (_soundVersion >= SCI_VERSION_2_1_EARLY) { - if (value != -1) { - value = 1; - } - } -#endif - - if (value == -1) { - musicSlot->loop = 0xFFFF; - } else { - musicSlot->loop = 1; // actually plays the music once - } - - writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop); + const uint16 loopCount = value == -1 ? 0xFFFF : 1; + writeSelectorValue(_segMan, obj, SELECTOR(loop), loopCount); #ifdef ENABLE_SCI32 - if (_soundVersion >= SCI_VERSION_2_1_EARLY && musicSlot->isSample) { + if (_soundVersion >= SCI_VERSION_2_1_MIDDLE && musicSlot->isSample) { g_sci->_audio32->setLoop(ResourceId(kResourceTypeAudio, musicSlot->resourceId), musicSlot->soundObj, value == -1); - } + } else #endif + musicSlot->loop = loopCount; return s->r_acc; } -- cgit v1.2.3