bw_svf

State variable filter (2nd order, 12 dB/oct) model with separated lowpass, bandpass, and highpass outputs.

Examples

Here you can download one or more example VST3 plugins for Windows, macOS and Linux. Source code of the audio engine(s) is included in the archive(s).

DescriptionLink
Second-order lowpass filter Download
Monophonic subtractive synth Download
Polyphonic subtractive synth Download
Simple monophonic subtractive synth Download
VST® is a trademark of Steinberg Media Technologies GmbH, registered in Europe and other countries.

API

Module type: DSP

bw_svf_coeffs

typedef struct bw_svf_coeffs bw_svf_coeffs;

Coefficients and related.

bw_svf_state

typedef struct bw_svf_state bw_svf_state;

Internal state and related.

bw_svf_init()

static inline void bw_svf_init(
	bw_svf_coeffs * BW_RESTRICT coeffs);

Initializes input parameter values in coeffs.

bw_svf_set_sample_rate()

static inline void bw_svf_set_sample_rate(
	bw_svf_coeffs * BW_RESTRICT coeffs,
	float                       sample_rate);

Sets the sample_rate (Hz) value in coeffs.

bw_svf_reset_coeffs()

static inline void bw_svf_reset_coeffs(
	bw_svf_coeffs * BW_RESTRICT coeffs);

Resets coefficients in coeffs to assume their target values.

bw_svf_reset_state()

static inline void bw_svf_reset_state(
	const bw_svf_coeffs * BW_RESTRICT coeffs,
	bw_svf_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.

bw_svf_reset_state_multi()

static inline void bw_svf_reset_state_multi(
	const bw_svf_coeffs * BW_RESTRICT              coeffs,
	bw_svf_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.

bw_svf_update_coeffs_ctrl()

static inline void bw_svf_update_coeffs_ctrl(
	bw_svf_coeffs * BW_RESTRICT coeffs);

Triggers control-rate update of coefficients in coeffs.

bw_svf_update_coeffs_audio()

static inline void bw_svf_update_coeffs_audio(
	bw_svf_coeffs * BW_RESTRICT coeffs);

Triggers audio-rate update of coefficients in coeffs.

bw_svf_process1()

static inline void bw_svf_process1(
	const bw_svf_coeffs * BW_RESTRICT coeffs,
	bw_svf_state * BW_RESTRICT        state,
	float                             x,
	float * BW_RESTRICT               y_lp,
	float * BW_RESTRICT               y_bp,
	float * BW_RESTRICT               y_hp);

Processes 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.

bw_svf_process()

static inline void bw_svf_process(
	bw_svf_coeffs * BW_RESTRICT coeffs,
	bw_svf_state * BW_RESTRICT  state,
	const float *               x,
	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).

bw_svf_process_multi()

static inline void bw_svf_process_multi(
	bw_svf_coeffs * BW_RESTRICT                    coeffs,
	bw_svf_state * BW_RESTRICT const * BW_RESTRICT state,
	const float * const *                          x,
	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).

y_lp, y_bp, and y_hp, or any of their elements may be BW_NULL.

bw_svf_set_cutoff()

static inline void bw_svf_set_cutoff(
	bw_svf_coeffs * BW_RESTRICT coeffs,
	float                       value);

Sets the cutoff frequency to the given value (Hz) in coeffs.

Valid range: [1e-6f, 1e12f].

Default value: 1e3f.

bw_svf_set_Q()

static inline void bw_svf_set_Q(
	bw_svf_coeffs * BW_RESTRICT coeffs,
	float                       value);

Sets the quality factor to the given value in coeffs.

Valid range: [1e-6f, 1e6f].

Default value: 0.5f.

bw_svf_set_prewarp_at_cutoff()

static inline void bw_svf_set_prewarp_at_cutoff(
	bw_svf_coeffs * BW_RESTRICT coeffs,
	char                        value);

Sets whether bilinear transform prewarping frequency should match the cutoff frequency (non-0) or not (0).

Default value: non-0 (on).

bw_svf_set_prewarp_freq()

static inline void bw_svf_set_prewarp_freq(
	bw_svf_coeffs * BW_RESTRICT coeffs,
	float                       value);

Sets the prewarping frequency value (Hz) in coeffs.

Only used when the prewarp_at_cutoff parameter is off and however internally limited to avoid instability.

Valid range: [1e-6f, 1e12f].

Default value: 1e3f.

bw_svf_coeffs_is_valid()

static inline char bw_svf_coeffs_is_valid(
	const bw_svf_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 bw_svf_coeffs.

bw_svf_state_is_valid()

static inline char bw_svf_state_is_valid(
	const bw_svf_coeffs * BW_RESTRICT coeffs,
	const bw_svf_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 bw_svf_state.

C++ wrapper

Brickworks::SVF
template<size_t N_CHANNELS>
class SVF {
public:
	SVF();

	void setSampleRate(
		float sampleRate);

	void reset(
		float               x0 = 0.f,
		float * BW_RESTRICT yLp0 = nullptr,
		float * BW_RESTRICT yBp0 = nullptr,
		float * BW_RESTRICT yHp0 = nullptr);

# 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 = nullptr,
		float *       yBp0 = nullptr,
		float *       yHp0 = nullptr);

# ifndef BW_CXX_NO_ARRAY
	void reset(
		std::array<float, N_CHANNELS>               x0,
		std::array<float, N_CHANNELS> * BW_RESTRICT yLp0 = nullptr,
		std::array<float, N_CHANNELS> * BW_RESTRICT yBp0 = nullptr,
		std::array<float, N_CHANNELS> * BW_RESTRICT yHp0 = nullptr);
# endif

	void process(
		const float * const * x,
		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<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 setQ(
		float value);

	void setPrewarpAtCutoff(
		bool value);

	void setPrewarpFreq(
		float value);
...
}

Changelog

  • Version 1.2.0:
    • Added support for BW_INCLUDE_WITH_QUOTES, BW_NO_CXX, and BW_CXX_NO_EXTERN_C.
    • Added debugging checks from bw_svf_process() to bw_svf_process_multi().
    • Added debugging checks in bw_svf_process_multi() to ensure that buffers used for both input and output appear at the same channel indices.
  • Version 1.1.0:
    • Now using BW_NULL and BW_CXX_NO_ARRAY.
  • Version 1.0.0:
    • Changed model to get positive polarity at the bandpass output.
    • Limited actual prewarping frequency to prevent instability.
    • Added bw_svf_reset_state_multi() and updated C++ API in this regard.
    • Now bw_svf_reset_state() returns the initial output values.
    • Added overloaded C++ reset() functions taking arrays as arguments.
    • bw_svf_process() and bw_svf_process_multi() now use size_t to count samples and channels.
    • Added more const and BW_RESTRICT specifiers to input arguments and implementation.
    • Moved C++ code to C header.
    • Added overloaded C++ process() function taking C-style arrays as arguments.
    • Removed usage of reserved identifiers.
    • Clearly specified parameter validity ranges.
    • Added debugging code.
  • Version 0.6.0:
    • Removed dependency on bw_config.
  • Version 0.5.0:
    • Added bw_svf_process_multi().
    • Fixed bug in bw_svf_process() when only y_hp is NULL.
    • Fixed prewarping-related stability bug.
    • Added C++ wrapper.
  • Version 0.4.0:
    • Added initial input value to bw_svf_reset_state().
    • Fixed unused parameter warnings.
  • Version 0.3.0:
    • Strenghtened algorithm for modulation.
    • Added prewarping control parameters (prewarp_at_cutoff and prewarp_freq).
    • Added BW_RESTRICT to bw_svf_process1().
    • Fixed typo in bw_svf_set_Q() documentation.
  • Version 0.2.0:
    • Refactored API.
  • Version 0.1.0:
    • First release.