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