ported bw_osc_saw to new API and simplified bw_osc_pulse API
This commit is contained in:
parent
6b4b0a3429
commit
abc87a99a3
@ -27,6 +27,7 @@
|
||||
|
||||
#include <bw_math.h>
|
||||
#include <bw_phase_gen.h>
|
||||
#include <bw_osc_saw.h>
|
||||
#include <bw_osc_pulse.h>
|
||||
#include <bw_osc_filt.h>
|
||||
#include <bw_noise_gen.h>
|
||||
@ -61,7 +62,6 @@ struct _bw_example_synth {
|
||||
bw_phase_gen_coeffs phase_gen_coeffs;
|
||||
bw_phase_gen_state phase_gen_state;
|
||||
bw_osc_pulse_coeffs osc_pulse_coeffs;
|
||||
bw_osc_pulse_state osc_pulse_state;
|
||||
bw_osc_filt_state osc_filt_state;
|
||||
bw_noise_gen_coeffs noise_gen_coeffs;
|
||||
bw_svf_coeffs svf_coeffs;
|
||||
@ -170,10 +170,8 @@ void bw_example_synth_process(bw_example_synth instance, const float** x, float*
|
||||
//bw_env_gen_set_gate(&instance->env_gen, 0);
|
||||
|
||||
if (instance->note != -1) {
|
||||
if (instance->note_prev < 0) {
|
||||
bw_osc_pulse_reset_state(&instance->osc_pulse_coeffs, &instance->osc_pulse_state);
|
||||
if (instance->note_prev < 0)
|
||||
bw_osc_filt_reset_state(&instance->osc_filt_state);
|
||||
}
|
||||
bw_phase_gen_update_coeffs_ctrl(&instance->phase_gen_coeffs);
|
||||
bw_osc_pulse_update_coeffs_ctrl(&instance->osc_pulse_coeffs);
|
||||
for (int i = 0; i < n_samples; i++) {
|
||||
@ -181,7 +179,7 @@ void bw_example_synth_process(bw_example_synth instance, const float** x, float*
|
||||
bw_phase_gen_update_coeffs_audio(&instance->phase_gen_coeffs);
|
||||
bw_phase_gen_process1(&instance->phase_gen_coeffs, &instance->phase_gen_state, &phase, &phase_inc);
|
||||
bw_osc_pulse_update_coeffs_audio(&instance->osc_pulse_coeffs);
|
||||
y[0][i] = bw_osc_pulse_process1_antialias(&instance->osc_pulse_coeffs, &instance->osc_pulse_state, phase, phase_inc);
|
||||
y[0][i] = bw_osc_pulse_process1_antialias(&instance->osc_pulse_coeffs, phase, phase_inc);
|
||||
}
|
||||
bw_osc_filt_process(&instance->osc_filt_state, y[0], y[0], n_samples);
|
||||
} else {
|
||||
|
@ -48,6 +48,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <bw_common.h>
|
||||
|
||||
/*! api {{{
|
||||
* #### bw_osc_pulse_coeffs
|
||||
* ```>>> */
|
||||
@ -55,12 +57,6 @@ typedef struct _bw_osc_pulse_coeffs bw_osc_pulse_coeffs;
|
||||
/*! <<<```
|
||||
* Coefficients.
|
||||
*
|
||||
* ### bw_one_pole_state
|
||||
* >>> */
|
||||
typedef struct _bw_osc_pulse_state bw_osc_pulse_state;
|
||||
/*! <<<```
|
||||
* State.
|
||||
*
|
||||
* #### bw_osc_pulse_init()
|
||||
* ```>>> */
|
||||
static inline void bw_osc_pulse_init(bw_osc_pulse_coeffs *BW_RESTRICT coeffs);
|
||||
@ -72,12 +68,6 @@ static inline void bw_osc_pulse_init(bw_osc_pulse_coeffs *BW_RESTRICT 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 for the given `coeffs`.
|
||||
*
|
||||
* #### bw_osc_pulse_reset_state()
|
||||
* ```>>> */
|
||||
static inline void bw_osc_pulse_reset_state(const bw_osc_pulse_coeffs *BW_RESTRICT coeffs, bw_osc_pulse_state *BW_RESTRICT state);
|
||||
/*! <<<```
|
||||
* Resets the given `instance` to its initial state.
|
||||
* >>> */
|
||||
|
||||
static inline void bw_osc_pulse_reset_coeffs(bw_osc_pulse_coeffs *BW_RESTRICT coeffs);
|
||||
@ -85,13 +75,13 @@ static inline void bw_osc_pulse_reset_coeffs(bw_osc_pulse_coeffs *BW_RESTRICT co
|
||||
static inline void bw_osc_pulse_update_coeffs_ctrl(bw_osc_pulse_coeffs *BW_RESTRICT coeffs);
|
||||
static inline void bw_osc_pulse_update_coeffs_audio(bw_osc_pulse_coeffs *BW_RESTRICT coeffs);
|
||||
|
||||
static inline float bw_osc_pulse_process1(const bw_osc_pulse_coeffs *BW_RESTRICT coeffs, bw_osc_pulse_state *BW_RESTRICT state, float x);
|
||||
static inline float bw_osc_pulse_process1_antialias(const bw_osc_pulse_coeffs *BW_RESTRICT coeffs, bw_osc_pulse_state *BW_RESTRICT state, float x, float x_phase_inc);
|
||||
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_phase_inc);
|
||||
|
||||
/*! ...
|
||||
* #### bw_osc_pulse_process()
|
||||
* ```>>> */
|
||||
static inline void bw_osc_pulse_process(bw_osc_pulse_coeffs *BW_RESTRICT coeffs, bw_osc_pulse_state *BW_RESTRICT state, const float *x, const float *x_phase_inc, float *y, int n_samples);
|
||||
static inline void bw_osc_pulse_process(bw_osc_pulse_coeffs *BW_RESTRICT coeffs, const float *x, const float *x_phase_inc, float *y, int n_samples);
|
||||
/*! <<<```
|
||||
* Lets the given `instance` process `n_samples` samples from the input
|
||||
* buffer `x` containing the normalized phase signal and fills the
|
||||
@ -141,11 +131,6 @@ struct _bw_osc_pulse_coeffs {
|
||||
float pulse_width;
|
||||
};
|
||||
|
||||
struct _bw_osc_pulse_state {
|
||||
// empty, but we keep for potential forward API compatibility
|
||||
char unused;
|
||||
};
|
||||
|
||||
static inline void bw_osc_pulse_init(bw_osc_pulse_coeffs *BW_RESTRICT coeffs) {
|
||||
bw_one_pole_init(&coeffs->smooth_coeffs);
|
||||
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.005f);
|
||||
@ -162,9 +147,6 @@ static inline void bw_osc_pulse_reset_coeffs(bw_osc_pulse_coeffs *BW_RESTRICT co
|
||||
bw_one_pole_reset_state(&coeffs->smooth_coeffs, &coeffs->smooth_state, coeffs->pulse_width);
|
||||
}
|
||||
|
||||
static inline void bw_osc_pulse_reset_state(const bw_osc_pulse_coeffs *BW_RESTRICT coeffs, bw_osc_pulse_state *BW_RESTRICT state) {
|
||||
}
|
||||
|
||||
static inline void bw_osc_pulse_update_coeffs_ctrl(bw_osc_pulse_coeffs *BW_RESTRICT coeffs) {
|
||||
}
|
||||
|
||||
@ -172,7 +154,7 @@ static inline void bw_osc_pulse_update_coeffs_audio(bw_osc_pulse_coeffs *BW_REST
|
||||
bw_one_pole_process1(&coeffs->smooth_coeffs, &coeffs->smooth_state, coeffs->pulse_width);
|
||||
}
|
||||
|
||||
static inline float bw_osc_pulse_process1(const bw_osc_pulse_coeffs *BW_RESTRICT coeffs, bw_osc_pulse_state *BW_RESTRICT state, float x) {
|
||||
static inline float bw_osc_pulse_process1(const bw_osc_pulse_coeffs *BW_RESTRICT coeffs, float x) {
|
||||
const float pw = bw_one_pole_get_y_z1(&coeffs->smooth_state);
|
||||
return bw_signf(pw - x);
|
||||
}
|
||||
@ -184,7 +166,7 @@ static inline float _bw_osc_pulse_blep_diff(float x) {
|
||||
: x * (x * ((0.6666666666666666f - 0.08333333333333333f * x) * x - 2.f) + 2.666666666666667f) - 1.333333333333333f;
|
||||
}
|
||||
|
||||
static inline float bw_osc_pulse_process1_antialias(const bw_osc_pulse_coeffs *BW_RESTRICT coeffs, bw_osc_pulse_state *BW_RESTRICT state, float x, float x_phase_inc) {
|
||||
static inline float bw_osc_pulse_process1_antialias(const bw_osc_pulse_coeffs *BW_RESTRICT coeffs, float x, float x_phase_inc) {
|
||||
const float pw = bw_one_pole_get_y_z1(&coeffs->smooth_state);
|
||||
const float pw_m_phase = pw - x;
|
||||
float v = bw_copysignf(1.f, pw_m_phase); // pw = phase case should be properly compensated by the AA
|
||||
@ -206,16 +188,16 @@ static inline float bw_osc_pulse_process1_antialias(const bw_osc_pulse_coeffs *B
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void bw_osc_pulse_process(bw_osc_pulse_coeffs *BW_RESTRICT coeffs, bw_osc_pulse_state *BW_RESTRICT state, const float *x, const float *x_phase_inc, float *y, int n_samples) {
|
||||
static inline void bw_osc_pulse_process(bw_osc_pulse_coeffs *BW_RESTRICT coeffs, const float *x, const float *x_phase_inc, float *y, int n_samples) {
|
||||
if (coeffs->antialiasing)
|
||||
for (int i = 0; i < n_samples; i++) {
|
||||
bw_osc_pulse_update_coeffs_audio(coeffs);
|
||||
y[i] = bw_osc_pulse_process1_antialias(coeffs, state, x[i], x_phase_inc[i]);
|
||||
y[i] = bw_osc_pulse_process1_antialias(coeffs, x[i], x_phase_inc[i]);
|
||||
}
|
||||
else
|
||||
for (int i = 0; i < n_samples; i++) {
|
||||
bw_osc_pulse_update_coeffs_audio(coeffs);
|
||||
y[i] = bw_osc_pulse_process1(coeffs, state, x[i]);
|
||||
y[i] = bw_osc_pulse_process1(coeffs, x[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
* <ul>
|
||||
* <li>Version <strong>0.2.0</strong>:
|
||||
* <ul>
|
||||
* <li>Refactored API to avoid dynamic memory allocation.</li>
|
||||
* <li>Refactored API.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>Version <strong>0.1.0</strong>:
|
||||
@ -47,32 +47,29 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! api {{{
|
||||
* #### bw_osc_saw
|
||||
* ```>>> */
|
||||
typedef struct _bw_osc_saw bw_osc_saw;
|
||||
/*! <<<```
|
||||
* Instance object.
|
||||
* >>> */
|
||||
#include <bw_common.h>
|
||||
|
||||
/*! ...
|
||||
/*! api {{{
|
||||
* #### bw_osc_saw_coeffs
|
||||
* ```>>> */
|
||||
typedef struct _bw_osc_saw_coeffs bw_osc_saw_coeffs;
|
||||
/*! <<<```
|
||||
* Coefficients.
|
||||
*
|
||||
* #### bw_osc_saw_init()
|
||||
* ```>>> */
|
||||
void bw_osc_saw_init(bw_osc_saw *instance);
|
||||
static inline void bw_osc_saw_init(bw_osc_saw_coeffs *BW_RESTRICT coeffs);
|
||||
/*! <<<```
|
||||
* Initializes the `instance` object.
|
||||
* Initializes the `coeffs`.
|
||||
* >>> */
|
||||
|
||||
/*! ...
|
||||
* #### bw_osc_saw_set_sample_rate() and bw_osc_saw_reset()
|
||||
*
|
||||
* These do not exist (not needed).
|
||||
* >>> */
|
||||
static inline float bw_osc_saw_process1(const bw_osc_saw_coeffs *BW_RESTRICT coeffs, float x);
|
||||
static inline float bw_osc_saw_process1_antialias(const bw_osc_saw_coeffs *BW_RESTRICT coeffs, float x, float x_phase_inc);
|
||||
|
||||
/*! ...
|
||||
* #### bw_osc_saw_process()
|
||||
* ```>>> */
|
||||
void bw_osc_saw_process(bw_osc_saw *instance, const float *x, const float *x_phase_inc, float* y, int n_samples);
|
||||
static inline void bw_osc_saw_process(bw_osc_saw_coeffs *BW_RESTRICT coeffs, const float *x, const float *x_phase_inc, float *y, int n_samples);
|
||||
/*! <<<```
|
||||
* Lets the given `instance` process `n_samples` samples from the input
|
||||
* buffer `x` containing the normalized phase signal and fills the
|
||||
@ -82,7 +79,7 @@ void bw_osc_saw_process(bw_osc_saw *instance, const float *x, const float *x_pha
|
||||
/*! ...
|
||||
* #### bw_osc_saw_set_antialiasing()
|
||||
* ```>>> */
|
||||
void bw_osc_saw_set_antialiasing(bw_osc_saw *instance, char value);
|
||||
static inline void bw_osc_saw_set_antialiasing(bw_osc_saw_coeffs *BW_RESTRICT coeffs, char value);
|
||||
/*! <<<```
|
||||
* Sets whether the antialiasing is on (`value` non-`0`) or off (`0`) for the
|
||||
* given `instance`.
|
||||
@ -90,14 +87,60 @@ void bw_osc_saw_set_antialiasing(bw_osc_saw *instance, char value);
|
||||
* Default value: `0`.
|
||||
* }}} */
|
||||
|
||||
/* WARNING: the internal definition of this struct is not part of the public
|
||||
* API. Its content may change at any time in future versions. Please, do not
|
||||
* access its members directly. */
|
||||
struct _bw_osc_saw {
|
||||
/*** Implementation ***/
|
||||
|
||||
/* WARNING: This part of the file is not part of the public API. Its content may
|
||||
* change at any time in future versions. Please, do not use it directly. */
|
||||
|
||||
#include <bw_math.h>
|
||||
|
||||
struct _bw_osc_saw_coeffs {
|
||||
// Parameters
|
||||
char antialiasing;
|
||||
};
|
||||
|
||||
static inline void bw_osc_saw_init(bw_osc_saw_coeffs *BW_RESTRICT coeffs) {
|
||||
coeffs->antialiasing = 0;
|
||||
}
|
||||
|
||||
static inline float bw_osc_saw_process1(const bw_osc_saw_coeffs *BW_RESTRICT coeffs, float x) {
|
||||
return x + x - 1.f;
|
||||
}
|
||||
|
||||
// PolyBLEP residual based on Parzen window (4th-order B-spline), one-sided (x in [0, 2])
|
||||
static inline float _bw_osc_saw_blep_diff(float x) {
|
||||
return x < 1.f
|
||||
? x * ((0.25f * x - 0.6666666666666666f) * x * x + 1.333333333333333f) - 1.f
|
||||
: x * (x * ((0.6666666666666666f - 0.08333333333333333f * x) * x - 2.f) + 2.666666666666667f) - 1.333333333333333f;
|
||||
}
|
||||
|
||||
static inline float bw_osc_saw_process1_antialias(const bw_osc_saw_coeffs *BW_RESTRICT coeffs, float x, float x_phase_inc) {
|
||||
const float s_1_m_phase = 1.f - x;
|
||||
float v = x - s_1_m_phase;
|
||||
if (x_phase_inc != 0.f) {
|
||||
const float phase_inc_2 = x_phase_inc + x_phase_inc;
|
||||
const float phase_inc_rcp = bw_rcpf_2(x_phase_inc);
|
||||
if (s_1_m_phase < phase_inc_2)
|
||||
v += _bw_osc_saw_blep_diff(s_1_m_phase * phase_inc_rcp);
|
||||
if (x < phase_inc_2)
|
||||
v -= _bw_osc_saw_blep_diff(x * phase_inc_rcp);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void bw_osc_saw_process(bw_osc_saw_coeffs *BW_RESTRICT coeffs, const float *x, const float *x_phase_inc, float *y, int n_samples) {
|
||||
if (coeffs->antialiasing)
|
||||
for (int i = 0; i < n_samples; i++)
|
||||
y[i] = bw_osc_saw_process1_antialias(coeffs, x[i], x_phase_inc[i]);
|
||||
else
|
||||
for (int i = 0; i < n_samples; i++)
|
||||
y[i] = bw_osc_saw_process1(coeffs, x[i]);
|
||||
}
|
||||
|
||||
static inline void bw_osc_saw_set_antialiasing(bw_osc_saw_coeffs *BW_RESTRICT coeffs, char value) {
|
||||
coeffs->antialiasing = value;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Brickworks
|
||||
*
|
||||
* Copyright (C) 2022 Orastron Srl unipersonale
|
||||
*
|
||||
* Brickworks is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Brickworks is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
*
|
||||
* File author: Stefano D'Angelo
|
||||
*/
|
||||
|
||||
#include <bw_osc_saw.h>
|
||||
|
||||
#include <bw_math.h>
|
||||
|
||||
void bw_osc_saw_init(bw_osc_saw *instance) {
|
||||
instance->antialiasing = 0;
|
||||
}
|
||||
|
||||
// PolyBLEP residual based on Parzen window (4th-order B-spline), one-sided (x in [0, 2])
|
||||
static inline float blep_diff(float x) {
|
||||
return x < 1.f
|
||||
? x * ((0.25f * x - 0.6666666666666666f) * x * x + 1.333333333333333f) - 1.f
|
||||
: x * (x * ((0.6666666666666666f - 0.08333333333333333f * x) * x - 2.0f) + 2.666666666666667f) - 1.333333333333333f;
|
||||
}
|
||||
|
||||
void bw_osc_saw_process(bw_osc_saw *instance, const float *x, const float *x_phase_inc, float* y, int n_samples) {
|
||||
if (instance->antialiasing) {
|
||||
for (int i = 0; i < n_samples; i++) {
|
||||
const float s_1_m_phase = 1.f - x[i];
|
||||
float v = x[i] - s_1_m_phase;
|
||||
|
||||
if (x_phase_inc[i] != 0.f) {
|
||||
const float phase_inc_2 = x_phase_inc[i] + x_phase_inc[i];
|
||||
const float phase_inc_rcp = bw_rcpf_2(x_phase_inc[i]);
|
||||
if (s_1_m_phase < phase_inc_2)
|
||||
v += blep_diff(s_1_m_phase * phase_inc_rcp);
|
||||
if (x[i] < phase_inc_2)
|
||||
v -= blep_diff(x[i] * phase_inc_rcp);
|
||||
}
|
||||
|
||||
y[i] = v;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < n_samples; i++)
|
||||
y[i] = x[i] + x[i] - 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
void bw_osc_saw_set_antialiasing(bw_osc_saw *instance, char value) {
|
||||
instance->antialiasing = value;
|
||||
}
|
Loading…
Reference in New Issue
Block a user