libsidplayfp  2.12.0
sid.h
Go to the documentation of this file.
1 
3 // ---------------------------------------------------------------------------
4 // This file is part of reSID, a MOS6581 SID emulator engine.
5 // Copyright (C) 2010 Dag Lem <resid@nimrod.no>
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // ---------------------------------------------------------------------------
21 
22 #ifndef RESID_SID_H
23 #define RESID_SID_H
24 
25 #include "resid-config.h"
26 #include "voice.h"
27 #if NEW_8580_FILTER
28 #include "filter8580new.h"
29 #else
30 #include "filter.h"
31 #endif
32 #include "extfilt.h"
33 #include "pot.h"
34 
35 namespace reSID
36 {
37 
38 class SID
39 {
40 public:
41  SID();
42  ~SID();
43 
44  void set_chip_model(chip_model model);
45  void set_voice_mask(reg4 mask);
46  void enable_filter(bool enable);
47  void adjust_filter_bias(double dac_bias);
48  void enable_external_filter(bool enable);
49  bool set_sampling_parameters(double clock_freq, sampling_method method,
50  double sample_freq, double pass_freq = -1,
51  double filter_scale = 0.97);
52  void adjust_sampling_frequency(double sample_freq);
53  void enable_raw_debug_output(bool enable);
54 
55  void clock();
56  void clock(cycle_count delta_t);
57  int clock(cycle_count& delta_t, short* buf, int n, int interleave = 1);
58  void reset();
59 
60  // Read/write registers.
61  reg8 read(reg8 offset);
62  void write(reg8 offset, reg8 value);
63 
64  // Read/write state.
65  class State
66  {
67  public:
68  State();
69 
70  char sid_register[0x20];
71 
72  reg8 bus_value;
73  cycle_count bus_value_ttl;
74  cycle_count write_pipeline;
75  reg8 write_address;
76  reg4 voice_mask;
77 
78  reg24 accumulator[3];
79  reg24 shift_register[3];
80  cycle_count shift_register_reset[3];
81  cycle_count shift_pipeline[3];
82  reg16 pulse_output[3];
83  cycle_count floating_output_ttl[3];
84 
85  reg16 rate_counter[3];
86  reg16 rate_counter_period[3];
87  reg16 exponential_counter[3];
88  reg16 exponential_counter_period[3];
89  reg8 envelope_counter[3];
90  EnvelopeGenerator::State envelope_state[3];
91  bool hold_zero[3];
92  cycle_count envelope_pipeline[3];
93  };
94 
95  State read_state();
96  void write_state(const State& state);
97 
98  // 16-bit input (EXT IN).
99  void input(short sample);
100 
101  // 16-bit output (AUDIO OUT).
102  int output();
103 
104  void debugoutput(void);
105 
106  protected:
107  static double I0(double x);
108  int clock_fast(cycle_count& delta_t, short* buf, int n, int interleave);
109  int clock_interpolate(cycle_count& delta_t, short* buf, int n, int interleave);
110  int clock_resample(cycle_count& delta_t, short* buf, int n, int interleave);
111  int clock_resample_fastmem(cycle_count& delta_t, short* buf, int n, int interleave);
112  void write();
113 
114  chip_model sid_model;
115  Voice voice[3];
116  Filter filter;
117  ExternalFilter extfilt;
118  Potentiometer potx;
119  Potentiometer poty;
120 
121  reg8 bus_value;
122  cycle_count bus_value_ttl;
123 
124  // The data bus TTL for the selected chip model
125  cycle_count databus_ttl;
126 
127  // Pipeline for writes on the MOS8580.
128  cycle_count write_pipeline;
129  reg8 write_address;
130 
131  double clock_frequency;
132 
133  // Used to amplify the output by scaleFactor/2 to get an adequate playback volume
134  int scaleFactor;
135 
136  enum {
137  // Resampling constants.
138  // The error in interpolated lookup is bounded by 1.234/L^2,
139  // while the error in non-interpolated lookup is bounded by
140  // 0.7854/L + 0.4113/L^2, see
141  // http://www-ccrma.stanford.edu/~jos/resample/Choice_Table_Size.html
142  // For a resolution of 16 bits this yields L >= 285 and L >= 51473,
143  // respectively.
144  FIR_N = 125,
145  FIR_RES = 285,
146  FIR_RES_FASTMEM = 51473,
147  FIR_SHIFT = 15,
148 
149  RINGSIZE = 1 << 14,
150  RINGMASK = RINGSIZE - 1,
151 
152  // Fixed point constants (16.16 bits).
153  FIXP_SHIFT = 16,
154  FIXP_MASK = 0xffff
155  };
156 
157  // Sampling variables.
158  sampling_method sampling;
159  cycle_count cycles_per_sample;
160  cycle_count sample_offset;
161  int sample_index;
162  short sample_prev, sample_now;
163  int fir_N;
164  int fir_RES;
165  double fir_beta;
166  double fir_f_cycles_per_sample;
167  double fir_filter_scale;
168 
169  // Ring buffer with overflow for contiguous storage of RINGSIZE samples.
170  short* sample;
171 
172  // FIR_RES filter tables (FIR_N*FIR_RES).
173  short* fir;
174 
175  bool raw_debug_output; // FIXME: should be private?
176 };
177 
178 
179 // ----------------------------------------------------------------------------
180 // Inline functions.
181 // The following functions are defined inline because they are called every
182 // time a sample is calculated.
183 // ----------------------------------------------------------------------------
184 
185 #if RESID_INLINING || defined(RESID_SID_CC)
186 
187 // ----------------------------------------------------------------------------
188 // Read 16-bit sample from audio output.
189 // ----------------------------------------------------------------------------
190 RESID_INLINE
191 int SID::output()
192 {
193  return extfilt.output();
194 }
195 
196 
197 // ----------------------------------------------------------------------------
198 // SID clocking - 1 cycle.
199 // ----------------------------------------------------------------------------
200 RESID_INLINE
201 void SID::clock()
202 {
203  int i;
204 
205  // Clock amplitude modulators.
206  for (i = 0; i < 3; i++) {
207  voice[i].envelope.clock();
208  }
209 
210  // Clock oscillators.
211  for (i = 0; i < 3; i++) {
212  voice[i].wave.clock();
213  }
214 
215  // Synchronize oscillators.
216  for (i = 0; i < 3; i++) {
217  voice[i].wave.synchronize();
218  }
219 
220  // Calculate waveform output.
221  for (i = 0; i < 3; i++) {
222  voice[i].wave.set_waveform_output();
223  }
224 
225  // Clock filter.
226  filter.clock(voice[0].output(), voice[1].output(), voice[2].output());
227 
228  // Clock external filter.
229  extfilt.clock(filter.output());
230 
231  // Pipelined writes on the MOS8580.
232  if (unlikely(write_pipeline)) {
233  write();
234  }
235 
236  // Age bus value.
237  if (unlikely(!--bus_value_ttl)) {
238  bus_value = 0;
239  }
240 
241  if (unlikely(raw_debug_output)) {
242  debugoutput();
243  }
244 }
245 
246 #endif // RESID_INLINING || defined(RESID_SID_CC)
247 
248 } // namespace reSID
249 
250 #endif // not RESID_SID_H
Definition: extfilt.h:56
Definition: filter.h:347
Definition: pot.h:29
Definition: sid.h:66
Definition: sid.h:39
Definition: voice.h:31