aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schickel2011-07-10 17:26:46 +0200
committerJohannes Schickel2011-07-10 17:42:02 +0200
commit781b7215c43ffc54ce571fb5ba830aa9dff3fcf9 (patch)
tree5eb6489dce9b49d031b66f164dc08c2ec45d1576
parentdab9c05783c56f6c0b0b3faf65921992bc953954 (diff)
downloadscummvm-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.cpp27
-rw-r--r--engines/scumm/imuse/pcspk.h3
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[];