bw_phase_gen

Phase generator with portamento and exponential frequency modulation.

It outputs a normalized phase signal (range [0.f, 1.f)).

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
Ring modulator 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_phase_gen_coeffs

typedef struct bw_phase_gen_coeffs bw_phase_gen_coeffs;

Coefficients and related.

bw_phase_gen_state

typedef struct bw_phase_gen_state bw_phase_gen_state;

Internal state and related.

bw_phase_gen_init()

static inline void bw_phase_gen_init(
	bw_phase_gen_coeffs * BW_RESTRICT coeffs);

Initializes input parameter values in coeffs.

bw_phase_gen_set_sample_rate()

static inline void bw_phase_gen_set_sample_rate(
	bw_phase_gen_coeffs * BW_RESTRICT coeffs,
	float                             sample_rate);

Sets the sample_rate (Hz) value in coeffs.

bw_phase_gen_reset_coeffs()

static inline void bw_phase_gen_reset_coeffs(
	bw_phase_gen_coeffs * BW_RESTRICT coeffs);

Resets coefficients in coeffs to assume their target values.

bw_phase_gen_reset_state()

static inline void bw_phase_gen_reset_state(
	const bw_phase_gen_coeffs * BW_RESTRICT coeffs,
	bw_phase_gen_state * BW_RESTRICT        state,
	float                                   phase_0,
	float * BW_RESTRICT                     y_0,
	float * BW_RESTRICT                     y_inc_0);

Resets the given state to its initial values using the given coeffs and the initial phase value phase_0.

The corresponding initial output and phase increment values are put into y_0 and y_inc_0 respectively.

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

bw_phase_gen_reset_state_multi()

static inline void bw_phase_gen_reset_state_multi(
	const bw_phase_gen_coeffs * BW_RESTRICT              coeffs,
	bw_phase_gen_state * BW_RESTRICT const * BW_RESTRICT state,
	const float *                                        phase_0,
	float *                                              y_0,
	float *                                              y_inc_0,
	size_t                                               n_channels);

Resets each of the n_channels states to its initial values using the given coeffs and the corresponding initial phase value in the phase_0 array.

The corresponding initial output and phase increment values are put into the y_0 and y_inc_0 arrays, respectively, if they are not BW_NULL.

Values in phase_0 must be in [0.f, 1.f).

bw_phase_gen_update_coeffs_ctrl()

static inline void bw_phase_gen_update_coeffs_ctrl(
	bw_phase_gen_coeffs * BW_RESTRICT coeffs);

Triggers control-rate update of coefficients in coeffs.

bw_phase_gen_update_coeffs_audio()

static inline void bw_phase_gen_update_coeffs_audio(
	bw_phase_gen_coeffs * BW_RESTRICT coeffs);

Triggers audio-rate update of coefficients in coeffs.

bw_phase_gen_process1*()

static inline void bw_phase_gen_process1(
	const bw_phase_gen_coeffs * BW_RESTRICT coeffs,
	bw_phase_gen_state * BW_RESTRICT        state,
	float * BW_RESTRICT                     y,
	float * BW_RESTRICT                     y_inc);

static inline void bw_phase_gen_process1_mod(
	const bw_phase_gen_coeffs * BW_RESTRICT coeffs,
	bw_phase_gen_state * BW_RESTRICT        state,
	float                                   x_mod,
	float * BW_RESTRICT                     y,
	float * BW_RESTRICT                     y_inc);

These functions generate one output sample using coeffs, while using and updating state, putting its value in y and the corresponding phase increment value in y_inc.

In particular:

  • bw_phase_gen_process1() does not apply frequency modulation;
  • bw_phase_gen_process1_mod() applies exponential frequency modulation using x_mod as modulation input (scale 1.f/octave).

bw_phase_gen_process()

static inline void bw_phase_gen_process(
	bw_phase_gen_coeffs * BW_RESTRICT coeffs,
	bw_phase_gen_state * BW_RESTRICT  state,
	const float *                     x_mod,
	float *                           y,
	float *                           y_inc,
	size_t                            n_samples);

Generates and fills the first n_samples of the output buffer y, while using and updating both coeffs and state (control and audio rate).

If x_mod is not BW_NULL, it is used as a source of exponential frequency modulation (scale 1.f/octave).

If y_inc is not BW_NULL, it is filled with phase increment values.

bw_phase_gen_process_multi()

static inline void bw_phase_gen_process_multi(
	bw_phase_gen_coeffs * BW_RESTRICT                    coeffs,
	bw_phase_gen_state * BW_RESTRICT const * BW_RESTRICT state,
	const float * const *                                x_mod,
	float * const *                                      y,
	float * const *                                      y_inc,
	size_t                                               n_channels,
	size_t                                               n_samples);

Generates and fills the first n_samples of the n_channels output buffers y, while using and updating both the common coeffs and each of the n_channels states (control and audio rate).

If x_mod and the channel-specific element are not BW_NULL, this is used as a source of exponential frequency modulation (scale 1.f/octave) for that channel.

If y_inc and the channel-specific element are not BW_NULL, this is filled with phase increment values for that channel.

bw_phase_gen_set_frequency()

static inline void bw_phase_gen_set_frequency(
	bw_phase_gen_coeffs * BW_RESTRICT coeffs,
	float                             value);

Sets the base frequency to value (Hz) in coeffs.

value must be finite.

Default value: 1.f.

bw_phase_gen_set_portamento_tau()

static inline void bw_phase_gen_set_portamento_tau(
	bw_phase_gen_coeffs * BW_RESTRICT coeffs,
	float                             value);

Sets the portamento time constant value (s) in coeffs.

value must be non-negative.

Default value: 0.f.

bw_phase_gen_set_phase_inc_min()

static inline void bw_phase_gen_set_phase_inc_min(
	bw_phase_gen_coeffs * BW_RESTRICT coeffs,
	float                             value);

Sets the minimum phase increment value in coeffs.

The algorithm will limit the actual phase increment accordingly, yet if the magnitude of the resulting phase increment is less than 6e-8f, it will be rounded to 0.f and such value will be reported by processing functions.

Valid range: [-INFINITY, INFINITY).

By the time bw_phase_gen_reset_\*(), bw_phase_gen_update_coeffs_\*(), or bw_peak_process\*() is called, phase_inc_min must be less than phase_inc_max.

Default value: -INFINITY.

bw_phase_gen_set_phase_inc_max()

static inline void bw_phase_gen_set_phase_inc_max(
	bw_phase_gen_coeffs * BW_RESTRICT coeffs,
	float                             value);

Sets the maximum phase increment value in coeffs.

The algorithm will limit the actual phase increment accordingly, yet if the magnitude of the resulting phase increment is less than 6e-8f, it will be rounded to 0.f and such value will be reported by processing functions.

Valid range: (-INFINITY, INFINITY].

By the time bw_phase_gen_reset_\*(), bw_phase_gen_update_coeffs_\*(), or bw_peak_process\*() is called, phase_inc_min must be less than phase_inc_max.

Default value: INFINITY.

bw_phase_gen_coeffs_is_valid()

static inline char bw_phase_gen_coeffs_is_valid(
	const bw_phase_gen_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_phase_gen_coeffs.

bw_phase_gen_state_is_valid()

static inline char bw_phase_gen_state_is_valid(
	const bw_phase_gen_coeffs * BW_RESTRICT coeffs,
	const bw_phase_gen_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_phase_gen_state.

C++ wrapper

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

	void setSampleRate(
		float sampleRate);

	void reset(
		float               phase0 = 0.f,
		float * BW_RESTRICT y0 = nullptr,
		float * BW_RESTRICT yInc0 = nullptr);

# ifndef BW_CXX_NO_ARRAY
	void reset(
		float                                       phase0,
		std::array<float, N_CHANNELS> * BW_RESTRICT y0,
		std::array<float, N_CHANNELS> * BW_RESTRICT yInc0);
# endif

	void reset(
		const float * phase0,
		float *       y0 = nullptr,
		float *       yInc0 = nullptr);

# ifndef BW_CXX_NO_ARRAY
	void reset(
		std::array<float, N_CHANNELS>               phase0,
		std::array<float, N_CHANNELS> * BW_RESTRICT y0 = nullptr,
		std::array<float, N_CHANNELS> * BW_RESTRICT yInc0 = nullptr);
# endif

	void process(
		const float * const * xMod,
		float * const *       y,
		float * const *       yInc,
		size_t                nSamples);

# ifndef BW_CXX_NO_ARRAY
	void process(
		std::array<const float *, N_CHANNELS> xMod,
		std::array<float *, N_CHANNELS>       y,
		std::array<float *, N_CHANNELS>       yInc,
		size_t                                nSamples);
# endif

	void setFrequency(
		float value);

	void setPortamentoTau(
		float value);

	void setPhaseIncMin(
		float value);

	void setPhaseIncMax(
		float value);
...
}

Changelog

  • Version 1.2.0:
    • Added phase_inc_min and phase_inc_max parameters.
    • Added support for BW_INCLUDE_WITH_QUOTES, BW_NO_CXX, and BW_CXX_NO_EXTERN_C.
    • Fixed rounding bug when frequency is tiny (again).
    • Added debugging checks from bw_phase_gen_process() to bw_phase_gen_process_multi().
    • Added debugging check in bw_phase_reset_state() to ensure that phase_0 is in [0.f, 1.f) and indicated such range in the documentation.
    • Added debugging checks in bw_phase_gen_process_multi() to ensure that buffers used for both input and output appear at the same channel indices.
    • Fixed bug in bw_phase_gen_process_multi() by which debugging code could report false negatives when BW_NULL buffers are used.
    • Fixed typo in the module description regarding output range.
  • Version 1.1.0:
    • Fixed rounding bug when frequency is tiny and negative.
    • Now using BW_NULL and BW_CXX_NO_ARRAY.
  • Version 1.0.0:
    • Added initial input value to bw_phase_gen_reset_state().
    • Added bw_phase_gen_reset_state_multi() and updated C++ API in this regard.
    • Now bw_phase_gen_reset_state() returns the initial output values.
    • Added overloaded C++ reset() functions taking arrays as arguments.
    • bw_phase_gen_process() and bw_phase_gen_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.
    • Fixed smoothing coefficients update in bw_phase_gen_reset_coeffs().
    • 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_phase_gen_process_multi().
    • Added C++ wrapper.
  • Version 0.4.0:
    • Fixed unused parameter warnings.
  • Version 0.3.0:
    • Added BW_RESTRICT to bw_phase_gen_process1*().
  • Version 0.2.0:
    • Refactored API.
  • Version 0.1.0:
    • First release.