Pulse oscillator waveshaper with variable pulse width (actually, duty cycle) and PolyBLEP antialiasing.
It turns a normalized phase signal, such as that geneated by bw_phase_gen, into a pulse 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,
with residual polynomials essentially corresponding to those in Table VII in
V. Valimaki and J. Pekonen, "Perceptually Informed Synthesis of Bandlimited Classical Waveforms Using Integrated Polynomial Interpolation", Journal of the Acoustical Society of America, vol. 131, no. 1, pp. 974-986, January 2012.
Version: 1.2.1
License:
Advanced versions:
Requires:
Included in Brickworks, which is:
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).
| Description | Link |
|---|---|
| Monophonic subtractive synth | Download |
| Polyphonic subtractive synth | Download |
| Simple monophonic subtractive synth | Download |

Module type: DSP
typedef struct bw_osc_pulse_coeffs bw_osc_pulse_coeffs;
Coefficients and related.
static inline void bw_osc_pulse_init(
bw_osc_pulse_coeffs * BW_RESTRICT coeffs);
Initializes input parameter values in coeffs.
static inline void bw_osc_pulse_set_sample_rate(
bw_osc_pulse_coeffs * BW_RESTRICT coeffs,
float sample_rate);
Sets the sample_rate (Hz) value in coeffs.
static inline void bw_osc_pulse_reset_coeffs(
bw_osc_pulse_coeffs * BW_RESTRICT coeffs);
Resets coefficients in coeffs to assume their target values.
static inline void bw_osc_pulse_update_coeffs_ctrl(
bw_osc_pulse_coeffs * BW_RESTRICT coeffs);
Triggers control-rate update of coefficients in coeffs.
static inline void bw_osc_pulse_update_coeffs_audio(
bw_osc_pulse_coeffs * BW_RESTRICT coeffs);
Triggers audio-rate update of coefficients in coeffs.
static inline float bw_osc_pulse_process1(
const bw_osc_pulse_coeffs * BW_RESTRICT coeffs,
float x);
static inline float bw_osc_pulse_process1_antialias(
const bw_osc_pulse_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_pulse_process1() assumes that antialiasing is disabled;bw_osc_pulse_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].
static inline void bw_osc_pulse_process(
bw_osc_pulse_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 (control and audio rate).
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].
static inline void bw_osc_pulse_process_multi(
bw_osc_pulse_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, each of the n_channels buffers pointed by x_inc must contain phase increment values, otherwise x_inc 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].
static inline void bw_osc_pulse_set_antialiasing(
bw_osc_pulse_coeffs * BW_RESTRICT coeffs,
char value);
Sets whether the antialiasing is on (value non-0) or off (0) in coeffs.
Default value: 0 (off).
static inline void bw_osc_pulse_set_pulse_width(
bw_osc_pulse_coeffs * BW_RESTRICT coeffs,
float value);
Sets the pulse width (actually, the duty cycle) to value in coeffs.
Valid range: [0.f (0% duty cycle), 1.f (100% duty cycle)].
Default value: 0.5f.
static inline char bw_osc_pulse_coeffs_is_valid(
const bw_osc_pulse_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_pulse_coeffs.
template<size_t N_CHANNELS = 1>
class OscPulse {
public:
OscPulse();
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 setPulseWidth(
float value);
...
}
N_CHANNELS in C++ API.BW_INCLUDE_WITH_QUOTES, BW_NO_CXX, and BW_CXX_NO_EXTERN_C.bw_osc_pulse_process() to bw_osc_pulse_process_multi().bw_osc_pulse_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.bw_osc_pulse_coeffs_is_valid().BW_NULL and BW_CXX_NO_ARRAY.bw_osc_pulse_process() and bw_osc_pulse_process_multi() now use size_t to count samples and channels.const specifiers to input arguments.process() function taking C-style arrays as arguments.bw_osc_pulse_process_multi().