libsidplayfp  1.0.3
sid.h
Go to the documentation of this file.
00001 
00003 //  ---------------------------------------------------------------------------
00004 //  This file is part of reSID, a MOS6581 SID emulator engine.
00005 //  Copyright (C) 2010  Dag Lem <resid@nimrod.no>
00006 //
00007 //  This program is free software; you can redistribute it and/or modify
00008 //  it under the terms of the GNU General Public License as published by
00009 //  the Free Software Foundation; either version 2 of the License, or
00010 //  (at your option) any later version.
00011 //
00012 //  This program is distributed in the hope that it will be useful,
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //  GNU General Public License for more details.
00016 //
00017 //  You should have received a copy of the GNU General Public License
00018 //  along with this program; if not, write to the Free Software
00019 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //  ---------------------------------------------------------------------------
00021 
00022 #ifndef RESID_SID_H
00023 #define RESID_SID_H
00024 
00025 #include "resid-config.h"
00026 #include "voice.h"
00027 #include "filter.h"
00028 #include "extfilt.h"
00029 #include "pot.h"
00030 
00031 namespace reSID
00032 {
00033 
00034 class SID
00035 {
00036 public:
00037   SID();
00038   ~SID();
00039 
00040   void set_chip_model(chip_model model);
00041   void set_voice_mask(reg4 mask);
00042   void enable_filter(bool enable);
00043   void adjust_filter_bias(double dac_bias);
00044   void enable_external_filter(bool enable);
00045   bool set_sampling_parameters(double clock_freq, sampling_method method,
00046                                double sample_freq, double pass_freq = -1,
00047                                double filter_scale = 0.97);
00048   void adjust_sampling_frequency(double sample_freq);
00049 
00050   void clock();
00051   void clock(cycle_count delta_t);
00052   int clock(cycle_count& delta_t, short* buf, int n, int interleave = 1);
00053   void reset();
00054   
00055   // Read/write registers.
00056   reg8 read(reg8 offset);
00057   void write(reg8 offset, reg8 value);
00058 
00059   // Read/write state.
00060   class State
00061   {
00062   public:
00063     State();
00064 
00065     char sid_register[0x20];
00066 
00067     reg8 bus_value;
00068     cycle_count bus_value_ttl;
00069     cycle_count write_pipeline;
00070     reg8 write_address;
00071     reg4 voice_mask;
00072 
00073     reg24 accumulator[3];
00074     reg24 shift_register[3];
00075     cycle_count shift_register_reset[3];
00076     cycle_count shift_pipeline[3];
00077     reg16 pulse_output[3];
00078     cycle_count floating_output_ttl[3];
00079 
00080     reg16 rate_counter[3];
00081     reg16 rate_counter_period[3];
00082     reg16 exponential_counter[3];
00083     reg16 exponential_counter_period[3];
00084     reg8 envelope_counter[3];
00085     EnvelopeGenerator::State envelope_state[3];
00086     bool hold_zero[3];
00087     cycle_count envelope_pipeline[3];
00088   };
00089     
00090   State read_state();
00091   void write_state(const State& state);
00092 
00093   // 16-bit input (EXT IN).
00094   void input(short sample);
00095 
00096   // 16-bit output (AUDIO OUT).
00097   short output();
00098 
00099  protected:
00100   static double I0(double x);
00101   int clock_fast(cycle_count& delta_t, short* buf, int n, int interleave);
00102   int clock_interpolate(cycle_count& delta_t, short* buf, int n,
00103                         int interleave);
00104   int clock_resample(cycle_count& delta_t, short* buf, int n, int interleave);
00105   int clock_resample_fastmem(cycle_count& delta_t, short* buf, int n,
00106                              int interleave);
00107   void write();
00108 
00109   chip_model sid_model;
00110   Voice voice[3];
00111   Filter filter;
00112   ExternalFilter extfilt;
00113   Potentiometer potx;
00114   Potentiometer poty;
00115 
00116   reg8 bus_value;
00117   cycle_count bus_value_ttl;
00118 
00119   // Pipeline for writes on the MOS8580.
00120   cycle_count write_pipeline;
00121   reg8 write_address;
00122 
00123   double clock_frequency;
00124 
00125   enum {
00126     // Resampling constants.
00127     // The error in interpolated lookup is bounded by 1.234/L^2,
00128     // while the error in non-interpolated lookup is bounded by
00129     // 0.7854/L + 0.4113/L^2, see
00130     // http://www-ccrma.stanford.edu/~jos/resample/Choice_Table_Size.html
00131     // For a resolution of 16 bits this yields L >= 285 and L >= 51473,
00132     // respectively.
00133     FIR_N = 125,
00134     FIR_RES = 285,
00135     FIR_RES_FASTMEM = 51473,
00136     FIR_SHIFT = 15,
00137 
00138     RINGSIZE = 1 << 14,
00139     RINGMASK = RINGSIZE - 1,
00140 
00141     // Fixed point constants (16.16 bits).
00142     FIXP_SHIFT = 16,
00143     FIXP_MASK = 0xffff
00144   };
00145 
00146   // Sampling variables.
00147   sampling_method sampling;
00148   cycle_count cycles_per_sample;
00149   cycle_count sample_offset;
00150   int sample_index;
00151   short sample_prev, sample_now;
00152   int fir_N;
00153   int fir_RES;
00154 
00155   // Ring buffer with overflow for contiguous storage of RINGSIZE samples.
00156   short* sample;
00157 
00158   // FIR_RES filter tables (FIR_N*FIR_RES).
00159   short* fir;
00160 };
00161 
00162 
00163 // ----------------------------------------------------------------------------
00164 // Inline functions.
00165 // The following functions are defined inline because they are called every
00166 // time a sample is calculated.
00167 // ----------------------------------------------------------------------------
00168 
00169 #if RESID_INLINING || defined(RESID_SID_CC)
00170 
00171 // ----------------------------------------------------------------------------
00172 // Read 16-bit sample from audio output.
00173 // ----------------------------------------------------------------------------
00174 RESID_INLINE
00175 short SID::output()
00176 {
00177   return extfilt.output();
00178 }
00179 
00180 
00181 // ----------------------------------------------------------------------------
00182 // SID clocking - 1 cycle.
00183 // ----------------------------------------------------------------------------
00184 RESID_INLINE
00185 void SID::clock()
00186 {
00187   int i;
00188 
00189   // Clock amplitude modulators.
00190   for (i = 0; i < 3; i++) {
00191     voice[i].envelope.clock();
00192   }
00193 
00194   // Clock oscillators.
00195   for (i = 0; i < 3; i++) {
00196     voice[i].wave.clock();
00197   }
00198 
00199   // Synchronize oscillators.
00200   for (i = 0; i < 3; i++) {
00201     voice[i].wave.synchronize();
00202   }
00203 
00204   // Calculate waveform output.
00205   for (i = 0; i < 3; i++) {
00206     voice[i].wave.set_waveform_output();
00207   }
00208 
00209   // Clock filter.
00210   filter.clock(voice[0].output(), voice[1].output(), voice[2].output());
00211 
00212   // Clock external filter.
00213   extfilt.clock(filter.output());
00214 
00215   // Pipelined writes on the MOS8580.
00216   if (unlikely(write_pipeline)) {
00217     write();
00218   }
00219 
00220   // Age bus value.
00221   if (unlikely(!--bus_value_ttl)) {
00222     bus_value = 0;
00223   }
00224 }
00225 
00226 #endif // RESID_INLINING || defined(RESID_SID_CC)
00227 
00228 } // namespace reSID
00229 
00230 #endif // not RESID_SID_H