public class Filter extends Object
Measurements show that excellent emulation of the SID filter is achieved, except when high resonance is combined with high sustain levels. In this case the SID op-amps are performing less than ideally and are causing some peculiar behavior of the SID filter. This however seems to have more effect on the overall amplitude than on the color of the sound.
The theory for the filter circuit can be found in "Microelectric Circuits" by Adel S. Sedra and Kenneth C. Smith. The circuit is modeled based on the explanation found there except that an additional inverter is used in the feedback from the bandpass output, allowing the summer op-amp to operate in single-ended mode. This yields inverted filter outputs with levels independent of Q, which corresponds with the results obtained from a real SID.
We have been able to model the summer and the two integrators of the circuit to form components of an IIR filter. vhp is the output of the summer, vbp is the output of the first integrator, and vlp is the output of the second integrator in the filter circuit.
According to Bob Yannes, the active stages of the SID filter are not really op-amps. Rather, simple NMOS inverters are used. By biasing an inverter into its region of quasi-linear operation using a feedback resistor from input to output, a MOS inverter can be made to act like an op-amp for small signals centered around the switching threshold.
Qualified guesses at SID filter schematics are depicted below.
SID filter
----------
-----------------------------------------------
| |
| ---Rq-- |
| | | |
| ------------<A]-----R1--------- |
| | | |
| | ---C---| ---C---|
| | | | | |
| --R1-- ---R1-- |---Rs--| |---Rs--|
| | | | | | | |
----R1--|-----[A>--|--R-----[A>--|--R-----[A>--|
| | | |
vi -----R1-- | | |
vhp vbp vlp
vi - input voltage
vhp - highpass output
vbp - bandpass output
vlp - lowpass output
[A> - op-amp
R1 - summer resistor
Rq - resistor array controlling resonance (4 resistors)
R - NMOS FET voltage controlled resistor controlling cutoff frequency
Rs - shunt resitor
C - capacitor
SID integrator
--------------
V+
|
|
-----|
| |
| ||--
-||
---C--- ||->
| | |
|---Rs-----------|---- vo
| |
| ||--
vi ---- -----|------------||
| ˆ | ||->
|___| | |
----- | |
| | |
|---R2-- |
|
R1 V-
|
|
Vw
----------------------------------------------------------------------------
| Modifier and Type | Class and Description |
|---|---|
static class |
Filter.Coefficients |
| Modifier and Type | Field and Description |
|---|---|
protected int |
_1024_div_Q |
protected boolean |
enabled
Filter enabled.
|
protected int[] |
f0 |
protected int[] |
f0_6581
Cutoff frequency tables.
|
protected int[] |
f0_8580
Cutoff frequency tables.
|
protected int |
f0_count |
protected int[][] |
f0_points |
protected static int[][] |
f0_points_6581
Maximum cutoff frequency is specified as FCmax = 2.6e-5/C =
2.6e-5/2200e-12 = 11818.
|
protected static int[][] |
f0_points_8580
Maximum cutoff frequency is specified as FCmax = 2.6e-5/C =
2.6e-5/2200e-12 = 11818.
|
protected int |
fc
Filter cutoff frequency.
|
protected int |
filt
Selects which inputs to route through filter.
|
protected int |
hp_bp_lp
Highpass, bandpass, and lowpass filter modes.
|
protected int |
mixer_DC
Mixer DC offset.
|
protected int |
res
Filter resonance.
|
static boolean |
SPLINE_BRUTE_FORCE
#define SPLINE_BRUTE_FORCE false
|
protected int |
vbp
State of filter. bandpass
|
protected int |
vhp
State of filter. highpass
|
protected int |
vlp
State of filter. lowpass
|
protected int |
vnf
State of filter. not filtered
|
protected int |
voice3off
Switch voice 3 off.
|
protected int |
vol
Output master volume.
|
protected int |
w0
Cutoff frequency, resonance.
|
protected int |
w0_ceil_1
Cutoff frequency, resonance.
|
protected int |
w0_ceil_dt
Cutoff frequency, resonance.
|
| Constructor and Description |
|---|
Filter()
Constructor.
|
| Modifier and Type | Method and Description |
|---|---|
void |
clock(int voice1,
int voice2,
int voice3,
int ext_in)
SID clocking - 1 cycle
|
void |
clock(int delta_t,
int voice1,
int voice2,
int voice3,
int ext_in)
SID clocking - delta_t cycles.
|
protected void |
cubic_coefficients(double x1,
double y1,
double x2,
double y2,
double k1,
double k2,
Filter.Coefficients coeff)
Calculation of coefficients.
|
void |
enable_filter(boolean enable)
Enable filter.
|
void |
fc_default(SID.FCPoints fcp)
Return the array of spline interpolation points used to map the FC
register to filter cutoff frequency.
|
PointPlotter |
fc_plotter() |
protected void |
interpolate_brute_force(double x1,
double y1,
double x2,
double y2,
double k1,
double k2,
PointPlotter plotter,
double res)
Evaluation of cubic polynomial by brute force.
|
protected void |
interpolate_forward_difference(double x1,
double y1,
double x2,
double y2,
double k1,
double k2,
PointPlotter plotter,
double res)
Evaluation of cubic polynomial by forward differencing.
|
void |
interpolate(int[][] f0_base,
int p0,
int pn,
PointPlotter plotter,
double res)
Evaluation of complete interpolating function.
|
int |
output()
SID audio output (16 bits).
|
void |
reset()
SID reset.
|
void |
set_chip_model(ISIDDefs.chip_model model)
Set chip model.
|
protected void |
set_Q()
Set filter resonance.
|
protected void |
set_w0() |
void |
writeFC_HI(int fc_hi)
Register functions.
|
void |
writeFC_LO(int fc_lo)
Register functions.
|
void |
writeMODE_VOL(int mode_vol)
Register functions.
|
void |
writeRES_FILT(int res_filt)
Register functions.
|
protected double |
x(int[][] f0_base,
int p) |
protected double |
y(int[][] f0_base,
int p) |
public static final boolean SPLINE_BRUTE_FORCE
protected boolean enabled
protected int fc
protected int res
protected int filt
protected int voice3off
protected int hp_bp_lp
protected int vol
protected int mixer_DC
protected int vhp
protected int vbp
protected int vlp
protected int vnf
protected int w0
protected int w0_ceil_1
protected int w0_ceil_dt
protected int _1024_div_Q
protected int[] f0_6581
protected int[] f0_8580
protected int[] f0
protected static int[][] f0_points_6581
Measurements indicate a cutoff frequency range of approximately 220Hz - 18kHz on a MOS6581 fitted with 470pF capacitors. The function mapping FC to cutoff frequency has the shape of the tanh function, with a discontinuity at FCHI = 0x80. In contrast, the MOS8580 almost perfectly corresponds with the specification of a linear mapping from 30Hz to 12kHz.
The mappings have been measured by feeding the SID with an external signal since the chip itself is incapable of generating waveforms of higher fundamental frequency than 4kHz. It is best to use the bandpass output at full resonance to pick out the cutoff frequency at any given FC setting.
The mapping function is specified with spline interpolation points and the function values are retrieved via table lookup.
NB! Cutoff frequency characteristics may vary, we have modeled two particular Commodore 64s.
protected static int[][] f0_points_8580
protected int[][] f0_points
protected int f0_count
public void clock(int voice1,
int voice2,
int voice3,
int ext_in)
voice1 - voice2 - voice3 - ext_in - public void clock(int delta_t,
int voice1,
int voice2,
int voice3,
int ext_in)
delta_t - voice1 - voice2 - voice3 - ext_in - public int output()
public void enable_filter(boolean enable)
enable - public void set_chip_model(ISIDDefs.chip_model model)
model - public void reset()
public void writeFC_LO(int fc_lo)
fc_lo - public void writeFC_HI(int fc_hi)
fc_hi - public void writeRES_FILT(int res_filt)
res_filt - public void writeMODE_VOL(int mode_vol)
mode_vol - protected void set_w0()
protected void set_Q()
public void fc_default(SID.FCPoints fcp)
fcp - IN/OUT parameter points and countpublic PointPlotter fc_plotter()
protected void cubic_coefficients(double x1,
double y1,
double x2,
double y2,
double k1,
double k2,
Filter.Coefficients coeff)
x1 - y1 - x2 - y2 - k1 - k2 - coeff - protected void interpolate_brute_force(double x1,
double y1,
double x2,
double y2,
double k1,
double k2,
PointPlotter plotter,
double res)
x1 - y1 - x2 - y2 - k1 - k2 - plotter - res - protected void interpolate_forward_difference(double x1,
double y1,
double x2,
double y2,
double k1,
double k2,
PointPlotter plotter,
double res)
x1 - y1 - x2 - y2 - k1 - k2 - plotter - res - protected double x(int[][] f0_base,
int p)
protected double y(int[][] f0_base,
int p)
public void interpolate(int[][] f0_base,
int p0,
int pn,
PointPlotter plotter,
double res)
p0 - pn - plotter - res - Copyright © 2014. All rights reserved.