bw_osc_tri

Triangle oscillator waveshaper with variable slope (increasing time over period) and PolyBLEP antialiasing.

It turns a normalized phase signal, such as that geneated by bw_phase_gen, into a triangle wave.

The antialiasing algorithm is based on

V. Valimaki and A. Huovilainen, "Antialiasing Oscillators in Subtractive Synthesis", IEEE Signal Processing Magazine, vol. 24, no. 2, pp. 116-125, March 2007.

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
Monophonic subtractive synth Download
Polyphonic subtractive synth Download
VST® is a trademark of Steinberg Media Technologies GmbH, registered in Europe and other countries.

API

Module type: DSP

bw_osc_tri_coeffs

typedef struct bw_osc_tri_coeffs bw_osc_tri_coeffs;

Coefficients and related.

bw_osc_tri_init()

static inline void bw_osc_tri_init(
	bw_osc_tri_coeffs * BW_RESTRICT coeffs);

Initializes input parameter values in coeffs.

bw_osc_tri_set_sample_rate()

static inline void bw_osc_tri_set_sample_rate(
	bw_osc_tri_coeffs * BW_RESTRICT coeffs,
	float                           sample_rate);

Sets the sample_rate (Hz) value in coeffs.

bw_osc_tri_reset_coeffs()

static inline void bw_osc_tri_reset_coeffs(
	bw_osc_tri_coeffs * BW_RESTRICT coeffs);

Resets coefficients in coeffs to assume their target values.

bw_osc_tri_update_coeffs_ctrl()

static inline void bw_osc_tri_update_coeffs_ctrl(
	bw_osc_tri_coeffs * BW_RESTRICT coeffs);

Triggers control-rate update of coefficients in coeffs.

bw_osc_tri_update_coeffs_audio()

static inline void bw_osc_tri_update_coeffs_audio(
	bw_osc_tri_coeffs * BW_RESTRICT coeffs);

Triggers audio-rate update of coefficients in coeffs.

bw_osc_tri_process1*()

static inline float bw_osc_tri_process1(
	const bw_osc_tri_coeffs * BW_RESTRICT coeffs,
	float                                 x);

static inline float bw_osc_tri_process1_antialias(
	const bw_osc_tri_coeffs * BW_RESTRICT coeffs,
	float                                 x,
	float                                 x_inc);

These function process one input sample x, representing the normalized phase, using coeffs. They return the corresponding output sample.

In particular:

  • bw_osc_tri_process1() assumes that antialiasing is disabled;
  • bw_osc_tri_process1_antialias() assumes that antialiasing is enabled and requires the corresponding phase increment value to be passed via x_inc.

Whether antialiasing is enabled or not is unchecked even for debugging purposes.

x must be in [0.f, 1.f).

x_inc must be in [-0.5f, 0.5f].

bw_osc_tri_process()

static inline void bw_osc_tri_process(
	bw_osc_tri_coeffs * BW_RESTRICT coeffs,
	const float *                   x,
	const float *                   x_inc,
	float *                         y,
	size_t                          n_samples);

Processes the first n_samples of the input buffer x, containing the normalized phase signal, and fills the first n_samples of the output buffer y, while using and updating coeffs.

If antialiasing is enabled, x_inc must contain phase increment values, otherwise it is ignored and can be BW_NULL.

All samples in x must be in [0.f, 1.f).

All samples is x_inc, if not ignored, must be in [-0.5f, 0.5f].

bw_osc_tri_process_multi()

static inline void bw_osc_tri_process_multi(
	bw_osc_tri_coeffs * BW_RESTRICT coeffs,
	const float * const *           x,
	const float * const *           x_inc,
	float * const *                 y,
	size_t                          n_channels,
	size_t                          n_samples);

Processes the first n_samples of the n_channels input buffers x, containing the normalized phase signals, and fills the first n_samples of the n_channels output buffers y, while using and updating the common coeffs (control and audio rate).

If antialiasing is enabled, x_inc must contain n_channels buffers of phase increment values, otherwise it is ignored and can be BW_NULL.

All samples in x must be in [0.f, 1.f).

All samples is x_inc, if not ignored, must be in [-0.5f, 0.5f].

bw_osc_tri_set_antialiasing()

static inline void bw_osc_tri_set_antialiasing(
	bw_osc_tri_coeffs * BW_RESTRICT coeffs,
	char                            value);

Sets whether the antialiasing is on (value non-0) or off (0) in coeffs.

Default value: 0 (off).

bw_osc_tri_set_slope()

static inline void bw_osc_tri_set_slope(
	bw_osc_tri_coeffs * BW_RESTRICT coeffs,
	float                           value);

Sets the slope (increasing time over period) to value in coeffs.

Valid range: [0.001f, 0.999f].

Default value: 0.5f.

bw_osc_tri_coeffs_is_valid()

static inline char bw_osc_tri_coeffs_is_valid(
	const bw_osc_tri_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_osc_tri_coeffs.

C++ wrapper

Brickworks::OscTri
template<size_t N_CHANNELS>
class OscTri {
public:
	OscTri();
	
	void setSampleRate(
		float sampleRate);

	void reset();

	void process(
		const float * const * x,
		const float * const * xInc,
		float * const *       y,
		size_t                nSamples);

# ifndef BW_CXX_NO_ARRAY
	void process(
		std::array<const float *, N_CHANNELS> x,
		std::array<const float *, N_CHANNELS> xInc,
		std::array<float *, N_CHANNELS>       y,
		size_t                                nSamples);
# endif
	
	void setAntialiasing(
		bool value);

	void setSlope(
		float value);
...
}

Changelog

  • Version 1.2.1:
    • Fixed typo in 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_osc_tri_process() to bw_osc_tri_process_multi().
    • Added debugging checks in bw_osc_tri_process_multi() to ensure that x_inc is not BW_NULL when antialiasing is on and that buffers used for both input and output appear at the same channel indices.
    • Added extra checks in bw_osc_tri_coeffs_is_valid().
    • Changed the name of C++ arguments to camel case.
  • Version 1.1.0:
    • Now using BW_NULL and BW_CXX_NO_ARRAY.
  • Version 1.0.0:
    • bw_osc_tri_process() and bw_osc_tri_process_multi() now use size_t to count samples and channels.
    • Added more const specifiers to input arguments.
    • Moved C++ code to C header.
    • Added overloaded C++ process() function taking C-style arrays as arguments.
    • Now antialiasing should work also with negative input increments.
    • Removed usage of reserved identifiers.
    • Clearly specified validity ranges for audio-rate signals.
    • Added debugging code.
  • Version 0.6.0:
    • Removed dependency on bw_config.
  • Version 0.5.0:
    • Added bw_osc_tri_process_multi().
    • Fixed typo in bw_osc_tri_process1*() documentation.
    • Added C++ wrapper.
  • Version 0.4.0:
    • Fixed unused parameter warnings.
  • Version 0.2.0:
    • Refactored API.
  • Version 0.1.0:
    • First release.