libsidplayfp  1.0.3
voice.h
00001 //  ---------------------------------------------------------------------------
00002 //  This file is part of reSID, a MOS6581 SID emulator engine.
00003 //  Copyright (C) 2010  Dag Lem <resid@nimrod.no>
00004 //
00005 //  This program is free software; you can redistribute it and/or modify
00006 //  it under the terms of the GNU General Public License as published by
00007 //  the Free Software Foundation; either version 2 of the License, or
00008 //  (at your option) any later version.
00009 //
00010 //  This program is distributed in the hope that it will be useful,
00011 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 //  GNU General Public License for more details.
00014 //
00015 //  You should have received a copy of the GNU General Public License
00016 //  along with this program; if not, write to the Free Software
00017 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 //  ---------------------------------------------------------------------------
00019 
00020 #ifndef RESID_VOICE_H
00021 #define RESID_VOICE_H
00022 
00023 #include "resid-config.h"
00024 #include "wave.h"
00025 #include "envelope.h"
00026 
00027 namespace reSID
00028 {
00029 
00030 class Voice
00031 {
00032 public:
00033   Voice();
00034 
00035   void set_chip_model(chip_model model);
00036   void set_sync_source(Voice*);
00037   void reset();
00038 
00039   void writeCONTROL_REG(reg8);
00040 
00041   // Amplitude modulated waveform output.
00042   // Range [-2048*255, 2047*255].
00043   int output();
00044 
00045   WaveformGenerator wave;
00046   EnvelopeGenerator envelope;
00047 
00048 protected:
00049   // Waveform D/A zero level.
00050   short wave_zero;
00051 
00052 friend class SID;
00053 };
00054 
00055 
00056 // ----------------------------------------------------------------------------
00057 // Inline functions.
00058 // The following function is defined inline because it is called every
00059 // time a sample is calculated.
00060 // ----------------------------------------------------------------------------
00061 
00062 #if RESID_INLINING || defined(RESID_VOICE_CC)
00063 
00064 // ----------------------------------------------------------------------------
00065 // Amplitude modulated waveform output (20 bits).
00066 // Ideal range [-2048*255, 2047*255].
00067 // ----------------------------------------------------------------------------
00068 
00069 // The output for a voice is produced by a multiplying DAC, where the
00070 // waveform output modulates the envelope output.
00071 //
00072 // As noted by Bob Yannes: "The 8-bit output of the Envelope Generator was then
00073 // sent to the Multiplying D/A converter to modulate the amplitude of the
00074 // selected Oscillator Waveform (to be technically accurate, actually the
00075 // waveform was modulating the output of the Envelope Generator, but the result
00076 // is the same)".
00077 //
00078 //          7   6   5   4   3   2   1   0   VGND
00079 //          |   |   |   |   |   |   |   |     |   Missing
00080 //         2R  2R  2R  2R  2R  2R  2R  2R    2R   termination
00081 //          |   |   |   |   |   |   |   |     |
00082 //          --R---R---R---R---R---R---R--   ---
00083 //          |          _____
00084 //        __|__     __|__   |
00085 //        -----     =====   |
00086 //        |   |     |   |   |
00087 // 12V ---     -----     ------- GND
00088 //               |
00089 //              vout
00090 //
00091 // Bit on:  wout (see figure in wave.h)
00092 // Bit off: 5V (VGND)
00093 //
00094 // As is the case with all MOS 6581 DACs, the termination to (virtual) ground
00095 // at bit 0 is missing. The MOS 8580 has correct termination.
00096 //
00097 
00098 RESID_INLINE
00099 int Voice::output()
00100 {
00101   // Multiply oscillator output with envelope output.
00102   return (wave.output() - wave_zero)*envelope.output();
00103 }
00104 
00105 #endif // RESID_INLINING || defined(RESID_VOICE_CC)
00106 
00107 } // namespace reSID
00108 
00109 #endif // not RESID_VOICE_H