diff options
author | Johannes Schickel | 2011-07-10 17:26:46 +0200 |
---|---|---|
committer | Johannes Schickel | 2011-07-10 17:42:02 +0200 |
commit | 781b7215c43ffc54ce571fb5ba830aa9dff3fcf9 (patch) | |
tree | 5eb6489dce9b49d031b66f164dc08c2ec45d1576 | |
parent | dab9c05783c56f6c0b0b3faf65921992bc953954 (diff) | |
download | scummvm-rg350-781b7215c43ffc54ce571fb5ba830aa9dff3fcf9.tar.gz scummvm-rg350-781b7215c43ffc54ce571fb5ba830aa9dff3fcf9.tar.bz2 scummvm-rg350-781b7215c43ffc54ce571fb5ba830aa9dff3fcf9.zip |
SCUMM: Fix PC Speaker sound.
Now we only output a new frequency if a new channel was selected or a new
output frequency has to be send. This makes the sound much more like in
DOSBox. This is not present in the original, but since our timings are
different this should make up for that.
-rw-r--r-- | engines/scumm/imuse/pcspk.cpp | 27 | ||||
-rw-r--r-- | engines/scumm/imuse/pcspk.h | 3 |
2 files changed, 29 insertions, 1 deletions
diff --git a/engines/scumm/imuse/pcspk.cpp b/engines/scumm/imuse/pcspk.cpp index ceecc3515e..6eaf7ad168 100644 --- a/engines/scumm/imuse/pcspk.cpp +++ b/engines/scumm/imuse/pcspk.cpp @@ -47,6 +47,12 @@ int PcSpkDriver::open() { _effectTimer = 0; _randBase = 1; + // We need to take care we only send note frequencies, when the internal + // settings actually changed, thus we need some extra state to keep track + // of that. + _lastActiveChannel = 0; + _lastActiveOut = 0; + _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); return 0; } @@ -120,6 +126,8 @@ void PcSpkDriver::onTimer() { output((_activeChannel->_out.note << 7) + _activeChannel->_pitchBend + _activeChannel->_out.unk60 + _activeChannel->_out.unkE); } else { _pcSpk.stop(); + _lastActiveChannel = 0; + _lastActiveOut = 0; } } @@ -135,6 +143,8 @@ void PcSpkDriver::updateNote() { if (_activeChannel == 0 || _activeChannel->_tl == 0) { _pcSpk.stop(); + _lastActiveChannel = 0; + _lastActiveOut = 0; } else { output(_activeChannel->_pitchBend + (_activeChannel->_out.note << 7)); } @@ -147,7 +157,15 @@ void PcSpkDriver::output(uint16 out) { byte shift = _outputTable1[v1]; uint16 indexBase = _outputTable2[v1] << 5; uint16 frequency = _frequencyTable[(indexBase + v2) / 2] >> shift; - _pcSpk.play(Audio::PCSpeaker::kWaveFormSquare, 1193180 / frequency, -1); + + // Only output in case the active channel changed or the frequency changed. + // This is not faithful to the original. Since our timings differ we would + // get distorted sound otherwise though. + if (_lastActiveChannel != _activeChannel || _lastActiveOut != out) { + _pcSpk.play(Audio::PCSpeaker::kWaveFormSquare, 1193180 / frequency, -1); + _lastActiveChannel = _activeChannel; + _lastActiveOut = out; + } } void PcSpkDriver::MidiChannel_PcSpk::init(PcSpkDriver *owner, byte channel) { @@ -249,6 +267,13 @@ void PcSpkDriver::MidiChannel_PcSpk::noteOn(byte note, byte velocity) { _out.unk60 = 0; _out.active = 1; + // In case we get a note on event on the last active channel, we reset the + // last active channel, thus we assure the frequency is correctly set, even + // when the same note was sent. + if (_owner->_lastActiveChannel == this) { + _owner->_lastActiveChannel = 0; + _owner->_lastActiveOut = 0; + } _owner->updateNote(); _out.unkC += PcSpkDriver::getEffectModifier(_instrument[3] + ((velocity & 0xFE) << 4)); diff --git a/engines/scumm/imuse/pcspk.h b/engines/scumm/imuse/pcspk.h index 3b63ec8199..3f70160988 100644 --- a/engines/scumm/imuse/pcspk.h +++ b/engines/scumm/imuse/pcspk.h @@ -145,6 +145,9 @@ private: MidiChannel_PcSpk _channels[6]; MidiChannel_PcSpk *_activeChannel; + MidiChannel_PcSpk *_lastActiveChannel; + uint16 _lastActiveOut; + static const byte _outInstrumentData[1024]; static const byte _outputTable1[]; static const byte _outputTable2[]; |