summaryrefslogtreecommitdiff
path: root/plugins/sid/sidplay-libs/resid/voice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/sid/sidplay-libs/resid/voice.cpp')
-rw-r--r--plugins/sid/sidplay-libs/resid/voice.cpp147
1 files changed, 147 insertions, 0 deletions
diff --git a/plugins/sid/sidplay-libs/resid/voice.cpp b/plugins/sid/sidplay-libs/resid/voice.cpp
new file mode 100644
index 00000000..049e0530
--- /dev/null
+++ b/plugins/sid/sidplay-libs/resid/voice.cpp
@@ -0,0 +1,147 @@
+// ---------------------------------------------------------------------------
+// This file is part of reSID, a MOS6581 SID emulator engine.
+// Copyright (C) 2002 Dag Lem <resid@nimrod.no>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// ---------------------------------------------------------------------------
+
+#define __VOICE_CC__
+#include "voice.h"
+
+RESID_NAMESPACE_START
+
+// ----------------------------------------------------------------------------
+// Constructor.
+// ----------------------------------------------------------------------------
+Voice::Voice()
+ : muted(false)
+{
+ set_chip_model(MOS6581);
+}
+
+// ----------------------------------------------------------------------------
+// Set chip model.
+// ----------------------------------------------------------------------------
+void Voice::set_chip_model(chip_model model)
+{
+ wave.set_chip_model(model);
+
+ if (model == MOS6581) {
+ // The waveform D/A converter introduces a DC offset in the signal
+ // to the envelope multiplying D/A converter. The "zero" level of
+ // the waveform D/A converter can be found as follows:
+ //
+ // Measure the "zero" voltage of voice 3 on the SID audio output
+ // pin, routing only voice 3 to the mixer ($d417 = $0b, $d418 =
+ // $0f, all other registers zeroed).
+ //
+ // Then set the sustain level for voice 3 to maximum and search for
+ // the waveform output value yielding the same voltage as found
+ // above. This is done by trying out different waveform output
+ // values until the correct value is found, e.g. with the following
+ // program:
+ //
+ // lda #$08
+ // sta $d412
+ // lda #$0b
+ // sta $d417
+ // lda #$0f
+ // sta $d418
+ // lda #$f0
+ // sta $d414
+ // lda #$21
+ // sta $d412
+ // lda #$01
+ // sta $d40e
+ //
+ // ldx #$00
+ // lda #$38 ; Tweak this to find the "zero" level
+ //l cmp $d41b
+ // bne l
+ // stx $d40e ; Stop frequency counter - freeze waveform output
+ // brk
+ //
+ // The waveform output range is 0x000 to 0xfff, so the "zero"
+ // level should ideally have been 0x800. In the measured chip, the
+ // waveform output "zero" level was found to be 0x380 (i.e. $d41b
+ // = 0x38) at 5.94V.
+
+ wave_DC = -0x380;
+
+ // The envelope multiplying D/A converter introduces another DC
+ // offset. This is isolated by the following measurements:
+ //
+ // * The "zero" output level of the mixer at full volume is 5.44V.
+ // * Routing one voice to the mixer at full volume yields
+ // 6.75V at maximum voice output (wave = 0xfff, sustain = 0xf)
+ // 5.94V at "zero" voice output (wave = any, sustain = 0x0)
+ // 5.70V at minimum voice output (wave = 0x000, sustain = 0xf)
+ // * The DC offset of one voice is (5.94V - 5.44V) = 0.50V
+ // * The dynamic range of one voice is |6.75V - 5.70V| = 1.05V
+ // * The DC offset is thus 0.50V/1.05V ~ 1/2 of the dynamic range.
+ //
+ // Note that by removing the DC offset, we get the following ranges for
+ // one voice:
+ // y > 0: (6.75V - 5.44V) - 0.50V = 0.81V
+ // y < 0: (5.70V - 5.44V) - 0.50V = -0.24V
+ // The scaling of the voice amplitude is not symmetric about y = 0;
+ // this follows from the DC level in the waveform output.
+
+ voice_DC = 0x800*0xff;
+ }
+ else {
+ // No DC offsets in the MOS8580.
+ wave_DC = -0x800;
+ voice_DC = 0;
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Set sync source.
+// ----------------------------------------------------------------------------
+void Voice::set_sync_source(Voice* source)
+{
+ wave.set_sync_source(&source->wave);
+}
+
+// ----------------------------------------------------------------------------
+// Register functions.
+// ----------------------------------------------------------------------------
+void Voice::writeCONTROL_REG(reg8 control)
+{
+ wave.writeCONTROL_REG(control);
+ envelope.writeCONTROL_REG(control);
+}
+
+// ----------------------------------------------------------------------------
+// SID reset.
+// ----------------------------------------------------------------------------
+void Voice::reset()
+{
+ wave.reset();
+ envelope.reset();
+}
+
+
+// ----------------------------------------------------------------------------
+// Voice mute.
+// ----------------------------------------------------------------------------
+void Voice::mute(bool enable)
+{
+ // enable = true (means voice is muted)
+ muted = enable;
+}
+
+RESID_NAMESPACE_STOP