libsidplayfp 1.8.8
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#include "filter.h"
28#include "extfilt.h"
29#include "pot.h"
30
31namespace reSID
32{
33
34class SID
35{
36public:
37 SID();
38 ~SID();
39
40 void set_chip_model(chip_model model);
41 void set_voice_mask(reg4 mask);
42 void enable_filter(bool enable);
43 void adjust_filter_bias(double dac_bias);
44 void enable_external_filter(bool enable);
45 bool set_sampling_parameters(double clock_freq, sampling_method method,
46 double sample_freq, double pass_freq = -1,
47 double filter_scale = 0.97);
48 void adjust_sampling_frequency(double sample_freq);
49
50 void clock();
51 void clock(cycle_count delta_t);
52 int clock(cycle_count& delta_t, short* buf, int n, int interleave = 1);
53 void reset();
54
55 // Read/write registers.
56 reg8 read(reg8 offset);
57 void write(reg8 offset, reg8 value);
58
59 // Read/write state.
60 class State
61 {
62 public:
63 State();
64
65 char sid_register[0x20];
66
67 reg8 bus_value;
68 cycle_count bus_value_ttl;
69 cycle_count write_pipeline;
70 reg8 write_address;
71 reg4 voice_mask;
72
73 reg24 accumulator[3];
74 reg24 shift_register[3];
75 cycle_count shift_register_reset[3];
76 cycle_count shift_pipeline[3];
77 reg16 pulse_output[3];
78 cycle_count floating_output_ttl[3];
79
80 reg16 rate_counter[3];
81 reg16 rate_counter_period[3];
82 reg16 exponential_counter[3];
83 reg16 exponential_counter_period[3];
84 reg8 envelope_counter[3];
85 EnvelopeGenerator::State envelope_state[3];
86 bool hold_zero[3];
87 cycle_count envelope_pipeline[3];
88 };
89
90 State read_state();
91 void write_state(const State& state);
92
93 // 16-bit input (EXT IN).
94 void input(short sample);
95
96 // 16-bit output (AUDIO OUT).
97 short output();
98
99 protected:
100 static double I0(double x);
101 int clock_fast(cycle_count& delta_t, short* buf, int n, int interleave);
102 int clock_interpolate(cycle_count& delta_t, short* buf, int n,
103 int interleave);
104 int clock_resample(cycle_count& delta_t, short* buf, int n, int interleave);
105 int clock_resample_fastmem(cycle_count& delta_t, short* buf, int n,
106 int interleave);
107 void write();
108
109 chip_model sid_model;
110 Voice voice[3];
111 Filter filter;
112 ExternalFilter extfilt;
113 Potentiometer potx;
114 Potentiometer poty;
115
116 reg8 bus_value;
117 cycle_count bus_value_ttl;
118
119 // Pipeline for writes on the MOS8580.
120 cycle_count write_pipeline;
121 reg8 write_address;
122
123 double clock_frequency;
124
125 enum {
126 // Resampling constants.
127 // The error in interpolated lookup is bounded by 1.234/L^2,
128 // while the error in non-interpolated lookup is bounded by
129 // 0.7854/L + 0.4113/L^2, see
130 // http://www-ccrma.stanford.edu/~jos/resample/Choice_Table_Size.html
131 // For a resolution of 16 bits this yields L >= 285 and L >= 51473,
132 // respectively.
133 FIR_N = 125,
134 FIR_RES = 285,
135 FIR_RES_FASTMEM = 51473,
136 FIR_SHIFT = 15,
137
138 RINGSIZE = 1 << 14,
139 RINGMASK = RINGSIZE - 1,
140
141 // Fixed point constants (16.16 bits).
142 FIXP_SHIFT = 16,
143 FIXP_MASK = 0xffff
144 };
145
146 // Sampling variables.
147 sampling_method sampling;
148 cycle_count cycles_per_sample;
149 cycle_count sample_offset;
150 int sample_index;
151 short sample_prev, sample_now;
152 int fir_N;
153 int fir_RES;
154 double fir_beta;
155 double fir_f_cycles_per_sample;
156 double fir_filter_scale;
157
158 // Ring buffer with overflow for contiguous storage of RINGSIZE samples.
159 short* sample;
160
161 // FIR_RES filter tables (FIR_N*FIR_RES).
162 short* fir;
163};
164
165
166// ----------------------------------------------------------------------------
167// Inline functions.
168// The following functions are defined inline because they are called every
169// time a sample is calculated.
170// ----------------------------------------------------------------------------
171
172#if RESID_INLINING || defined(RESID_SID_CC)
173
174// ----------------------------------------------------------------------------
175// Read 16-bit sample from audio output.
176// ----------------------------------------------------------------------------
177RESID_INLINE
178short SID::output()
179{
180 return extfilt.output();
181}
182
183
184// ----------------------------------------------------------------------------
185// SID clocking - 1 cycle.
186// ----------------------------------------------------------------------------
187RESID_INLINE
188void SID::clock()
189{
190 int i;
191
192 // Clock amplitude modulators.
193 for (i = 0; i < 3; i++) {
194 voice[i].envelope.clock();
195 }
196
197 // Clock oscillators.
198 for (i = 0; i < 3; i++) {
199 voice[i].wave.clock();
200 }
201
202 // Synchronize oscillators.
203 for (i = 0; i < 3; i++) {
204 voice[i].wave.synchronize();
205 }
206
207 // Calculate waveform output.
208 for (i = 0; i < 3; i++) {
209 voice[i].wave.set_waveform_output();
210 }
211
212 // Clock filter.
213 filter.clock(voice[0].output(), voice[1].output(), voice[2].output());
214
215 // Clock external filter.
216 extfilt.clock(filter.output());
217
218 // Pipelined writes on the MOS8580.
219 if (unlikely(write_pipeline)) {
220 write();
221 }
222
223 // Age bus value.
224 if (unlikely(!--bus_value_ttl)) {
225 bus_value = 0;
226 }
227}
228
229#endif // RESID_INLINING || defined(RESID_SID_CC)
230
231} // namespace reSID
232
233#endif // not RESID_SID_H
Definition: extfilt.h:42
Definition: filter.h:347
Definition: pot.h:29
Definition: sid.h:61
Definition: sid.h:35
Definition: voice.h:31