From a867fb70ddc145b03b8b782401364681e8c5560c Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Thu, 9 Feb 2017 12:14:46 -0600 Subject: SCI32: Fix audio playback with monitored channel in SCI3 SCI3 changes the way that monitored channel works. In SCI2/2.1, when a channel is monitored, it is the only audible channel. In SCI3, monitored channels mix normally. This is very noticeable in LSL7, where music disappears totally during speech if the monitored channel is the only channel played back. --- engines/sci/sound/audio32.cpp | 54 ++++++++++++++++++++++++++++--------------- engines/sci/sound/audio32.h | 4 +++- 2 files changed, 38 insertions(+), 20 deletions(-) (limited to 'engines/sci/sound') diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp index e9e90e41a7..5d008bff46 100644 --- a/engines/sci/sound/audio32.cpp +++ b/engines/sci/sound/audio32.cpp @@ -217,6 +217,8 @@ int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) { freeUnusedChannels(); + const bool playOnlyMonitoredChannel = getSciVersion() != SCI_VERSION_3 && _monitoredChannelIndex != -1; + // The caller of `readBuffer` is a rate converter, // which reuses (without clearing) an intermediate // buffer, so we need to zero the intermediate buffer @@ -248,7 +250,7 @@ int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) { // 0 | 2 (>> 1) // 1 | 4 (>> 2) // 2 | 6... - if (_monitoredChannelIndex == -1 && _numActiveChannels > 1) { + if (!playOnlyMonitoredChannel && _numActiveChannels > 1) { attenuationAmount = _numActiveChannels + 1; attenuationStepAmount = 1; } else { @@ -299,7 +301,7 @@ int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) { rightVolume = channel.volume * channel.pan / 100 * Audio::Mixer::kMaxChannelVolume / kMaxVolume; } - if (_monitoredChannelIndex == -1 && _attenuatedMixing) { + if (!playOnlyMonitoredChannel && _attenuatedMixing) { leftVolume >>= attenuationAmount; rightVolume >>= attenuationAmount; } @@ -326,7 +328,7 @@ int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) { maxSamplesWritten = _numMonitoredSamples; } } else if (!channel.stream->endOfStream() || channel.loop) { - if (_monitoredChannelIndex != -1) { + if (playOnlyMonitoredChannel) { // Audio that is not on the monitored channel is silent // when the monitored channel is active, but the stream still // needs to be read in order to ensure that sound effects sync @@ -942,14 +944,23 @@ reg_t Audio32::kernelPlay(const bool autoPlay, const int argc, const reg_t *cons loop = (bool)argv[5].toSint16(); } - if (argc < 7 || argv[6].toSint16() < 0 || argv[6].toSint16() > Audio32::kMaxVolume) { - volume = Audio32::kMaxVolume; - - if (argc >= 7) { - monitor = true; + if (getSciVersion() == SCI_VERSION_3) { + if (argc < 7) { + volume = Audio32::kMaxVolume; + } else { + volume = argv[6].toSint16() & Audio32::kMaxVolume; + monitor = argv[6].toSint16() & Audio32::kMonitorAudioFlagSci3; } } else { - volume = argv[6].toSint16(); + if (argc < 7 || argv[6].toSint16() < 0 || argv[6].toSint16() > Audio32::kMaxVolume) { + volume = Audio32::kMaxVolume; + + if (argc >= 7) { + monitor = true; + } + } else { + volume = argv[6].toSint16(); + } } } else { resourceId = ResourceId(kResourceTypeAudio, argv[0].toUint16()); @@ -960,18 +971,23 @@ reg_t Audio32::kernelPlay(const bool autoPlay, const int argc, const reg_t *cons loop = (bool)argv[1].toSint16(); } - // TODO: SCI3 uses the 0x80 bit as a flag to - // indicate "priority channel", but the volume is clamped - // in this call to 0x7F so that flag never makes it into - // the audio subsystem - if (argc < 3 || argv[2].toSint16() < 0 || argv[2].toSint16() > Audio32::kMaxVolume) { - volume = Audio32::kMaxVolume; - - if (argc >= 3) { - monitor = true; + if (getSciVersion() == SCI_VERSION_3) { + if (argc < 3) { + volume = Audio32::kMaxVolume; + } else { + volume = argv[2].toSint16() & Audio32::kMaxVolume; + monitor = argv[2].toSint16() & Audio32::kMonitorAudioFlagSci3; } } else { - volume = argv[2].toSint16(); + if (argc < 3 || argv[2].toSint16() < 0 || argv[2].toSint16() > Audio32::kMaxVolume) { + volume = Audio32::kMaxVolume; + + if (argc >= 3) { + monitor = true; + } + } else { + volume = argv[2].toSint16(); + } } soundNode = argc == 4 ? argv[3] : NULL_REG; diff --git a/engines/sci/sound/audio32.h b/engines/sci/sound/audio32.h index 8a1d8cfb43..f631de2bdf 100644 --- a/engines/sci/sound/audio32.h +++ b/engines/sci/sound/audio32.h @@ -164,7 +164,9 @@ public: /** * The maximum channel volume. */ - kMaxVolume = 127 + kMaxVolume = 127, + + kMonitorAudioFlagSci3 = 0x80 }; private: -- cgit v1.2.3