Digital model of the MOS Technology®/Commodore® Semiconductor Group 8580 Sound Interface Device (SID) filter with separated outputs.
The bandpass output is phase-inverted, as in the original device. Also, please note that in the original device the bypassed output (not implemented here) is also phase-inverted and its gain may be slightly different from other filter outputs (theoretically about 0.6 dB lower).
The cutoff and resonance parameter values correspond to those on the original chip, extended to "continuous" ranges. They both implement modulation as detailed in bwp_mod_func. Modulations are however internally limited to avoid instability.
Version: 1.0.0
License: proprietary license
We can privately hand you one or more example plugins if you are interested.
Module type: DSP
typedef struct bwp_sid_8580_filt_coeffs bwp_sid_8580_filt_coeffs;
Coefficients and related.
typedef struct bwp_sid_8580_filt_state bwp_sid_8580_filt_state;
Internal state and related.
static inline void bwp_sid_8580_filt_init(
bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs);
Initializes input parameter values in coeffs.
static inline void bwp_sid_8580_filt_set_sample_rate(
bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
float sample_rate);
Sets the sample_rate (Hz) value in coeffs.
static inline void bwp_sid_8580_filt_reset_coeffs(
bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs);
Resets coefficients in coeffs to assume their target values.
static inline void bwp_sid_8580_filt_reset_state(
const bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
bwp_sid_8580_filt_state * BW_RESTRICT state,
float x_0,
float * BW_RESTRICT y_lp_0,
float * BW_RESTRICT y_bp_0,
float * BW_RESTRICT y_hp_0);
Resets the given state to its initial values using the given coeffs and the initial input value x_0.
The corresponding initial lowpass, bandpass, and highpass output values are put into y_lp_0, y_bp_0, and y_hp_0 respectively.
static inline void bwp_sid_8580_filt_reset_state_multi(
const bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
bwp_sid_8580_filt_state * BW_RESTRICT const * BW_RESTRICT state,
const float * x_0,
float * y_lp_0,
float * y_bp_0,
float * y_hp_0,
size_t n_channels);
Resets each of the n_channels states to its initial values using the given coeffs and the corresponding initial input value in the x_0 array.
The corresponding initial lowpass, bandpass, and highpass output values are put into the y_lp_0, y_bp_0, and y_hp_0 arrays, respectively, if they are not BW_NULL.
static inline void bwp_sid_8580_filt_update_coeffs_ctrl(
bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs);
Triggers control-rate update of coefficients in coeffs.
static inline void bwp_sid_8580_filt_update_coeffs_audio(
bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs);
Triggers audio-rate update of coefficients in coeffs.
static inline void bwp_sid_8580_filt_process1(
const bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
bwp_sid_8580_filt_state * BW_RESTRICT state,
float x,
float * BW_RESTRICT y_lp,
float * BW_RESTRICT y_bp,
float * BW_RESTRICT y_hp);
static inline void bwp_sid_8580_filt_process1_mod_cutoff(
const bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
bwp_sid_8580_filt_state * BW_RESTRICT state,
float x,
float x_mod_cutoff,
float * BW_RESTRICT y_lp,
float * BW_RESTRICT y_bp,
float * BW_RESTRICT y_hp);
static inline void bwp_sid_8580_filt_process1_mod_resonance(
const bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
bwp_sid_8580_filt_state * BW_RESTRICT state,
float x,
float x_mod_resonance,
float * BW_RESTRICT y_lp,
float * BW_RESTRICT y_bp,
float * BW_RESTRICT y_hp);
static inline void bwp_sid_8580_filt_process1_mod_cutoff_resonance(
const bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
bwp_sid_8580_filt_state * BW_RESTRICT state,
float x,
float x_mod_cutoff,
float x_mod_resonance,
float * BW_RESTRICT y_lp,
float * BW_RESTRICT y_bp,
float * BW_RESTRICT y_hp);
These functions process one input sample x using coeffs, while using and updating state. The lowpass, bandpass, and highpass output samples are put into y_lp, y_bp, and y_hp respectively.
They take various combinations of audio-rate modulation signals as input, namely x_mod_cutoff and x_mod_resonance.
static inline void bwp_sid_8580_filt_process(
bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
bwp_sid_8580_filt_state * BW_RESTRICT state,
const float * x,
const float * x_mod_cutoff,
const float * x_mod_resonance,
float * y_lp,
float * y_bp,
float * y_hp,
size_t n_samples);
Processes the first n_samples of the input buffer x and fills the first n_samples of the output buffers y_lp (lowpass), y_bp (bandpass), and y_hp (highpass), if they are not BW_NULL, while using and updating both coeffs and state (control and audio rate).
If x_mod_cutoff is not BW_NULL, it is used as a source of cutoff frequency modulation. The same holds for x_mod_resonance w.r.t. resonance modulation.
static inline void bwp_sid_8580_filt_process_multi(
bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
bwp_sid_8580_filt_state * BW_RESTRICT const * BW_RESTRICT state,
const float * const * x,
const float * const * x_mod_cutoff,
const float * const * x_mod_resonance,
float * const * y_lp,
float * const * y_bp,
float * const * y_hp,
size_t n_channels,
size_t n_samples);
Processes the first n_samples of the n_channels input buffers x and fills the first n_samples of the n_channels output buffers y_lp (lowpass), y_bp (bandpass), and y_hp (highpass), while using and updating both the common coeffs and each of the n_channels states (control and audio rate).
If x_mod_cutoff and the channel-specific element are not BW_NULL, this is used as a source of cutoff frequency modulation for that channel. The same hold for x_mod_resonance w.r.t.resonance modulation.
y_lp, y_bp, and y_hp, or any of their elements may be BW_NULL.
static inline void bwp_sid_8580_filt_set_cutoff(
bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
float value);
Sets the cutoff frequency to the given value in coeffs.
Valid range: [0.f, 2047.f].
Default value: 2047.f.
static inline void bwp_sid_8580_filt_set_cutoff_mod(
bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
float value);
Sets the non-smoothed cutoff frequency modulation component to the given value in coeffs.
value must be finite.
Default value: 0.f.
static inline void bwp_sid_8580_filt_set_resonance(
bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
float value);
Sets the resonance to the given value in coeffs.
Valid range: [0.f, 15.f].
Default value: 0.f.
static inline void bwp_sid_8580_filt_set_resonance_mod(
bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
float value);
Sets the non-smoothed resonance modulation component to the given value in coeffs.
value must be finite.
Default value: 0.f.
static inline void bwp_sid_8580_filt_set_mod_func_cutoff(
bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
bwp_mod_func value);
Sets the cutoff frequency modulation function.
Default value: bwp_mod_func_sum.
static inline void bwp_sid_8580_filt_set_mod_func_resonance(
bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
bwp_mod_func value);
Sets the resonance modulation function.
Default value: bwp_mod_func_sum.
static inline char bwp_sid_8580_filt_coeffs_is_valid(
const bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs);
Tries to determine whether coeffs is valid and returns non-0 if it seems to be the case and 0 if it is certainly not. False positives are possible, false negatives are not.
coeffs must at least point to a readable memory block of size greater than or equal to that of bwp_sid_8580_filt_coeffs.
static inline char bwp_sid_8580_filt_state_is_valid(
const bwp_sid_8580_filt_coeffs * BW_RESTRICT coeffs,
const bwp_sid_8580_filt_state * BW_RESTRICT state);
Tries to determine whether state is valid and returns non-0 if it seems to be the case and 0 if it is certainly not. False positives are possible, false negatives are not.
If coeffs is not BW_NULL extra cross-checks might be performed (state is supposed to be associated to coeffs).
state must at least point to a readable memory block of size greater than or equal to that of bwp_sid_8580_filt_state.
template<size_t N_CHANNELS = 1>
class SID8580Filt {
public:
SID8580Filt();
void setSampleRate(
float sampleRate);
void reset(
float x0 = 0.f,
float * BW_RESTRICT yLp0 = BW_NULL,
float * BW_RESTRICT yBp0 = BW_NULL,
float * BW_RESTRICT yHp0 = BW_NULL);
# ifndef BW_CXX_NO_ARRAY
void reset(
float x0,
std::array<float, N_CHANNELS> * BW_RESTRICT yLp0,
std::array<float, N_CHANNELS> * BW_RESTRICT yBp0,
std::array<float, N_CHANNELS> * BW_RESTRICT yHp0);
# endif
void reset(
const float * x0,
float * yLp0 = BW_NULL,
float * yBp0 = BW_NULL,
float * yHp0 = BW_NULL);
# ifndef BW_CXX_NO_ARRAY
void reset(
std::array<float, N_CHANNELS> x0,
std::array<float, N_CHANNELS> * BW_RESTRICT yLp0 = BW_NULL,
std::array<float, N_CHANNELS> * BW_RESTRICT yBp0 = BW_NULL,
std::array<float, N_CHANNELS> * BW_RESTRICT yHp0 = BW_NULL);
# endif
void process(
const float * const * x,
const float * const * xModCutoff,
const float * const * xModResonance,
float * const * yLp,
float * const * yBp,
float * const * yHp,
size_t nSamples);
# ifndef BW_CXX_NO_ARRAY
void process(
std::array<const float *, N_CHANNELS> x,
std::array<const float *, N_CHANNELS> xModCutoff,
std::array<const float *, N_CHANNELS> xModResonance,
std::array<float *, N_CHANNELS> yLp,
std::array<float *, N_CHANNELS> yBp,
std::array<float *, N_CHANNELS> yHp,
size_t nSamples);
# endif
void setCutoff(
float value);
void setCutoffMod(
float value);
void setResonance(
float value);
void setResonanceMod(
float value);
void setModFuncCutoff(
bwp_mod_func value);
void setModFuncResonance(
bwp_mod_func value);
...
}