Advanced version of bw_phase_gen with hard sync.
In addition to the usual phase and phase increment signals, this module introduces 3 hard sync-specific signals, namely:
char
, which is non-0
when a hard sync event occurs between the beginning of the current sample (included) and the beginning of the next samples (excluded);float
, which reports an estimate of the time distance, as number of samples, between the last hard sync event and the beginning of the current sample -- valid range: [0.f
, INFINITY
];float
, which reports an estimate of the time distance, as number of samples, between the beginning of the current sample and the next hard sync event -- valid range: (0.f
, INFINITY
].The presence of a "hard sync do" signal, which is always optional, implicitly indicates whether a phase generator is a hard sync master (has hard sync output), slave (has hard sync input), both, or none. A set of hard sync signals must always contain all 3 signals.
Requires:
We can privately hand you one or more example plugins if you are interested.
Module type: DSP
typedef struct bwp_phase_gen_coeffs bwp_phase_gen_coeffs;
Coefficients and related.
typedef struct bwp_phase_gen_state bwp_phase_gen_state;
Internal state and related.
static inline void bwp_phase_gen_init(
bwp_phase_gen_coeffs * BW_RESTRICT coeffs);
Initializes input parameter values in coeffs
.
static inline void bwp_phase_gen_set_sample_rate(
bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
float sample_rate);
Sets the sample_rate
(Hz) value in coeffs
.
static inline void bwp_phase_gen_reset_coeffs(
bwp_phase_gen_coeffs * BW_RESTRICT coeffs);
Resets coefficients in coeffs
to assume their target values.
static inline void bwp_phase_gen_reset_state(
const bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
bwp_phase_gen_state * BW_RESTRICT state,
float phase_0,
char is_slave,
float x_sync_low_0,
float x_sync_high_0,
float * BW_RESTRICT y_0,
float * BW_RESTRICT y_inc_0,
float * BW_RESTRICT y_sync_low_0,
float * BW_RESTRICT y_sync_high_0);
Resets the given state
to its initial values using the given coeffs
and the initial phase value phase_0
, an is_slave
flag indicating whether the phase generator is a hard sync slave, and x_sync_low_0
and x_sync_high_0
input hard sync signal initial values.
The corresponding initial output and phase increment values are put into y_0
and y_inc_0
respectively, while y_sync_low_0
and y_sync_high_0
will be filled with output hard sync signal initial values, regardless of whether the phase generator is a hard sync master or not.
phase_0
must be in [0.f
, 1.f
).
If is_slave
is 0
then x_sync_low_0
and x_sync_high_0
are ignored.
static inline void bwp_phase_gen_reset_state_multi(
const bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
bwp_phase_gen_state * BW_RESTRICT const * BW_RESTRICT state,
const float * phase_0,
const char * BW_RESTRICT is_slave,
const float * x_sync_low_0,
const float * x_sync_high_0,
float * y_0,
float * y_inc_0,
float * y_sync_low_0,
float * y_sync_high_0,
size_t n_channels);
Resets each of the n_channels
state
s to its initial values using the given coeffs
and the corresponding initial phase value in the phase_0
array, flag indicating whether the phase generator is a hard sync slave in the is_slave
array, and input hard sync signal initial values in the x_sync_low_0
and x_sync_high_0
arrays.
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
. The same goes with y_sync_low_0
and y_sync_high_0
which will be filled with output hard sync signal initial values, regardless of whether the phase generators are hard sync master or not, unless they are BW_NULL
. y_sync_low_0
must be either both BW_NULL
or both not BW_NULL
.
Values in phase_0
must be in [0.f
, 1.f
).
is_slave
may be BW_NULL
, in which case x_sync_low_0
and x_sync_high_0
are ignored. Otherwise, if any element in is_slave
is non-0
, then both x_sync_low_0
and x_sync_high_0
are required to be not BW_NULL
. Furthermore, if is_slave[i]
is 0
then x_sync_low_0[i]
and x_sync_high_0[i]
are ignored.
static inline void bwp_phase_gen_update_coeffs_ctrl(
bwp_phase_gen_coeffs * BW_RESTRICT coeffs);
Triggers control-rate update of coefficients in coeffs
.
static inline void bwp_phase_gen_update_coeffs_audio(
bwp_phase_gen_coeffs * BW_RESTRICT coeffs);
Triggers audio-rate update of coefficients in coeffs
.
static inline void bwp_phase_gen_process1(
const bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
bwp_phase_gen_state * BW_RESTRICT state,
float * BW_RESTRICT y,
float * BW_RESTRICT y_inc);
static inline void bwp_phase_gen_process1_mod(
const bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
bwp_phase_gen_state * BW_RESTRICT state,
float x_mod,
float * BW_RESTRICT y,
float * BW_RESTRICT y_inc);
static inline void bwp_phase_gen_process1_slave(
const bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
bwp_phase_gen_state * BW_RESTRICT state,
char x_sync_do,
float x_sync_low,
float x_sync_high,
float * BW_RESTRICT y,
float * BW_RESTRICT y_inc);
static inline void bwp_phase_gen_process1_slave_mod(
const bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
bwp_phase_gen_state * BW_RESTRICT state,
float x_mod,
char x_sync_do,
float x_sync_low,
float x_sync_high,
float * BW_RESTRICT y,
float * BW_RESTRICT y_inc);
static inline void bwp_phase_gen_process1_master(
const bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
bwp_phase_gen_state * BW_RESTRICT state,
float * BW_RESTRICT y,
float * BW_RESTRICT y_inc,
char * BW_RESTRICT y_sync_do,
float * BW_RESTRICT y_sync_low,
float * BW_RESTRICT y_sync_high);
static inline void bwp_phase_gen_process1_master_mod(
const bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
bwp_phase_gen_state * BW_RESTRICT state,
float x_mod,
float * BW_RESTRICT y,
float * BW_RESTRICT y_inc,
char * BW_RESTRICT y_sync_do,
float * BW_RESTRICT y_sync_low,
float * BW_RESTRICT y_sync_high);
static inline void bwp_phase_gen_process1_master_slave(
const bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
bwp_phase_gen_state * BW_RESTRICT state,
char x_sync_do,
float x_sync_low,
float x_sync_high,
float * BW_RESTRICT y,
float * BW_RESTRICT y_inc,
char * BW_RESTRICT y_sync_do,
float * BW_RESTRICT y_sync_low,
float * BW_RESTRICT y_sync_high);
static inline void bwp_phase_gen_process1_master_slave_mod(
const bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
bwp_phase_gen_state * BW_RESTRICT state,
float x_mod,
char x_sync_do,
float x_sync_low,
float x_sync_high,
float * BW_RESTRICT y,
float * BW_RESTRICT y_inc,
char * BW_RESTRICT y_sync_do,
float * BW_RESTRICT y_sync_low,
float * BW_RESTRICT y_sync_high);
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:
bwp_phase_gen_process1()
does not apply frequency modulation, with the phase generator operating neither as hard sync slave nor master;bwp_phase_gen_process1_mod()
applies exponential frequency modulation using x_mod
as modulation input, with the phase generator operating neither as hard sync slave nor master;bwp_phase_gen_process1_slave()
does not apply frequency modulation, with the phase generator operating as hard sync slave but not master, where x_sync_do
, x_sync_low
, and x_sync_high
are the input hard sync signals;bwp_phase_gen_process1_slave_mod()
is like bwp_phase_gen_process1_slave()
but applying exponential frequency modulation using x_mod
as modulation input;bwp_phase_gen_process1_master()
does not apply frequency modulation, with the phase generator operating as hard sync master but not slave, where y_sync_do
, y_sync_low
, and y_sync_high
are the output hard sync signals;bwp_phase_gen_process1_master_mod()
is like bwp_phase_gen_process1_master()
but applying exponential frequency modulation using x_mod
as modulation input;bwp_phase_gen_process1_master_slave()
does not apply frequency modulation, with the phase generator operating both as hard sync master and slave, x_sync_do
, x_sync_low
, and x_sync_high
are the input hard sync signals, and y_sync_do
, y_sync_low
, and y_sync_high
are the output hard sync signals;bwp_phase_gen_process1_master_slave_mod()
is like bwp_phase_gen_process1_master_slave()
but applying exponential frequency modulation using x_mod
as modulation input.The modulation scale for x_mod
is 1.f
/octave.
x_sync_low
and x_sync_high
are ignored if x_sync_do
is 0
.
static inline void bwp_phase_gen_process(
bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
bwp_phase_gen_state * BW_RESTRICT state,
const float * x_mod,
const char * x_sync_do,
const float * x_sync_low,
const float * x_sync_high,
float * y,
float * y_inc,
char * y_sync_do,
float * y_sync_low,
float * y_sync_high,
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 x_sync_do
is not BW_NULL
, x_sync_low
and x_sync_high
must point to different buffers. These buffers represent input hard sync signals.
If y_inc
is not BW_NULL
, it is filled with phase increment values.
If y_sync_do
is not BW_NULL
, y_sync_low
and y_sync_high
must not be BW_NULL
either. These buffers will be filled with output hard sync signals.
static inline void bwp_phase_gen_process_multi(
bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
bwp_phase_gen_state * BW_RESTRICT const * BW_RESTRICT state,
const float * const * x_mod,
const char * const * x_sync_do,
const float * const * x_sync_low,
const float * const * x_sync_high,
float * const * y,
float * const * y_inc,
char * const * y_sync_do,
float * const * y_sync_low,
float * const * y_sync_high,
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
state
s (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 x_sync_do
is not BW_NULL
, x_sync_low
and x_sync_high
must point to different arrays. Then, if x_sync_do[i]
is not BW_NULL
, x_sync_low[i]
and x_sync_high[i]
must point to different buffers. These buffers represent input hard sync signals.
If y_inc
and the channel-specific element are not BW_NULL
, this is filled with phase increment values for that channel.
If y_sync_do
is not BW_NULL
, y_sync_low
and y_sync_high
must point to different arrays. Then, if y_sync_do[i]
is not BW_NULL
, y_sync_low[i]
and y_sync_high[i]
must point to different buffers. These buffers will be filled with output hard sync signals.
static inline void bwp_phase_gen_set_frequency(
bwp_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
.
static inline void bwp_phase_gen_set_sync_phase(
bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
float value);
Sets which value
the phase assumes immediately after a hard sync event when the phase generator is operating as a hard sync slave.
Valid range: [0.f
, 1.f
).
Default value: 0.f
.
static inline void bwp_phase_gen_set_portamento_tau(
bwp_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
.
static inline void bwp_phase_gen_set_phase_inc_min(
bwp_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 bwp_phase_gen_reset_\*()
, bwp_phase_gen_update_coeffs_\*()
, or bwp_peak_process\*()
is called, phase_inc_min must be less than phase_inc_max.
Default value: -INFINITY
.
static inline void bwp_phase_gen_set_phase_inc_max(
bwp_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 bwp_phase_gen_reset_\*()
, bwp_phase_gen_update_coeffs_\*()
, or bwp_peak_process\*()
is called, phase_inc_min must be less than phase_inc_max.
Default value: INFINITY
.
static inline char bwp_phase_gen_coeffs_is_valid(
const bwp_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 bwp_phase_gen_coeffs
.
static inline char bwp_phase_gen_state_is_valid(
const bwp_phase_gen_coeffs * BW_RESTRICT coeffs,
const bwp_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 bwp_phase_gen_state
.
template<size_t N_CHANNELS>
class PhaseGen {
public:
PhaseGen();
void setSampleRate(
float sampleRate);
void reset(
float phase0 = 0.f,
char isSlave = 0,
float xSyncLow0 = 0.f,
float xSyncHigh0 = 0.f,
float * BW_RESTRICT y0 = BW_NULL,
float * BW_RESTRICT yInc0 = BW_NULL,
float * BW_RESTRICT ySyncLow0 = BW_NULL,
float * BW_RESTRICT ySyncHigh0 = BW_NULL);
# ifndef BW_CXX_NO_ARRAY
void reset(
float phase0,
char isSlave,
float xSyncLow0,
float xSyncHigh0,
std::array<float, N_CHANNELS> * BW_RESTRICT y0,
std::array<float, N_CHANNELS> * BW_RESTRICT yInc0,
std::array<float, N_CHANNELS> * BW_RESTRICT ySyncLow0,
std::array<float, N_CHANNELS> * BW_RESTRICT ySyncHigh0);
# endif
void reset(
const float * phase0,
const char * BW_RESTRICT isSlave,
const float * xSyncLow0,
const float * xSyncHigh0,
float * y0 = BW_NULL,
float * yInc0 = BW_NULL,
float * ySyncLow0 = BW_NULL,
float * ySyncHigh0 = BW_NULL);
# ifndef BW_CXX_NO_ARRAY
void reset(
std::array<float, N_CHANNELS> phase0,
std::array<char, N_CHANNELS> isSlave,
std::array<float, N_CHANNELS> xSyncLow0,
std::array<float, N_CHANNELS> xSyncHigh0,
std::array<float, N_CHANNELS> * BW_RESTRICT y0 = BW_NULL,
std::array<float, N_CHANNELS> * BW_RESTRICT yInc0 = BW_NULL,
std::array<float, N_CHANNELS> * BW_RESTRICT ySyncLow0 = BW_NULL,
std::array<float, N_CHANNELS> * BW_RESTRICT ySyncHigh0 = BW_NULL);
# endif
void process(
const float * const * xMod,
const char * const * xSyncDo,
const float * const * xSyncLow,
const float * const * xSyncHigh,
float * const * y,
float * const * yInc,
char * const * ySyncDo,
float * const * ySyncLow,
float * const * ySyncHigh,
size_t nSamples);
# ifndef BW_CXX_NO_ARRAY
void process(
std::array<const float *, N_CHANNELS> xMod,
std::array<const char *, N_CHANNELS> xSyncDo,
std::array<const float *, N_CHANNELS> xSyncLow,
std::array<const float *, N_CHANNELS> xSyncHigh,
std::array<float *, N_CHANNELS> y,
std::array<float *, N_CHANNELS> yInc,
std::array<char *, N_CHANNELS> ySyncDo,
std::array<float *, N_CHANNELS> ySyncLow,
std::array<float *, N_CHANNELS> ySyncHigh,
size_t nSamples);
# endif
void setFrequency(
float value);
void setSyncPhase(
float value);
void setPortamentoTau(
float value);
void setPhaseIncMin(
float value);
void setPhaseIncMax(
float value);
...
}
BW_NULL
in the C++ API and implementation.