aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/sound
diff options
context:
space:
mode:
authorColin Snover2016-07-11 10:37:51 -0500
committerColin Snover2016-07-11 10:39:50 -0500
commitec73fa1e4af4acc9806e948993f702dfc363a094 (patch)
treea7257cb11fddcc1cad038984176e956c9b8434ce /engines/sci/sound
parent1714cf8aa562e0eb25e957e9bf7636ceb4785216 (diff)
downloadscummvm-rg350-ec73fa1e4af4acc9806e948993f702dfc363a094.tar.gz
scummvm-rg350-ec73fa1e4af4acc9806e948993f702dfc363a094.tar.bz2
scummvm-rg350-ec73fa1e4af4acc9806e948993f702dfc363a094.zip
SCI32: Fix audio deadlocks
Several functions in Audio32 would call into the mixer to pause or resume the audio handle, which would cause a deadlock if the mixer's mixCallback timer fired while one of these functions was running on the main thread. To address this, calls to mixer to pause/unpause the digital audio handle have been removed. Since this was just an optimisation to prevent unnecessary calls to fill the audio buffer, the only problem now is that a tiny amount of CPU is wasted on unnecessary callbacks to read from the empty SCI mixer.
Diffstat (limited to 'engines/sci/sound')
-rw-r--r--engines/sci/sound/audio32.cpp20
1 files changed, 6 insertions, 14 deletions
diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp
index 98c2a51a3b..e7d02464d6 100644
--- a/engines/sci/sound/audio32.cpp
+++ b/engines/sci/sound/audio32.cpp
@@ -153,7 +153,6 @@ Audio32::Audio32(ResourceManager *resMan) :
}
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
- _mixer->pauseHandle(_handle, true);
}
Audio32::~Audio32() {
@@ -235,16 +234,16 @@ int Audio32::writeAudioInternal(Audio::RewindableAudioStream *const sourceStream
int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) {
Common::StackLock lock(_mutex);
+ if (_pausedAtTick != 0 || _numActiveChannels == 0) {
+ return 0;
+ }
+
// ResourceManager is not thread-safe so we need to
// avoid calling into it from the audio thread, but at
// the same time we need to be able to clear out any
// finished channels on a regular basis
_inAudioThread = true;
- // The system mixer should not try to get data when
- // Audio32 is paused
- assert(_pausedAtTick == 0 && _numActiveChannels > 0);
-
freeUnusedChannels();
// The caller of `readBuffer` is a rate converter,
@@ -647,7 +646,6 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
if (_numActiveChannels == 1) {
_startedAtTick = now;
- _mixer->pauseHandle(_handle, false);
}
return channel.duration;
@@ -678,7 +676,6 @@ bool Audio32::resume(const int16 channelIndex) {
_startedAtTick += now - _pausedAtTick;
_pausedAtTick = 0;
- _mixer->pauseHandle(_handle, false);
return true;
} else if (channelIndex == kRobotChannel) {
for (int i = 0; i < _numActiveChannels; ++i) {
@@ -715,7 +712,6 @@ bool Audio32::pause(const int16 channelIndex) {
if (channelIndex == kAllChannels) {
if (_pausedAtTick == 0) {
_pausedAtTick = now;
- _mixer->pauseHandle(_handle, true);
didPause = true;
}
} else if (channelIndex == kRobotChannel) {
@@ -768,9 +764,6 @@ int16 Audio32::stop(const int16 channelIndex) {
// NOTE: SSCI stops the DSP interrupt and frees the
// global decompression buffer here if there are no
// more active channels
- if (_numActiveChannels == 0) {
- _mixer->pauseHandle(_handle, true);
- }
return oldNumChannels;
}
@@ -886,17 +879,15 @@ reg_t Audio32::kernelPlay(const bool autoPlay, const int argc, const reg_t *cons
#pragma mark Effects
int16 Audio32::getVolume(const int16 channelIndex) const {
- Common::StackLock lock(_mutex);
if (channelIndex < 0 || channelIndex >= _numActiveChannels) {
return _mixer->getChannelVolume(_handle) * kMaxVolume / Audio::Mixer::kMaxChannelVolume;
}
+ Common::StackLock lock(_mutex);
return getChannel(channelIndex).volume;
}
void Audio32::setVolume(const int16 channelIndex, int16 volume) {
- Common::StackLock lock(_mutex);
-
volume = MIN((int16)kMaxVolume, volume);
if (channelIndex == kAllChannels) {
ConfMan.setInt("sfx_volume", volume * Audio::Mixer::kMaxChannelVolume / kMaxVolume);
@@ -904,6 +895,7 @@ void Audio32::setVolume(const int16 channelIndex, int16 volume) {
_mixer->setChannelVolume(_handle, volume * Audio::Mixer::kMaxChannelVolume / kMaxVolume);
g_engine->syncSoundSettings();
} else if (channelIndex != kNoExistingChannel) {
+ Common::StackLock lock(_mutex);
getChannel(channelIndex).volume = volume;
}
}