ported bw_osc_filt to new API
This commit is contained in:
parent
f98f07009d
commit
6b4b0a3429
4
TODO
4
TODO
@ -1,6 +1,6 @@
|
||||
code:
|
||||
* blep etc in a module?
|
||||
* osc post filter init val? osc post filter and one pole init val from input?
|
||||
* osc post filter (and one pole init, slew rate, etc.) val from input? set state instead?
|
||||
* audio rate optional pulse width/slope inputs?
|
||||
* one pole process const input? (return also if const out)
|
||||
* optimize triangle generation for constant pulse width
|
||||
@ -16,6 +16,6 @@ build system:
|
||||
* make autodependencies (.d?)
|
||||
* make from... directories
|
||||
* order-only prerequisites to avoid multiple make updates? (https://interrupt.memfault.com/blog/gnu-make-guidelines#order-only-prerequisites)
|
||||
* clang + Ofast & bulk memory (maybe using old binaryen)
|
||||
* clang + Ofast & bulk memory (maybe using old binaryen) - or implement memset etc.
|
||||
* put common parts of Makefiles together somewhere/somehow (DRY)
|
||||
* recursive make?
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <bw_math.h>
|
||||
#include <bw_phase_gen.h>
|
||||
#include <bw_osc_pulse.h>
|
||||
#include <bw_osc_filt.h>
|
||||
#include <bw_noise_gen.h>
|
||||
#include <bw_svf.h>
|
||||
#include <bw_osc_sin.h>
|
||||
@ -35,12 +36,7 @@
|
||||
#include <bw_env_follow.h>
|
||||
|
||||
/*
|
||||
#include <bw_osc_pulse.h>
|
||||
#include <bw_osc_filt.h>
|
||||
#include <bw_svf.h>
|
||||
#include <bw_env_gen.h>
|
||||
#include <bw_vol.h>
|
||||
#include <bw_env_follow.h>
|
||||
*/
|
||||
|
||||
enum {
|
||||
@ -66,6 +62,7 @@ struct _bw_example_synth {
|
||||
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;
|
||||
bw_svf_state svf_state;
|
||||
@ -75,20 +72,18 @@ struct _bw_example_synth {
|
||||
bw_env_follow_coeffs env_follow_coeffs;
|
||||
bw_env_follow_state env_follow_state;
|
||||
/*
|
||||
bw_osc_pulse osc_pulse;
|
||||
bw_osc_filt osc_filt;
|
||||
bw_env_gen env_gen;
|
||||
bw_vol vol;
|
||||
bw_env_follow env_follow;
|
||||
*/
|
||||
|
||||
// Parameters
|
||||
float params[p_n];
|
||||
int param_changed;
|
||||
|
||||
// States
|
||||
uint64_t rand_state;
|
||||
int note;
|
||||
float level;
|
||||
int note_prev;
|
||||
|
||||
// Buffers
|
||||
//float buf[BUFFER_SIZE];
|
||||
@ -115,7 +110,6 @@ bw_example_synth bw_example_synth_new() {
|
||||
/*
|
||||
bw_osc_pulse_init(&instance->osc_pulse);
|
||||
bw_osc_filt_init(&instance->osc_filt);
|
||||
bw_svf_init(&instance->svf);
|
||||
bw_env_gen_init(&instance->env_gen);
|
||||
|
||||
bw_osc_pulse_set_antialiasing(&instance->osc_pulse, 1);
|
||||
@ -147,7 +141,6 @@ void bw_example_synth_reset(bw_example_synth instance) {
|
||||
bw_phase_gen_reset_coeffs(&instance->phase_gen_coeffs);
|
||||
bw_phase_gen_reset_state(&instance->phase_gen_coeffs, &instance->phase_gen_state, 0.f);
|
||||
bw_osc_pulse_reset_coeffs(&instance->osc_pulse_coeffs);
|
||||
bw_osc_pulse_reset_state(&instance->osc_pulse_coeffs, &instance->osc_pulse_state);
|
||||
bw_phase_gen_reset_coeffs(&instance->a440_phase_gen_coeffs);
|
||||
bw_phase_gen_reset_state(&instance->a440_phase_gen_coeffs, &instance->a440_phase_gen_state, 0.f);
|
||||
bw_svf_reset_coeffs(&instance->svf_coeffs);
|
||||
@ -156,23 +149,31 @@ void bw_example_synth_reset(bw_example_synth instance) {
|
||||
bw_env_follow_reset_coeffs(&instance->env_follow_coeffs);
|
||||
bw_env_follow_reset_state(&instance->env_follow_coeffs, &instance->env_follow_state);
|
||||
/*
|
||||
bw_osc_filt_reset(&instance->osc_filt);
|
||||
bw_env_gen_reset(&instance->env_gen);
|
||||
*/
|
||||
instance->note = -1;
|
||||
instance->note_prev = -2;
|
||||
instance->param_changed = ~0;
|
||||
}
|
||||
|
||||
#define PARAM_CHANGED_MASK(x) (1 << x)
|
||||
|
||||
void bw_example_synth_process(bw_example_synth instance, const float** x, float** y, int n_samples) {
|
||||
// TODO: I was too lazy to keep track of master tune and note and only update when needed, could be improved
|
||||
if (instance->note != -1) {
|
||||
if ((instance->note != instance->note_prev) || (instance->param_changed & PARAM_CHANGED_MASK(p_master_tune))) {
|
||||
bw_phase_gen_set_frequency(&instance->phase_gen_coeffs,
|
||||
440.f * bw_pow2f_3(8.333333333333333e-2f * ((instance->note - 69) + 2.f * instance->params[p_master_tune] - 1.f)));
|
||||
}
|
||||
//bw_env_gen_set_gate(&instance->env_gen, 1);
|
||||
} else
|
||||
;
|
||||
//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);
|
||||
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++) {
|
||||
@ -182,8 +183,8 @@ void bw_example_synth_process(bw_example_synth instance, const float** x, float*
|
||||
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);
|
||||
}
|
||||
bw_osc_filt_process(&instance->osc_filt_state, y[0], y[0], n_samples);
|
||||
} else {
|
||||
bw_osc_pulse_reset_state(&instance->osc_pulse_coeffs, &instance->osc_pulse_state); // FIXME
|
||||
bw_phase_gen_process(&instance->phase_gen_coeffs, &instance->phase_gen_state, NULL, NULL, NULL, n_samples);
|
||||
for (int i = 0; i < n_samples; i++)
|
||||
y[0][i] = 0.f;
|
||||
@ -221,10 +222,16 @@ void bw_example_synth_process(bw_example_synth instance, const float** x, float*
|
||||
|
||||
bw_env_follow_process(&instance->env_follow_coeffs, &instance->env_follow_state, y[0], NULL, n_samples);
|
||||
instance->level = bw_clipf(bw_env_follow_get_y_z1(&instance->env_follow_state), 0.f, 1.f);
|
||||
|
||||
instance->param_changed = 0;
|
||||
instance->note_prev = instance->note;
|
||||
}
|
||||
|
||||
void bw_example_synth_set_parameter(bw_example_synth instance, int index, float value) {
|
||||
if (instance->params[index] == value)
|
||||
return;
|
||||
instance->params[index] = value;
|
||||
instance->param_changed |= PARAM_CHANGED_MASK(index);
|
||||
switch (index) {
|
||||
case p_volume:
|
||||
bw_vol_set_volume(&instance->vol_coeffs, value);
|
||||
@ -264,10 +271,13 @@ float bw_example_synth_get_parameter(bw_example_synth instance, int index) {
|
||||
}
|
||||
|
||||
void bw_example_synth_note_on(bw_example_synth instance, char note, char velocity) {
|
||||
if (instance->note == note)
|
||||
return;
|
||||
instance->note = note;
|
||||
}
|
||||
|
||||
void bw_example_synth_note_off(bw_example_synth instance, char note) {
|
||||
if (note == instance->note)
|
||||
if (note != instance->note)
|
||||
return;
|
||||
instance->note = -1;
|
||||
}
|
||||
|
@ -33,7 +33,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>:
|
||||
@ -52,69 +52,62 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <bw_common.h>
|
||||
|
||||
/*! api {{{
|
||||
* #### bw_osc_filt
|
||||
* #### bw_osc_filt_state
|
||||
* ```>>> */
|
||||
typedef struct _bw_osc_filt bw_osc_filt;
|
||||
typedef struct _bw_osc_filt_state bw_osc_filt_state;
|
||||
/*! <<<```
|
||||
* Instance object.
|
||||
* >>> */
|
||||
|
||||
/*! ...
|
||||
* #### bw_osc_filt_init()
|
||||
* ```>>> */
|
||||
void bw_osc_filt_init(bw_osc_filt *instance);
|
||||
/*! <<<```
|
||||
* Initializes the `instance` object.
|
||||
* >>> */
|
||||
|
||||
/*! ...
|
||||
* #### bw_osc_filt_set_sample_rate()
|
||||
*
|
||||
* There is none (not needed).
|
||||
* State
|
||||
* >>> */
|
||||
|
||||
/*! ...
|
||||
* #### bw_osc_filt_reset()
|
||||
* ```>>> */
|
||||
void bw_osc_filt_reset(bw_osc_filt *instance);
|
||||
static inline void bw_osc_filt_reset_state(bw_osc_filt_state *BW_RESTRICT state);
|
||||
/*! <<<```
|
||||
* Resets the given `instance` to its initial state.
|
||||
* >>> */
|
||||
|
||||
static inline float bw_osc_filt_process1(bw_osc_filt_state *BW_RESTRICT state, float x);
|
||||
|
||||
/*! ...
|
||||
* #### bw_osc_filt_process()
|
||||
* ```>>> */
|
||||
void bw_osc_filt_process(bw_osc_filt *instance, const float *x, float* y, int n_samples);
|
||||
static inline void bw_osc_filt_process(bw_osc_filt_state *BW_RESTRICT state, const float *x, float* y, int n_samples);
|
||||
/*! <<<```
|
||||
* Lets the given `instance` process `n_samples` samples from the input
|
||||
* buffer `x` and fills the corresponding `n_samples` samples in the output
|
||||
* buffer `y`.
|
||||
* >>> */
|
||||
|
||||
/*! ...
|
||||
* #### bw_osc_filt_set_enabled()
|
||||
* ```>>> */
|
||||
void bw_osc_filt_set_enabled(bw_osc_filt *instance, char value);
|
||||
/*! <<<```
|
||||
* Sets whether the filter is enabled (`value` non-`0`) or bypassed (`0`)
|
||||
* for the given `instance`.
|
||||
*
|
||||
* Default value: non-`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_filt {
|
||||
// Parameters
|
||||
char enabled;
|
||||
/*** Implementation ***/
|
||||
|
||||
// State
|
||||
/* 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. */
|
||||
|
||||
struct _bw_osc_filt_state {
|
||||
float x_z1;
|
||||
float y_z1;
|
||||
};
|
||||
|
||||
static inline void bw_osc_filt_reset_state(bw_osc_filt_state *BW_RESTRICT state) {
|
||||
state->x_z1 = 0.f;
|
||||
state->y_z1 = 0.f;
|
||||
}
|
||||
|
||||
static inline float bw_osc_filt_process1(bw_osc_filt_state *BW_RESTRICT state, float x) {
|
||||
const float y = 1.371308261611209f * x + 0.08785458027104826f * state->x_z1 - 4.591628418822578e-1f * state->y_z1;
|
||||
state->x_z1 = x;
|
||||
state->y_z1 = y;
|
||||
return y;
|
||||
}
|
||||
|
||||
static inline void bw_osc_filt_process(bw_osc_filt_state *BW_RESTRICT state, const float *x, float* y, int n_samples) {
|
||||
for (int i = 0; i < n_samples; i++)
|
||||
y[i] = bw_osc_filt_process1(state, x[i]);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1,51 +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_filt.h>
|
||||
|
||||
#include <bw_common.h>
|
||||
|
||||
void bw_osc_filt_init(bw_osc_filt *instance) {
|
||||
instance->enabled = 1;
|
||||
}
|
||||
|
||||
void bw_osc_filt_reset(bw_osc_filt *instance) {
|
||||
instance->x_z1 = 0.f;
|
||||
instance->y_z1 = 0.f;
|
||||
}
|
||||
|
||||
void bw_osc_filt_process(bw_osc_filt *instance, const float *x, float* y, int n_samples) {
|
||||
if (instance->enabled)
|
||||
for (int i = 0; i < n_samples; i++) {
|
||||
const float v = 1.371308261611209f * x[i] + 0.08785458027104826f * instance->x_z1 - 4.591628418822578e-1f * instance->y_z1;
|
||||
instance->x_z1 = x[i];
|
||||
instance->y_z1 = y[i];
|
||||
y[i] = v;
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < n_samples; i++)
|
||||
y[i] = x[i];
|
||||
instance->x_z1 = instance->y_z1 = x[n_samples - 1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void bw_osc_filt_set_enabled(bw_osc_filt *instance, char value) {
|
||||
instance->enabled = value;
|
||||
}
|
Loading…
Reference in New Issue
Block a user