removed bw_allpass* + renamed bw_vol to bw_gain + new bw_lowpass1
This commit is contained in:
parent
a23ee901a2
commit
2096a877aa
4
TODO
4
TODO
@ -15,8 +15,8 @@ code:
|
|||||||
* fix vst3 mapped values (visible in Ableton Live) and short names
|
* fix vst3 mapped values (visible in Ableton Live) and short names
|
||||||
* polish examples (ranges, etc.)
|
* polish examples (ranges, etc.)
|
||||||
* change name of vst3 template folders to something that doesn't look like a vst3 folder itself
|
* change name of vst3 template folders to something that doesn't look like a vst3 folder itself
|
||||||
* compute bit depth reduction only when input changes? (state)
|
* compute bit depth reduction only when input changes? (state, option?)
|
||||||
* common smoothing policy (as control rate as possible?)
|
* common smoothing policy (as control rate as possible?) - smoothing control?
|
||||||
* avoid "force" in coeffs update by using inline functions?
|
* avoid "force" in coeffs update by using inline functions?
|
||||||
|
|
||||||
build system:
|
build system:
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
#include <bw_pink_filt.h>
|
#include <bw_pink_filt.h>
|
||||||
#include <bw_svf.h>
|
#include <bw_svf.h>
|
||||||
#include <bw_env_gen.h>
|
#include <bw_env_gen.h>
|
||||||
#include <bw_vol.h>
|
#include <bw_gain.h>
|
||||||
#include <bw_env_follow.h>
|
#include <bw_env_follow.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -50,21 +50,21 @@ enum {
|
|||||||
p_vco1_fine,
|
p_vco1_fine,
|
||||||
p_vco1_waveform,
|
p_vco1_waveform,
|
||||||
p_vco1_pw_slope,
|
p_vco1_pw_slope,
|
||||||
p_vco1_volume,
|
p_vco1_level,
|
||||||
p_vco2_mod,
|
p_vco2_mod,
|
||||||
p_vco2_coarse,
|
p_vco2_coarse,
|
||||||
p_vco2_fine,
|
p_vco2_fine,
|
||||||
p_vco2_waveform,
|
p_vco2_waveform,
|
||||||
p_vco2_pw_slope,
|
p_vco2_pw_slope,
|
||||||
p_vco2_volume,
|
p_vco2_level,
|
||||||
p_vco3_kbd,
|
p_vco3_kbd,
|
||||||
p_vco3_coarse,
|
p_vco3_coarse,
|
||||||
p_vco3_fine,
|
p_vco3_fine,
|
||||||
p_vco3_waveform,
|
p_vco3_waveform,
|
||||||
p_vco3_pw_slope,
|
p_vco3_pw_slope,
|
||||||
p_vco3_volume,
|
p_vco3_level,
|
||||||
p_noise_color,
|
p_noise_color,
|
||||||
p_noise_volume,
|
p_noise_level,
|
||||||
p_vcf_mod,
|
p_vcf_mod,
|
||||||
p_vcf_kbd_ctrl,
|
p_vcf_kbd_ctrl,
|
||||||
p_vcf_cutoff,
|
p_vcf_cutoff,
|
||||||
@ -91,22 +91,22 @@ struct _bw_example_synth_mono {
|
|||||||
bw_phase_gen_state vco1_phase_gen_state;
|
bw_phase_gen_state vco1_phase_gen_state;
|
||||||
bw_osc_pulse_coeffs vco1_pulse_coeffs;
|
bw_osc_pulse_coeffs vco1_pulse_coeffs;
|
||||||
bw_osc_tri_coeffs vco1_tri_coeffs;
|
bw_osc_tri_coeffs vco1_tri_coeffs;
|
||||||
bw_vol_coeffs vco1_vol_coeffs;
|
bw_gain_coeffs vco1_gain_coeffs;
|
||||||
bw_phase_gen_coeffs vco2_phase_gen_coeffs;
|
bw_phase_gen_coeffs vco2_phase_gen_coeffs;
|
||||||
bw_phase_gen_state vco2_phase_gen_state;
|
bw_phase_gen_state vco2_phase_gen_state;
|
||||||
bw_osc_pulse_coeffs vco2_pulse_coeffs;
|
bw_osc_pulse_coeffs vco2_pulse_coeffs;
|
||||||
bw_osc_tri_coeffs vco2_tri_coeffs;
|
bw_osc_tri_coeffs vco2_tri_coeffs;
|
||||||
bw_vol_coeffs vco2_vol_coeffs;
|
bw_gain_coeffs vco2_gain_coeffs;
|
||||||
bw_phase_gen_coeffs vco3_phase_gen_coeffs;
|
bw_phase_gen_coeffs vco3_phase_gen_coeffs;
|
||||||
bw_phase_gen_state vco3_phase_gen_state;
|
bw_phase_gen_state vco3_phase_gen_state;
|
||||||
bw_osc_pulse_coeffs vco3_pulse_coeffs;
|
bw_osc_pulse_coeffs vco3_pulse_coeffs;
|
||||||
bw_osc_tri_coeffs vco3_tri_coeffs;
|
bw_osc_tri_coeffs vco3_tri_coeffs;
|
||||||
bw_vol_coeffs vco3_vol_coeffs;
|
bw_gain_coeffs vco3_gain_coeffs;
|
||||||
bw_osc_filt_state osc_filt_state;
|
bw_osc_filt_state osc_filt_state;
|
||||||
bw_noise_gen_coeffs noise_gen_coeffs;
|
bw_noise_gen_coeffs noise_gen_coeffs;
|
||||||
bw_pink_filt_coeffs pink_filt_coeffs;
|
bw_pink_filt_coeffs pink_filt_coeffs;
|
||||||
bw_pink_filt_state pink_filt_state;
|
bw_pink_filt_state pink_filt_state;
|
||||||
bw_vol_coeffs noise_vol_coeffs;
|
bw_gain_coeffs noise_gain_coeffs;
|
||||||
bw_env_gen_coeffs vcf_env_gen_coeffs;
|
bw_env_gen_coeffs vcf_env_gen_coeffs;
|
||||||
bw_env_gen_state vcf_env_gen_state;
|
bw_env_gen_state vcf_env_gen_state;
|
||||||
bw_svf_coeffs vcf_coeffs;
|
bw_svf_coeffs vcf_coeffs;
|
||||||
@ -115,7 +115,7 @@ struct _bw_example_synth_mono {
|
|||||||
bw_env_gen_state vca_env_gen_state;
|
bw_env_gen_state vca_env_gen_state;
|
||||||
bw_phase_gen_coeffs a440_phase_gen_coeffs;
|
bw_phase_gen_coeffs a440_phase_gen_coeffs;
|
||||||
bw_phase_gen_state a440_phase_gen_state;
|
bw_phase_gen_state a440_phase_gen_state;
|
||||||
bw_vol_coeffs vol_coeffs;
|
bw_gain_coeffs gain_coeffs;
|
||||||
bw_env_follow_coeffs env_follow_coeffs;
|
bw_env_follow_coeffs env_follow_coeffs;
|
||||||
bw_env_follow_state env_follow_state;
|
bw_env_follow_state env_follow_state;
|
||||||
|
|
||||||
@ -143,23 +143,23 @@ bw_example_synth_mono bw_example_synth_mono_new() {
|
|||||||
bw_phase_gen_init(&instance->vco1_phase_gen_coeffs);
|
bw_phase_gen_init(&instance->vco1_phase_gen_coeffs);
|
||||||
bw_osc_pulse_init(&instance->vco1_pulse_coeffs);
|
bw_osc_pulse_init(&instance->vco1_pulse_coeffs);
|
||||||
bw_osc_tri_init(&instance->vco1_tri_coeffs);
|
bw_osc_tri_init(&instance->vco1_tri_coeffs);
|
||||||
bw_vol_init(&instance->vco1_vol_coeffs);
|
bw_gain_init(&instance->vco1_gain_coeffs);
|
||||||
bw_phase_gen_init(&instance->vco2_phase_gen_coeffs);
|
bw_phase_gen_init(&instance->vco2_phase_gen_coeffs);
|
||||||
bw_osc_pulse_init(&instance->vco2_pulse_coeffs);
|
bw_osc_pulse_init(&instance->vco2_pulse_coeffs);
|
||||||
bw_osc_tri_init(&instance->vco2_tri_coeffs);
|
bw_osc_tri_init(&instance->vco2_tri_coeffs);
|
||||||
bw_vol_init(&instance->vco2_vol_coeffs);
|
bw_gain_init(&instance->vco2_gain_coeffs);
|
||||||
bw_phase_gen_init(&instance->vco3_phase_gen_coeffs);
|
bw_phase_gen_init(&instance->vco3_phase_gen_coeffs);
|
||||||
bw_osc_pulse_init(&instance->vco3_pulse_coeffs);
|
bw_osc_pulse_init(&instance->vco3_pulse_coeffs);
|
||||||
bw_osc_tri_init(&instance->vco3_tri_coeffs);
|
bw_osc_tri_init(&instance->vco3_tri_coeffs);
|
||||||
bw_vol_init(&instance->vco3_vol_coeffs);
|
bw_gain_init(&instance->vco3_gain_coeffs);
|
||||||
bw_noise_gen_init(&instance->noise_gen_coeffs, &instance->rand_state);
|
bw_noise_gen_init(&instance->noise_gen_coeffs, &instance->rand_state);
|
||||||
bw_pink_filt_init(&instance->pink_filt_coeffs);
|
bw_pink_filt_init(&instance->pink_filt_coeffs);
|
||||||
bw_vol_init(&instance->noise_vol_coeffs);
|
bw_gain_init(&instance->noise_gain_coeffs);
|
||||||
bw_env_gen_init(&instance->vcf_env_gen_coeffs);
|
bw_env_gen_init(&instance->vcf_env_gen_coeffs);
|
||||||
bw_svf_init(&instance->vcf_coeffs);
|
bw_svf_init(&instance->vcf_coeffs);
|
||||||
bw_env_gen_init(&instance->vca_env_gen_coeffs);
|
bw_env_gen_init(&instance->vca_env_gen_coeffs);
|
||||||
bw_phase_gen_init(&instance->a440_phase_gen_coeffs);
|
bw_phase_gen_init(&instance->a440_phase_gen_coeffs);
|
||||||
bw_vol_init(&instance->vol_coeffs);
|
bw_gain_init(&instance->gain_coeffs);
|
||||||
bw_env_follow_init(&instance->env_follow_coeffs);
|
bw_env_follow_init(&instance->env_follow_coeffs);
|
||||||
|
|
||||||
bw_osc_saw_set_antialiasing(&instance->vco_saw_coeffs, 1);
|
bw_osc_saw_set_antialiasing(&instance->vco_saw_coeffs, 1);
|
||||||
@ -167,11 +167,11 @@ bw_example_synth_mono bw_example_synth_mono_new() {
|
|||||||
bw_osc_tri_set_antialiasing(&instance->vco1_tri_coeffs, 1);
|
bw_osc_tri_set_antialiasing(&instance->vco1_tri_coeffs, 1);
|
||||||
bw_osc_pulse_set_antialiasing(&instance->vco2_pulse_coeffs, 1);
|
bw_osc_pulse_set_antialiasing(&instance->vco2_pulse_coeffs, 1);
|
||||||
bw_osc_tri_set_antialiasing(&instance->vco2_tri_coeffs, 1);
|
bw_osc_tri_set_antialiasing(&instance->vco2_tri_coeffs, 1);
|
||||||
bw_vol_set_volume_lin(&instance->vco2_vol_coeffs, 0.f);
|
bw_gain_set_gain_lin(&instance->vco2_gain_coeffs, 0.f);
|
||||||
bw_osc_pulse_set_antialiasing(&instance->vco3_pulse_coeffs, 1);
|
bw_osc_pulse_set_antialiasing(&instance->vco3_pulse_coeffs, 1);
|
||||||
bw_osc_tri_set_antialiasing(&instance->vco3_tri_coeffs, 1);
|
bw_osc_tri_set_antialiasing(&instance->vco3_tri_coeffs, 1);
|
||||||
bw_vol_set_volume_lin(&instance->vco3_vol_coeffs, 0.f);
|
bw_gain_set_gain_lin(&instance->vco3_gain_coeffs, 0.f);
|
||||||
bw_vol_set_volume_lin(&instance->noise_vol_coeffs, 0.f);
|
bw_gain_set_gain_lin(&instance->noise_gain_coeffs, 0.f);
|
||||||
bw_phase_gen_set_frequency(&instance->a440_phase_gen_coeffs, 440.f);
|
bw_phase_gen_set_frequency(&instance->a440_phase_gen_coeffs, 440.f);
|
||||||
bw_env_follow_set_release_tau(&instance->env_follow_coeffs, 1.f);
|
bw_env_follow_set_release_tau(&instance->env_follow_coeffs, 1.f);
|
||||||
|
|
||||||
@ -188,23 +188,23 @@ void bw_example_synth_mono_set_sample_rate(bw_example_synth_mono instance, float
|
|||||||
bw_phase_gen_set_sample_rate(&instance->vco1_phase_gen_coeffs, sample_rate);
|
bw_phase_gen_set_sample_rate(&instance->vco1_phase_gen_coeffs, sample_rate);
|
||||||
bw_osc_pulse_set_sample_rate(&instance->vco1_pulse_coeffs, sample_rate);
|
bw_osc_pulse_set_sample_rate(&instance->vco1_pulse_coeffs, sample_rate);
|
||||||
bw_osc_tri_set_sample_rate(&instance->vco1_tri_coeffs, sample_rate);
|
bw_osc_tri_set_sample_rate(&instance->vco1_tri_coeffs, sample_rate);
|
||||||
bw_vol_set_sample_rate(&instance->vco1_vol_coeffs, sample_rate);
|
bw_gain_set_sample_rate(&instance->vco1_gain_coeffs, sample_rate);
|
||||||
bw_phase_gen_set_sample_rate(&instance->vco2_phase_gen_coeffs, sample_rate);
|
bw_phase_gen_set_sample_rate(&instance->vco2_phase_gen_coeffs, sample_rate);
|
||||||
bw_osc_pulse_set_sample_rate(&instance->vco2_pulse_coeffs, sample_rate);
|
bw_osc_pulse_set_sample_rate(&instance->vco2_pulse_coeffs, sample_rate);
|
||||||
bw_osc_tri_set_sample_rate(&instance->vco2_tri_coeffs, sample_rate);
|
bw_osc_tri_set_sample_rate(&instance->vco2_tri_coeffs, sample_rate);
|
||||||
bw_vol_set_sample_rate(&instance->vco2_vol_coeffs, sample_rate);
|
bw_gain_set_sample_rate(&instance->vco2_gain_coeffs, sample_rate);
|
||||||
bw_phase_gen_set_sample_rate(&instance->vco3_phase_gen_coeffs, sample_rate);
|
bw_phase_gen_set_sample_rate(&instance->vco3_phase_gen_coeffs, sample_rate);
|
||||||
bw_osc_pulse_set_sample_rate(&instance->vco3_pulse_coeffs, sample_rate);
|
bw_osc_pulse_set_sample_rate(&instance->vco3_pulse_coeffs, sample_rate);
|
||||||
bw_osc_tri_set_sample_rate(&instance->vco3_tri_coeffs, sample_rate);
|
bw_osc_tri_set_sample_rate(&instance->vco3_tri_coeffs, sample_rate);
|
||||||
bw_vol_set_sample_rate(&instance->vco3_vol_coeffs, sample_rate);
|
bw_gain_set_sample_rate(&instance->vco3_gain_coeffs, sample_rate);
|
||||||
bw_noise_gen_set_sample_rate(&instance->noise_gen_coeffs, sample_rate);
|
bw_noise_gen_set_sample_rate(&instance->noise_gen_coeffs, sample_rate);
|
||||||
bw_pink_filt_set_sample_rate(&instance->pink_filt_coeffs, sample_rate);
|
bw_pink_filt_set_sample_rate(&instance->pink_filt_coeffs, sample_rate);
|
||||||
bw_vol_set_sample_rate(&instance->noise_vol_coeffs, sample_rate);
|
bw_gain_set_sample_rate(&instance->noise_gain_coeffs, sample_rate);
|
||||||
bw_env_gen_set_sample_rate(&instance->vcf_env_gen_coeffs, sample_rate);
|
bw_env_gen_set_sample_rate(&instance->vcf_env_gen_coeffs, sample_rate);
|
||||||
bw_svf_set_sample_rate(&instance->vcf_coeffs, sample_rate);
|
bw_svf_set_sample_rate(&instance->vcf_coeffs, sample_rate);
|
||||||
bw_env_gen_set_sample_rate(&instance->vca_env_gen_coeffs, sample_rate);
|
bw_env_gen_set_sample_rate(&instance->vca_env_gen_coeffs, sample_rate);
|
||||||
bw_phase_gen_set_sample_rate(&instance->a440_phase_gen_coeffs, sample_rate);
|
bw_phase_gen_set_sample_rate(&instance->a440_phase_gen_coeffs, sample_rate);
|
||||||
bw_vol_set_sample_rate(&instance->vol_coeffs, sample_rate);
|
bw_gain_set_sample_rate(&instance->gain_coeffs, sample_rate);
|
||||||
bw_env_follow_set_sample_rate(&instance->env_follow_coeffs, sample_rate);
|
bw_env_follow_set_sample_rate(&instance->env_follow_coeffs, sample_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,20 +217,20 @@ void bw_example_synth_mono_reset(bw_example_synth_mono instance) {
|
|||||||
bw_phase_gen_reset_state(&instance->vco1_phase_gen_coeffs, &instance->vco1_phase_gen_state, 0.f);
|
bw_phase_gen_reset_state(&instance->vco1_phase_gen_coeffs, &instance->vco1_phase_gen_state, 0.f);
|
||||||
bw_osc_pulse_reset_coeffs(&instance->vco1_pulse_coeffs);
|
bw_osc_pulse_reset_coeffs(&instance->vco1_pulse_coeffs);
|
||||||
bw_osc_tri_reset_coeffs(&instance->vco1_tri_coeffs);
|
bw_osc_tri_reset_coeffs(&instance->vco1_tri_coeffs);
|
||||||
bw_vol_reset_coeffs(&instance->vco1_vol_coeffs);
|
bw_gain_reset_coeffs(&instance->vco1_gain_coeffs);
|
||||||
bw_phase_gen_reset_coeffs(&instance->vco2_phase_gen_coeffs);
|
bw_phase_gen_reset_coeffs(&instance->vco2_phase_gen_coeffs);
|
||||||
bw_phase_gen_reset_state(&instance->vco2_phase_gen_coeffs, &instance->vco2_phase_gen_state, 0.f);
|
bw_phase_gen_reset_state(&instance->vco2_phase_gen_coeffs, &instance->vco2_phase_gen_state, 0.f);
|
||||||
bw_osc_pulse_reset_coeffs(&instance->vco2_pulse_coeffs);
|
bw_osc_pulse_reset_coeffs(&instance->vco2_pulse_coeffs);
|
||||||
bw_osc_tri_reset_coeffs(&instance->vco2_tri_coeffs);
|
bw_osc_tri_reset_coeffs(&instance->vco2_tri_coeffs);
|
||||||
bw_vol_reset_coeffs(&instance->vco2_vol_coeffs);
|
bw_gain_reset_coeffs(&instance->vco2_gain_coeffs);
|
||||||
bw_phase_gen_reset_coeffs(&instance->vco3_phase_gen_coeffs);
|
bw_phase_gen_reset_coeffs(&instance->vco3_phase_gen_coeffs);
|
||||||
bw_phase_gen_reset_state(&instance->vco3_phase_gen_coeffs, &instance->vco3_phase_gen_state, 0.f);
|
bw_phase_gen_reset_state(&instance->vco3_phase_gen_coeffs, &instance->vco3_phase_gen_state, 0.f);
|
||||||
bw_osc_pulse_reset_coeffs(&instance->vco3_pulse_coeffs);
|
bw_osc_pulse_reset_coeffs(&instance->vco3_pulse_coeffs);
|
||||||
bw_osc_tri_reset_coeffs(&instance->vco3_tri_coeffs);
|
bw_osc_tri_reset_coeffs(&instance->vco3_tri_coeffs);
|
||||||
bw_vol_reset_coeffs(&instance->vco3_vol_coeffs);
|
bw_gain_reset_coeffs(&instance->vco3_gain_coeffs);
|
||||||
bw_osc_filt_reset_state(&instance->osc_filt_state);
|
bw_osc_filt_reset_state(&instance->osc_filt_state);
|
||||||
bw_pink_filt_reset_state(&instance->pink_filt_coeffs, &instance->pink_filt_state);
|
bw_pink_filt_reset_state(&instance->pink_filt_coeffs, &instance->pink_filt_state);
|
||||||
bw_vol_reset_coeffs(&instance->noise_vol_coeffs);
|
bw_gain_reset_coeffs(&instance->noise_gain_coeffs);
|
||||||
bw_env_gen_reset_coeffs(&instance->vcf_env_gen_coeffs);
|
bw_env_gen_reset_coeffs(&instance->vcf_env_gen_coeffs);
|
||||||
bw_env_gen_reset_state(&instance->vcf_env_gen_coeffs, &instance->vcf_env_gen_state);
|
bw_env_gen_reset_state(&instance->vcf_env_gen_coeffs, &instance->vcf_env_gen_state);
|
||||||
bw_svf_reset_coeffs(&instance->vcf_coeffs);
|
bw_svf_reset_coeffs(&instance->vcf_coeffs);
|
||||||
@ -239,7 +239,7 @@ void bw_example_synth_mono_reset(bw_example_synth_mono instance) {
|
|||||||
bw_env_gen_reset_state(&instance->vca_env_gen_coeffs, &instance->vca_env_gen_state);
|
bw_env_gen_reset_state(&instance->vca_env_gen_coeffs, &instance->vca_env_gen_state);
|
||||||
bw_phase_gen_reset_coeffs(&instance->a440_phase_gen_coeffs);
|
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_phase_gen_reset_state(&instance->a440_phase_gen_coeffs, &instance->a440_phase_gen_state, 0.f);
|
||||||
bw_vol_reset_coeffs(&instance->vol_coeffs);
|
bw_gain_reset_coeffs(&instance->gain_coeffs);
|
||||||
bw_env_follow_reset_coeffs(&instance->env_follow_coeffs);
|
bw_env_follow_reset_coeffs(&instance->env_follow_coeffs);
|
||||||
bw_env_follow_reset_state(&instance->env_follow_coeffs, &instance->env_follow_state);
|
bw_env_follow_reset_state(&instance->env_follow_coeffs, &instance->env_follow_state);
|
||||||
instance->note = 60;
|
instance->note = 60;
|
||||||
@ -329,10 +329,10 @@ void bw_example_synth_mono_process(bw_example_synth_mono instance, const float**
|
|||||||
bw_osc_tri_reset_coeffs(&instance->vco2_tri_coeffs);
|
bw_osc_tri_reset_coeffs(&instance->vco2_tri_coeffs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bw_vol_process(&instance->vco1_vol_coeffs, instance->buf[2], instance->buf[2], n);
|
bw_gain_process(&instance->vco1_gain_coeffs, instance->buf[2], instance->buf[2], n);
|
||||||
bw_vol_process(&instance->vco2_vol_coeffs, instance->buf[1], instance->buf[1], n);
|
bw_gain_process(&instance->vco2_gain_coeffs, instance->buf[1], instance->buf[1], n);
|
||||||
bw_vol_process(&instance->vco3_vol_coeffs, out, out, n);
|
bw_gain_process(&instance->vco3_gain_coeffs, out, out, n);
|
||||||
bw_vol_process(&instance->noise_vol_coeffs, instance->buf[0], instance->buf[0], n);
|
bw_gain_process(&instance->noise_gain_coeffs, instance->buf[0], instance->buf[0], n);
|
||||||
for (int j = 0; j < n; j++)
|
for (int j = 0; j < n; j++)
|
||||||
out[j] = out[j] + instance->buf[1][j] + instance->buf[2][j];
|
out[j] = out[j] + instance->buf[1][j] + instance->buf[2][j];
|
||||||
|
|
||||||
@ -367,7 +367,7 @@ void bw_example_synth_mono_process(bw_example_synth_mono instance, const float**
|
|||||||
for (int j = 0; j < n; j++)
|
for (int j = 0; j < n; j++)
|
||||||
out[j] += instance->buf[0][j];
|
out[j] += instance->buf[0][j];
|
||||||
|
|
||||||
bw_vol_process(&instance->vol_coeffs, out, out, n);
|
bw_gain_process(&instance->gain_coeffs, out, out, n);
|
||||||
bw_env_follow_process(&instance->env_follow_coeffs, &instance->env_follow_state, out, NULL, n);
|
bw_env_follow_process(&instance->env_follow_coeffs, &instance->env_follow_state, out, NULL, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -378,7 +378,7 @@ void bw_example_synth_mono_set_parameter(bw_example_synth_mono instance, int ind
|
|||||||
instance->params[index] = value;
|
instance->params[index] = value;
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case p_volume:
|
case p_volume:
|
||||||
bw_vol_set_volume_lin(&instance->vol_coeffs, value * value * value);
|
bw_gain_set_gain_lin(&instance->gain_coeffs, value * value * value);
|
||||||
break;
|
break;
|
||||||
case p_portamento:
|
case p_portamento:
|
||||||
bw_phase_gen_set_portamento_tau(&instance->vco1_phase_gen_coeffs, value);
|
bw_phase_gen_set_portamento_tau(&instance->vco1_phase_gen_coeffs, value);
|
||||||
@ -389,25 +389,25 @@ void bw_example_synth_mono_set_parameter(bw_example_synth_mono instance, int ind
|
|||||||
bw_osc_pulse_set_pulse_width(&instance->vco1_pulse_coeffs, value);
|
bw_osc_pulse_set_pulse_width(&instance->vco1_pulse_coeffs, value);
|
||||||
bw_osc_tri_set_slope(&instance->vco1_tri_coeffs, bw_clipf(value, 0.001f, 0.999f));
|
bw_osc_tri_set_slope(&instance->vco1_tri_coeffs, bw_clipf(value, 0.001f, 0.999f));
|
||||||
break;
|
break;
|
||||||
case p_vco1_volume:
|
case p_vco1_level:
|
||||||
bw_vol_set_volume_lin(&instance->vco1_vol_coeffs, value * value * value);
|
bw_gain_set_gain_lin(&instance->vco1_gain_coeffs, value * value * value);
|
||||||
break;
|
break;
|
||||||
case p_vco2_pw_slope:
|
case p_vco2_pw_slope:
|
||||||
bw_osc_pulse_set_pulse_width(&instance->vco2_pulse_coeffs, value);
|
bw_osc_pulse_set_pulse_width(&instance->vco2_pulse_coeffs, value);
|
||||||
bw_osc_tri_set_slope(&instance->vco2_tri_coeffs, bw_clipf(value, 0.001f, 0.999f));
|
bw_osc_tri_set_slope(&instance->vco2_tri_coeffs, bw_clipf(value, 0.001f, 0.999f));
|
||||||
break;
|
break;
|
||||||
case p_vco2_volume:
|
case p_vco2_level:
|
||||||
bw_vol_set_volume_lin(&instance->vco2_vol_coeffs, value * value * value);
|
bw_gain_set_gain_lin(&instance->vco2_gain_coeffs, value * value * value);
|
||||||
break;
|
break;
|
||||||
case p_vco3_pw_slope:
|
case p_vco3_pw_slope:
|
||||||
bw_osc_pulse_set_pulse_width(&instance->vco3_pulse_coeffs, value);
|
bw_osc_pulse_set_pulse_width(&instance->vco3_pulse_coeffs, value);
|
||||||
bw_osc_tri_set_slope(&instance->vco3_tri_coeffs, bw_clipf(value, 0.001f, 0.999f));
|
bw_osc_tri_set_slope(&instance->vco3_tri_coeffs, bw_clipf(value, 0.001f, 0.999f));
|
||||||
break;
|
break;
|
||||||
case p_vco3_volume:
|
case p_vco3_level:
|
||||||
bw_vol_set_volume_lin(&instance->vco3_vol_coeffs, value * value * value);
|
bw_gain_set_gain_lin(&instance->vco3_gain_coeffs, value * value * value);
|
||||||
break;
|
break;
|
||||||
case p_noise_volume:
|
case p_noise_level:
|
||||||
bw_vol_set_volume_lin(&instance->noise_vol_coeffs, value * value * value);
|
bw_gain_set_gain_lin(&instance->noise_gain_coeffs, value * value * value);
|
||||||
break;
|
break;
|
||||||
case p_vcf_Q:
|
case p_vcf_Q:
|
||||||
bw_svf_set_Q(&instance->vcf_coeffs, 0.5f + 9.5f * value);
|
bw_svf_set_Q(&instance->vcf_coeffs, 0.5f + 9.5f * value);
|
||||||
|
@ -74,21 +74,21 @@ static struct config_parameter config_parameters[NUM_PARAMETERS] = {
|
|||||||
{ "VCO1 fine", "VCO1 fine", "st", 0, 0, 0, 0.5f },
|
{ "VCO1 fine", "VCO1 fine", "st", 0, 0, 0, 0.5f },
|
||||||
{ "VCO1 waveform", "VCO1 wave", "", 0, 0, 2, 0.f },
|
{ "VCO1 waveform", "VCO1 wave", "", 0, 0, 2, 0.f },
|
||||||
{ "VCO1 pulse width/slope", "VCO1 pw/slope", "%", 0, 0, 0, 0.5f },
|
{ "VCO1 pulse width/slope", "VCO1 pw/slope", "%", 0, 0, 0, 0.5f },
|
||||||
{ "VCO1 volume", "VCO1 volume", "%", 0, 0, 0, 1.f },
|
{ "VCO1 level", "VCO1 level", "%", 0, 0, 0, 1.f },
|
||||||
{ "VCO2 modulation", "VCO2 mod", "%", 0, 0, 0, 0.f },
|
{ "VCO2 modulation", "VCO2 mod", "%", 0, 0, 0, 0.f },
|
||||||
{ "VCO2 coarse", "VCO2 coarse", "", 0, 0, 6, 0.5f },
|
{ "VCO2 coarse", "VCO2 coarse", "", 0, 0, 6, 0.5f },
|
||||||
{ "VCO2 fine", "VCO2 fine", "st", 0, 0, 0, 0.5f },
|
{ "VCO2 fine", "VCO2 fine", "st", 0, 0, 0, 0.5f },
|
||||||
{ "VCO2 waveform", "VCO2 wave", "", 0, 0, 2, 0.f },
|
{ "VCO2 waveform", "VCO2 wave", "", 0, 0, 2, 0.f },
|
||||||
{ "VCO2 pulse width/slope", "VCO2 pw/slope", "%", 0, 0, 0, 0.5f },
|
{ "VCO2 pulse width/slope", "VCO2 pw/slope", "%", 0, 0, 0, 0.5f },
|
||||||
{ "VCO2 volume", "VCO2 volume", "%", 0, 0, 0, 0.f },
|
{ "VCO2 level", "VCO2 level", "%", 0, 0, 0, 0.f },
|
||||||
{ "VCO3 kyboard control", "VCO3 kbd ctrl", "", 0, 0, 1, 1.f },
|
{ "VCO3 kyboard control", "VCO3 kbd ctrl", "", 0, 0, 1, 1.f },
|
||||||
{ "VCO3 coarse", "VCO3 coarse", "", 0, 0, 6, 0.5f },
|
{ "VCO3 coarse", "VCO3 coarse", "", 0, 0, 6, 0.5f },
|
||||||
{ "VCO3 fine", "VCO3 fine", "st", 0, 0, 0, 0.5f },
|
{ "VCO3 fine", "VCO3 fine", "st", 0, 0, 0, 0.5f },
|
||||||
{ "VCO3 waveform", "VCO3 wave", "", 0, 0, 2, 0.f },
|
{ "VCO3 waveform", "VCO3 wave", "", 0, 0, 2, 0.f },
|
||||||
{ "VCO3 pulse width/slope", "VCO3 pw/slope", "%", 0, 0, 0, 0.5f },
|
{ "VCO3 pulse width/slope", "VCO3 pw/slope", "%", 0, 0, 0, 0.5f },
|
||||||
{ "VCO3 volume", "VCO3 volume", "%", 0, 0, 0, 0.f },
|
{ "VCO3 level", "VCO3 level", "%", 0, 0, 0, 0.f },
|
||||||
{ "Noise color", "Noise color", "", 0, 0, 1, 0.f },
|
{ "Noise color", "Noise color", "", 0, 0, 1, 0.f },
|
||||||
{ "Noise volume", "Noise volume", "%", 0, 0, 0, 0.f },
|
{ "Noise level", "Noise level", "%", 0, 0, 0, 0.f },
|
||||||
{ "VCF modulation", "VCF mod", "%", 0, 0, 0, 0.f },
|
{ "VCF modulation", "VCF mod", "%", 0, 0, 0, 0.f },
|
||||||
{ "VCF keyboard control", "VCF kbd ctrl", "", 0, 0, 3, 0.f },
|
{ "VCF keyboard control", "VCF kbd ctrl", "", 0, 0, 3, 0.f },
|
||||||
{ "VCF cutoff", "VCF cutoff", "Hz", 0, 0, 0, 1.f },
|
{ "VCF cutoff", "VCF cutoff", "Hz", 0, 0, 0, 1.f },
|
||||||
|
@ -74,7 +74,7 @@ var parameters = [
|
|||||||
defaultValue: 0.5
|
defaultValue: 0.5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "VCO1 volume",
|
name: "VCO1 level",
|
||||||
output: false,
|
output: false,
|
||||||
defaultValue: 1.0
|
defaultValue: 1.0
|
||||||
},
|
},
|
||||||
@ -106,7 +106,7 @@ var parameters = [
|
|||||||
defaultValue: 0.5
|
defaultValue: 0.5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "VCO2 volume",
|
name: "VCO2 level",
|
||||||
output: false,
|
output: false,
|
||||||
defaultValue: 0.0
|
defaultValue: 0.0
|
||||||
},
|
},
|
||||||
@ -139,7 +139,7 @@ var parameters = [
|
|||||||
defaultValue: 0.5
|
defaultValue: 0.5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "VCO3 volume",
|
name: "VCO3 level",
|
||||||
output: false,
|
output: false,
|
||||||
defaultValue: 0.0
|
defaultValue: 0.0
|
||||||
},
|
},
|
||||||
@ -150,7 +150,7 @@ var parameters = [
|
|||||||
step: 1
|
step: 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Noise volume",
|
name: "Noise level",
|
||||||
output: false,
|
output: false,
|
||||||
defaultValue: 0.0
|
defaultValue: 0.0
|
||||||
},
|
},
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
#include <bw_osc_filt.h>
|
#include <bw_osc_filt.h>
|
||||||
#include <bw_svf.h>
|
#include <bw_svf.h>
|
||||||
#include <bw_env_gen.h>
|
#include <bw_env_gen.h>
|
||||||
#include <bw_vol.h>
|
#include <bw_gain.h>
|
||||||
#include <bw_env_follow.h>
|
#include <bw_env_follow.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -61,7 +61,7 @@ struct _bw_example_synth_simple {
|
|||||||
bw_svf_state svf_state;
|
bw_svf_state svf_state;
|
||||||
bw_env_gen_coeffs env_gen_coeffs;
|
bw_env_gen_coeffs env_gen_coeffs;
|
||||||
bw_env_gen_state env_gen_state;
|
bw_env_gen_state env_gen_state;
|
||||||
bw_vol_coeffs vol_coeffs;
|
bw_gain_coeffs gain_coeffs;
|
||||||
bw_env_follow_coeffs env_follow_coeffs;
|
bw_env_follow_coeffs env_follow_coeffs;
|
||||||
bw_env_follow_state env_follow_state;
|
bw_env_follow_state env_follow_state;
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ bw_example_synth_simple bw_example_synth_simple_new() {
|
|||||||
bw_osc_pulse_init(&instance->osc_pulse_coeffs);
|
bw_osc_pulse_init(&instance->osc_pulse_coeffs);
|
||||||
bw_svf_init(&instance->svf_coeffs);
|
bw_svf_init(&instance->svf_coeffs);
|
||||||
bw_env_gen_init(&instance->env_gen_coeffs);
|
bw_env_gen_init(&instance->env_gen_coeffs);
|
||||||
bw_vol_init(&instance->vol_coeffs);
|
bw_gain_init(&instance->gain_coeffs);
|
||||||
bw_env_follow_init(&instance->env_follow_coeffs);
|
bw_env_follow_init(&instance->env_follow_coeffs);
|
||||||
|
|
||||||
bw_osc_pulse_set_antialiasing(&instance->osc_pulse_coeffs, 1);
|
bw_osc_pulse_set_antialiasing(&instance->osc_pulse_coeffs, 1);
|
||||||
@ -105,7 +105,7 @@ void bw_example_synth_simple_set_sample_rate(bw_example_synth_simple instance, f
|
|||||||
bw_osc_pulse_set_sample_rate(&instance->osc_pulse_coeffs, sample_rate);
|
bw_osc_pulse_set_sample_rate(&instance->osc_pulse_coeffs, sample_rate);
|
||||||
bw_svf_set_sample_rate(&instance->svf_coeffs, sample_rate);
|
bw_svf_set_sample_rate(&instance->svf_coeffs, sample_rate);
|
||||||
bw_env_gen_set_sample_rate(&instance->env_gen_coeffs, sample_rate);
|
bw_env_gen_set_sample_rate(&instance->env_gen_coeffs, sample_rate);
|
||||||
bw_vol_set_sample_rate(&instance->vol_coeffs, sample_rate);
|
bw_gain_set_sample_rate(&instance->gain_coeffs, sample_rate);
|
||||||
bw_env_follow_set_sample_rate(&instance->env_follow_coeffs, sample_rate);
|
bw_env_follow_set_sample_rate(&instance->env_follow_coeffs, sample_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ void bw_example_synth_simple_reset(bw_example_synth_simple instance) {
|
|||||||
bw_svf_reset_state(&instance->svf_coeffs, &instance->svf_state);
|
bw_svf_reset_state(&instance->svf_coeffs, &instance->svf_state);
|
||||||
bw_env_gen_reset_coeffs(&instance->env_gen_coeffs);
|
bw_env_gen_reset_coeffs(&instance->env_gen_coeffs);
|
||||||
bw_env_gen_reset_state(&instance->env_gen_coeffs, &instance->env_gen_state);
|
bw_env_gen_reset_state(&instance->env_gen_coeffs, &instance->env_gen_state);
|
||||||
bw_vol_reset_coeffs(&instance->vol_coeffs);
|
bw_gain_reset_coeffs(&instance->gain_coeffs);
|
||||||
bw_env_follow_reset_coeffs(&instance->env_follow_coeffs);
|
bw_env_follow_reset_coeffs(&instance->env_follow_coeffs);
|
||||||
bw_env_follow_reset_state(&instance->env_follow_coeffs, &instance->env_follow_state);
|
bw_env_follow_reset_state(&instance->env_follow_coeffs, &instance->env_follow_state);
|
||||||
instance->note = -1;
|
instance->note = -1;
|
||||||
@ -142,7 +142,7 @@ void bw_example_synth_simple_process(bw_example_synth_simple instance, const flo
|
|||||||
bw_env_gen_process(&instance->env_gen_coeffs, &instance->env_gen_state, instance->buf, n);
|
bw_env_gen_process(&instance->env_gen_coeffs, &instance->env_gen_state, instance->buf, n);
|
||||||
for (int j = 0; j < n; j++)
|
for (int j = 0; j < n; j++)
|
||||||
out[j] *= instance->buf[j];
|
out[j] *= instance->buf[j];
|
||||||
bw_vol_process(&instance->vol_coeffs, out, out, n);
|
bw_gain_process(&instance->gain_coeffs, out, out, n);
|
||||||
bw_env_follow_process(&instance->env_follow_coeffs, &instance->env_follow_state, out, NULL, n);
|
bw_env_follow_process(&instance->env_follow_coeffs, &instance->env_follow_state, out, NULL, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,7 +153,7 @@ void bw_example_synth_simple_set_parameter(bw_example_synth_simple instance, int
|
|||||||
instance->params[index] = value;
|
instance->params[index] = value;
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case p_volume:
|
case p_volume:
|
||||||
bw_vol_set_volume_lin(&instance->vol_coeffs, value * value * value);
|
bw_gain_set_gain_lin(&instance->gain_coeffs, value * value * value);
|
||||||
break;
|
break;
|
||||||
case p_portamento:
|
case p_portamento:
|
||||||
bw_phase_gen_set_portamento_tau(&instance->phase_gen_coeffs, value);
|
bw_phase_gen_set_portamento_tau(&instance->phase_gen_coeffs, value);
|
||||||
|
@ -1,201 +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
|
|
||||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* File author: Stefano D'Angelo
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* module_type {{{ dsp }}}
|
|
||||||
* version {{{ 0.3.0 }}}
|
|
||||||
* requires {{{ bw_config bw_common bw_math }}}
|
|
||||||
* description {{{
|
|
||||||
* First-order allpass filter.
|
|
||||||
* }}}
|
|
||||||
* changelog {{{
|
|
||||||
* <ul>
|
|
||||||
* <li>Version <strong>0.3.0</strong>:
|
|
||||||
* <ul>
|
|
||||||
* <li>First release.</li>
|
|
||||||
* </ul>
|
|
||||||
* </li>
|
|
||||||
* </ul>
|
|
||||||
* }}}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BW_ALLPASS1_H
|
|
||||||
#define _BW_ALLPASS1_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <bw_common.h>
|
|
||||||
|
|
||||||
/*! api {{{
|
|
||||||
* #### bw_allpass1_coeffs
|
|
||||||
* ```>>> */
|
|
||||||
typedef struct _bw_allpass1_coeffs bw_allpass1_coeffs;
|
|
||||||
/*! <<<```
|
|
||||||
* Coefficients and related.
|
|
||||||
*
|
|
||||||
* #### bw_allpass1_state
|
|
||||||
* ```>>> */
|
|
||||||
typedef struct _bw_allpass1_state bw_allpass1_state;
|
|
||||||
/*! <<<```
|
|
||||||
* Internal state and related.
|
|
||||||
*
|
|
||||||
* #### bw_allpass1_init()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass1_init(bw_allpass1_coeffs *BW_RESTRICT coeffs);
|
|
||||||
/*! <<<```
|
|
||||||
* Initializes input parameter values in `coeffs`.
|
|
||||||
*
|
|
||||||
* #### bw_allpass1_set_sample_rate()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass1_set_sample_rate(bw_allpass1_coeffs *BW_RESTRICT coeffs, float sample_rate);
|
|
||||||
/*! <<<```
|
|
||||||
* Sets the `sample_rate` (Hz) value in `coeffs`.
|
|
||||||
*
|
|
||||||
* #### bw_allpass1_reset_coeffs()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass1_reset_coeffs(bw_allpass1_coeffs *BW_RESTRICT coeffs);
|
|
||||||
/*! <<<```
|
|
||||||
* Resets coefficients in `coeffs` to assume their target values.
|
|
||||||
*
|
|
||||||
* #### bw_allpass1_reset_state()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass1_reset_state(const bw_allpass1_coeffs *BW_RESTRICT coeffs, bw_allpass1_state *BW_RESTRICT state);
|
|
||||||
/*! <<<```
|
|
||||||
* Resets the given `state` to its initial values using the given `coeffs`.
|
|
||||||
*
|
|
||||||
* #### bw_allpass1_update_coeffs_ctrl()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass1_update_coeffs_ctrl(bw_allpass1_coeffs *BW_RESTRICT coeffs);
|
|
||||||
/*! <<<```
|
|
||||||
* Triggers control-rate update of coefficients in `coeffs`.
|
|
||||||
*
|
|
||||||
* #### bw_allpass1_update_coeffs_audio()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass1_update_coeffs_audio(bw_allpass1_coeffs *BW_RESTRICT coeffs);
|
|
||||||
/*! <<<```
|
|
||||||
* Triggers audio-rate update of coefficients in `coeffs`.
|
|
||||||
*
|
|
||||||
* #### bw_allpass1_process1()
|
|
||||||
* ```>>> */
|
|
||||||
static inline float bw_allpass1_process1(const bw_allpass1_coeffs *BW_RESTRICT coeffs, bw_allpass1_state *BW_RESTRICT state, float x);
|
|
||||||
/*! <<<```
|
|
||||||
* Processes one input sample `x` using `coeffs`, while using and updating
|
|
||||||
* `state`. Returns the corresponding output sample.
|
|
||||||
*
|
|
||||||
* #### bw_allpass1_process()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass1_process(bw_allpass1_coeffs *BW_RESTRICT coeffs, bw_allpass1_state *BW_RESTRICT state, const float *x, float *y, int n_samples);
|
|
||||||
/*! <<<```
|
|
||||||
* Processes the first `n_samples` of the input buffer `x` and fills the
|
|
||||||
* first `n_samples` of the output buffer `y`, while using and updating both
|
|
||||||
* `coeffs` and `state` (control and audio rate).
|
|
||||||
*
|
|
||||||
* #### bw_allpass1_set_cutoff()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass1_set_cutoff(bw_allpass1_coeffs *BW_RESTRICT coeffs, float value);
|
|
||||||
/*! <<<```
|
|
||||||
* Sets the cutoff frequency `value` (Hz) in `coeffs`.
|
|
||||||
*
|
|
||||||
* Default value: `1e3f`.
|
|
||||||
* }}} */
|
|
||||||
|
|
||||||
/*** 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_allpass1_coeffs {
|
|
||||||
// Coefficients
|
|
||||||
float t_k;
|
|
||||||
|
|
||||||
float t;
|
|
||||||
float X_x;
|
|
||||||
float X_X_z1;
|
|
||||||
float lp_X;
|
|
||||||
|
|
||||||
// Parameters
|
|
||||||
float cutoff;
|
|
||||||
float cutoff_prev;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _bw_allpass1_state {
|
|
||||||
float lp_z1;
|
|
||||||
float X_z1;
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline void bw_allpass1_init(bw_allpass1_coeffs *BW_RESTRICT coeffs) {
|
|
||||||
coeffs->cutoff = 1e3f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass1_set_sample_rate(bw_allpass1_coeffs *BW_RESTRICT coeffs, float sample_rate) {
|
|
||||||
coeffs->t_k = 3.141592653589793f / sample_rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass1_reset_coeffs(bw_allpass1_coeffs *BW_RESTRICT coeffs) {
|
|
||||||
coeffs->cutoff_prev = -1.f;
|
|
||||||
bw_allpass1_update_coeffs_ctrl(coeffs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass1_reset_state(const bw_allpass1_coeffs *BW_RESTRICT coeffs, bw_allpass1_state *BW_RESTRICT state) {
|
|
||||||
state->lp_z1 = 0.f;
|
|
||||||
state->X_z1 = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass1_update_coeffs_ctrl(bw_allpass1_coeffs *BW_RESTRICT coeffs) {
|
|
||||||
if (coeffs->cutoff != coeffs->cutoff_prev) {
|
|
||||||
coeffs->t = bw_tanf_3(coeffs->t_k * coeffs->cutoff);
|
|
||||||
const float k = bw_rcpf_2(1.f + coeffs->T);
|
|
||||||
coeffs->X_x = k * coeffs->cutoff;
|
|
||||||
coeffs->X_X_z1 = k * coeffs->t;
|
|
||||||
coeffs->lp_X = bw_rcpf_2(coeffs->cutoff);
|
|
||||||
coeffs->cutoff_prev = coeffs->cutoff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass1_update_coeffs_audio(bw_allpass1_coeffs *BW_RESTRICT coeffs) {
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline float bw_allpass1_process1(const bw_allpass1_coeffs *BW_RESTRICT coeffs, bw_allpass1_state *BW_RESTRICT state, float x) {
|
|
||||||
const float X = coeffs->X_x * (x - state->lp_z1) - coeffs->X_X_z1 * state->X_z1;
|
|
||||||
const float lp = x - coeffs->lp_X * X;
|
|
||||||
state->X_z1 = X;
|
|
||||||
state->lp_z1 = lp;
|
|
||||||
return lp + lp - x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass1_process(bw_allpass1_coeffs *BW_RESTRICT coeffs, bw_allpass1_state *BW_RESTRICT state, const float *x, float *y, int n_samples) {
|
|
||||||
bw_allpass1_update_coeffs_ctrl(coeffs);
|
|
||||||
for (int i = 0; i < n_samples; i++)
|
|
||||||
y[i] = bw_allpass1_process1(coeffs, state, x[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass1_set_cutoff(bw_allpass1_coeffs *BW_RESTRICT coeffs, float value) {
|
|
||||||
coeffs->cutoff = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,258 +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
|
|
||||||
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* File author: Stefano D'Angelo
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* module_type {{{ dsp }}}
|
|
||||||
* version {{{ 0.3.0 }}}
|
|
||||||
* requires {{{ bw_config bw_common bw_math }}}
|
|
||||||
* description {{{
|
|
||||||
* Second-order allpass filter.
|
|
||||||
* }}}
|
|
||||||
* changelog {{{
|
|
||||||
* <ul>
|
|
||||||
* <li>Version <strong>0.3.0</strong>:
|
|
||||||
* <ul>
|
|
||||||
* <li>First release.</li>
|
|
||||||
* </ul>
|
|
||||||
* </li>
|
|
||||||
* </ul>
|
|
||||||
* }}}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BW_ALLPASS2_H
|
|
||||||
#define _BW_ALLPASS2_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <bw_common.h>
|
|
||||||
|
|
||||||
/*! api {{{
|
|
||||||
* #### bw_allpass2_coeffs
|
|
||||||
* ```>>> */
|
|
||||||
typedef struct _bw_allpass2_coeffs bw_allpass2_coeffs;
|
|
||||||
/*! <<<```
|
|
||||||
* Coefficients and related.
|
|
||||||
*
|
|
||||||
* #### bw_allpass2_state
|
|
||||||
* ```>>> */
|
|
||||||
typedef struct _bw_allpass2_state bw_allpass2_state;
|
|
||||||
/*! <<<```
|
|
||||||
* Internal state and related.
|
|
||||||
*
|
|
||||||
* #### bw_allpass2_init()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass2_init(bw_allpass2_coeffs *BW_RESTRICT coeffs);
|
|
||||||
/*! <<<```
|
|
||||||
* Initializes input parameter values in `coeffs`.
|
|
||||||
*
|
|
||||||
* #### bw_allpass2_set_sample_rate()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass2_set_sample_rate(bw_allpass2_coeffs *BW_RESTRICT coeffs, float sample_rate);
|
|
||||||
/*! <<<```
|
|
||||||
* Sets the `sample_rate` (Hz) value in `coeffs`.
|
|
||||||
*
|
|
||||||
* #### bw_allpass2_reset_coeffs()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass2_reset_coeffs(bw_allpass2_coeffs *BW_RESTRICT coeffs);
|
|
||||||
/*! <<<```
|
|
||||||
* Resets coefficients in `coeffs` to assume their target values.
|
|
||||||
*
|
|
||||||
* #### bw_allpass2_reset_state()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass2_reset_state(const bw_allpass2_coeffs *BW_RESTRICT coeffs, bw_allpass2_state *BW_RESTRICT state);
|
|
||||||
/*! <<<```
|
|
||||||
* Resets the given `state` to its initial values using the given `coeffs`.
|
|
||||||
*
|
|
||||||
* #### bw_allpass2_update_coeffs_ctrl()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass2_update_coeffs_ctrl(bw_allpass2_coeffs *BW_RESTRICT coeffs);
|
|
||||||
/*! <<<```
|
|
||||||
* Triggers control-rate update of coefficients in `coeffs`.
|
|
||||||
*
|
|
||||||
* #### bw_allpass2_update_coeffs_audio()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass2_update_coeffs_audio(bw_allpass2_coeffs *BW_RESTRICT coeffs);
|
|
||||||
/*! <<<```
|
|
||||||
* Triggers audio-rate update of coefficients in `coeffs`.
|
|
||||||
*
|
|
||||||
* #### bw_allpass2_process1()
|
|
||||||
* ```>>> */
|
|
||||||
static inline float bw_allpass2_process1(const bw_allpass2_coeffs *BW_RESTRICT coeffs, bw_allpass2_state *BW_RESTRICT state, float x);
|
|
||||||
/*! <<<```
|
|
||||||
* Processes one input sample `x` using `coeffs`, while using and updating
|
|
||||||
* `state`. Returns the corresponding output sample.
|
|
||||||
*
|
|
||||||
* #### bw_allpass2_process()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass2_process(bw_allpass2_coeffs *BW_RESTRICT coeffs, bw_allpass2_state *BW_RESTRICT state, const float *x, float *y, int n_samples);
|
|
||||||
/*! <<<```
|
|
||||||
* Processes the first `n_samples` of the input buffer `x` and fills the
|
|
||||||
* first `n_samples` of the output buffer `y`, while using and updating both
|
|
||||||
* `coeffs` and `state` (control and audio rate).
|
|
||||||
*
|
|
||||||
* #### bw_allpass2_set_cutoff()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass2_set_cutoff(bw_allpass2_coeffs *BW_RESTRICT coeffs, float value);
|
|
||||||
/*! <<<```
|
|
||||||
* Sets the cutoff frequency `value` (Hz) in `coeffs`.
|
|
||||||
*
|
|
||||||
* Default value: `1e3f`.
|
|
||||||
*
|
|
||||||
* #### bw_allpass2_set_Q()
|
|
||||||
* ```>>> */
|
|
||||||
static inline void bw_allpass2_set_Q(bw_allpass2_coeffs *BW_RESTRICT coeffs, float value);
|
|
||||||
/*! <<<```
|
|
||||||
* Sets the quality factor `value` in `coeffs`.
|
|
||||||
*
|
|
||||||
* Default value: `0.5f`.
|
|
||||||
* }}} */
|
|
||||||
|
|
||||||
/*** 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_allpass2_coeffs {
|
|
||||||
// Coefficients
|
|
||||||
float t_k;
|
|
||||||
|
|
||||||
float t;
|
|
||||||
float kf;
|
|
||||||
float k;
|
|
||||||
float ks;
|
|
||||||
float X1_x;
|
|
||||||
float X2_X2_xz1_x1;
|
|
||||||
float X2_X1;
|
|
||||||
float X1_X2_xz1_x1;
|
|
||||||
float X1_VC1_xz1;
|
|
||||||
|
|
||||||
// Parameters
|
|
||||||
float cutoff;
|
|
||||||
float Q;
|
|
||||||
int param_changed;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _bw_allpass2_state {
|
|
||||||
float VC1_z1;
|
|
||||||
float VC2_z1;
|
|
||||||
float X1_z1;
|
|
||||||
float X2_z1;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define _BW_ALLPASS2_PARAM_CUTOFF 1
|
|
||||||
#define _BW_ALLPASS2_PARAM_Q (1<<1)
|
|
||||||
|
|
||||||
static inline void bw_allpass2_init(bw_allpass2_coeffs *BW_RESTRICT coeffs) {
|
|
||||||
coeffs->cutoff = 1e3f;
|
|
||||||
coeffs->Q = 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass2_set_sample_rate(bw_allpass2_coeffs *BW_RESTRICT coeffs, float sample_rate) {
|
|
||||||
coeffs->t_k = 3.141592653589793f / sample_rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass2_reset_coeffs(bw_allpass2_coeffs *BW_RESTRICT coeffs) {
|
|
||||||
coeffs->param_changed = ~0;
|
|
||||||
bw_allpass2_update_coeffs_ctrl(coeffs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass2_reset_state(const bw_allpass2_coeffs *BW_RESTRICT coeffs, bw_allpass2_state *BW_RESTRICT state) {
|
|
||||||
state->VC1_z1 = 0.f;
|
|
||||||
state->VC2_z1 = 0.f;
|
|
||||||
state->X1_z1 = 0.f;
|
|
||||||
state->X2_z1 = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass2_update_coeffs_ctrl(bw_allpass2_coeffs *BW_RESTRICT coeffs) {
|
|
||||||
if (coeffs->param_changed) {
|
|
||||||
if (coeffs->param_changed & _BW_ALLPASS2_PARAM_CUTOFF) {
|
|
||||||
coeffs->t = bw_tanf_3(coeffs->t_k * coeffs->cutoff);
|
|
||||||
coeffs->kf = coeffs->t * bw_rcpf_2(coeffs->cutoff);
|
|
||||||
}
|
|
||||||
if (coeffs->param_changed & _BW_ALLPASS2_PARAM_Q) {
|
|
||||||
const float Q2 = coeffs->Q + coeffs->Q;
|
|
||||||
const float Q2s = Q2 + Q2;
|
|
||||||
coeffs->k = Q2 * bw_rcpf_2(1.f + bw_sqrtf_2(1.f + Q2s + Q2s));
|
|
||||||
coeffs->ks = coeffs->k * coeffs->k;
|
|
||||||
coeffs->X1_x = 1.f - coeffs->ks - coeffs->ks;
|
|
||||||
}
|
|
||||||
const float kt = coeffs->k * coeffs->t;
|
|
||||||
const float kt1 = 1.f + kt;
|
|
||||||
const float X1_k = coeffs->cutoff * bw_rcpf_2(coeffs->t * kt1 + coeffs->k * (1.f - kt - kt));
|
|
||||||
coeffs->X2_X2_xz1_x1 = -coeffs->cutoff * coeffs->k * bw_rcpf_2(kt1);
|
|
||||||
coeffs->X2_X1 = coeffs->kf * coeffs->X2_X2_xz1_x1;
|
|
||||||
coeffs->X1_X2_xz1_x1 = 3.f * X1_k * coeffs->ks;
|
|
||||||
coeffs->X1_VC1_xz1 = X1_k * kt1;
|
|
||||||
coeffs->param_changed = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass2_update_coeffs_audio(bw_allpass2_coeffs *BW_RESTRICT coeffs) {
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline float bw_allpass2_process1(const bw_allpass2_coeffs *BW_RESTRICT coeffs, bw_allpass2_state *BW_RESTRICT state, float x) {
|
|
||||||
const float VC2_xz1 = coeffs->kf * state->X2_z1 + state->VC2_z1;
|
|
||||||
const float VC1_xz1 = coeffs->kf * state->X1_z1 + state->VC1_z1;
|
|
||||||
const float X2_xz1_x1 = state->VC2_xz1 + state->VC1_xz1;
|
|
||||||
const float X2_xz1 = coeffs->X2_X2_xz1_x1 * X2_xz1_x1;
|
|
||||||
const float X1 = coeffs->X1_VC1_xz1 * (coeffs->X1_x * x - state->VC1_xz1) + coeffs->X1_X2_xz1_x1 * X2_xz1_x1;
|
|
||||||
const float X2 = X2_xz1 + coeffs->X2_X1 * X1;
|
|
||||||
const float VC1 = coeffs->kf * X1 + VC1_xz1;
|
|
||||||
const float VC2 = coeffs->kf * X2 + VC2_xz1;
|
|
||||||
const float y_x1 = VC1 + VC2;
|
|
||||||
state->VC1_z1 = VC1;
|
|
||||||
state->VC2_z1 = VC2;
|
|
||||||
state->X1_z1 = X1;
|
|
||||||
state->X2_z1 = X2;
|
|
||||||
return x - (y_x1 + y_x1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass2_process(bw_allpass2_coeffs *BW_RESTRICT coeffs, bw_allpass2_state *BW_RESTRICT state, const float *x, float *y, int n_samples) {
|
|
||||||
bw_allpass2_update_coeffs_ctrl(coeffs);
|
|
||||||
for (int i = 0; i < n_samples; i++)
|
|
||||||
y[i] = bw_allpass2_process1(coeffs, state, x[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass2_set_cutoff(bw_allpass2_coeffs *BW_RESTRICT coeffs, float value) {
|
|
||||||
if (value != coeffs->cutoff) {
|
|
||||||
coeffs->cutoff = value;
|
|
||||||
coeffs->param_changed |= _BW_ALLPASS2_PARAM_CUTOFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bw_allpass2_set_Q(bw_allpass2_coeffs *BW_RESTRICT coeffs, float value) {
|
|
||||||
if (value != coeffs->Q) {
|
|
||||||
coeffs->Q = value;
|
|
||||||
coeffs->param_changed |= _BW_ALLPASS2_PARAM_Q;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef _BW_ALLPASS2_PARAM_CUTOFF
|
|
||||||
#undef _BW_ALLPASS2_PARAM_Q
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -21,7 +21,9 @@
|
|||||||
/*!
|
/*!
|
||||||
* module_type {{{ dsp }}}
|
* module_type {{{ dsp }}}
|
||||||
* version {{{ 0.3.0 }}}
|
* version {{{ 0.3.0 }}}
|
||||||
* requires {{{ bw_config bw_common bw_env_follow bw_one_pole bw_math bw_vol }}}
|
* requires {{{
|
||||||
|
* bw_config bw_common bw_env_follow bw_one_pole bw_math bw_gain
|
||||||
|
* }}}
|
||||||
* description {{{
|
* description {{{
|
||||||
* Feedforward compressor/limiter with independent sidechain input.
|
* Feedforward compressor/limiter with independent sidechain input.
|
||||||
* }}}
|
* }}}
|
||||||
@ -180,13 +182,13 @@ static inline void bw_comp_set_gain_dB(bw_comp_coeffs *BW_RESTRICT coeffs, float
|
|||||||
|
|
||||||
#include <bw_math.h>
|
#include <bw_math.h>
|
||||||
#include <bw_env_follow.h>
|
#include <bw_env_follow.h>
|
||||||
#include <bw_vol.h>
|
#include <bw_gain.h>
|
||||||
#include <bw_one_pole.h>
|
#include <bw_one_pole.h>
|
||||||
|
|
||||||
struct _bw_comp_coeffs {
|
struct _bw_comp_coeffs {
|
||||||
// Sub-components
|
// Sub-components
|
||||||
bw_env_follow_coeffs env_follow_coeffs;
|
bw_env_follow_coeffs env_follow_coeffs;
|
||||||
bw_vol_coeffs vol_coeffs;
|
bw_gain_coeffs gain_coeffs;
|
||||||
bw_one_pole_coeffs smooth_coeffs;
|
bw_one_pole_coeffs smooth_coeffs;
|
||||||
bw_one_pole_state smooth_thresh_state;
|
bw_one_pole_state smooth_thresh_state;
|
||||||
bw_one_pole_state smooth_ratio_state;
|
bw_one_pole_state smooth_ratio_state;
|
||||||
@ -205,7 +207,7 @@ struct _bw_comp_state {
|
|||||||
|
|
||||||
static inline void bw_comp_init(bw_comp_coeffs *BW_RESTRICT coeffs) {
|
static inline void bw_comp_init(bw_comp_coeffs *BW_RESTRICT coeffs) {
|
||||||
bw_env_follow_init(&coeffs->env_follow_coeffs);
|
bw_env_follow_init(&coeffs->env_follow_coeffs);
|
||||||
bw_vol_init(&coeffs->vol_coeffs);
|
bw_gain_init(&coeffs->gain_coeffs);
|
||||||
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.05f);
|
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.05f);
|
||||||
coeffs->thresh = 1.f;
|
coeffs->thresh = 1.f;
|
||||||
coeffs->ratio = 1.f;
|
coeffs->ratio = 1.f;
|
||||||
@ -213,14 +215,14 @@ static inline void bw_comp_init(bw_comp_coeffs *BW_RESTRICT coeffs) {
|
|||||||
|
|
||||||
static inline void bw_comp_set_sample_rate(bw_comp_coeffs *BW_RESTRICT coeffs, float sample_rate) {
|
static inline void bw_comp_set_sample_rate(bw_comp_coeffs *BW_RESTRICT coeffs, float sample_rate) {
|
||||||
bw_env_follow_set_sample_rate(&coeffs->env_follow_coeffs, sample_rate);
|
bw_env_follow_set_sample_rate(&coeffs->env_follow_coeffs, sample_rate);
|
||||||
bw_vol_set_sample_rate(&coeffs->vol_coeffs, sample_rate);
|
bw_gain_set_sample_rate(&coeffs->gain_coeffs, sample_rate);
|
||||||
bw_one_pole_set_sample_rate(&coeffs->smooth_coeffs, sample_rate);
|
bw_one_pole_set_sample_rate(&coeffs->smooth_coeffs, sample_rate);
|
||||||
bw_one_pole_reset_coeffs(&coeffs->smooth_coeffs);
|
bw_one_pole_reset_coeffs(&coeffs->smooth_coeffs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_comp_reset_coeffs(bw_comp_coeffs *BW_RESTRICT coeffs) {
|
static inline void bw_comp_reset_coeffs(bw_comp_coeffs *BW_RESTRICT coeffs) {
|
||||||
bw_env_follow_reset_coeffs(&coeffs->env_follow_coeffs);
|
bw_env_follow_reset_coeffs(&coeffs->env_follow_coeffs);
|
||||||
bw_vol_reset_coeffs(&coeffs->vol_coeffs);
|
bw_gain_reset_coeffs(&coeffs->gain_coeffs);
|
||||||
bw_one_pole_reset_state(&coeffs->smooth_coeffs, &coeffs->smooth_thresh_state, coeffs->thresh);
|
bw_one_pole_reset_state(&coeffs->smooth_coeffs, &coeffs->smooth_thresh_state, coeffs->thresh);
|
||||||
bw_one_pole_reset_state(&coeffs->smooth_coeffs, &coeffs->smooth_ratio_state, coeffs->ratio);
|
bw_one_pole_reset_state(&coeffs->smooth_coeffs, &coeffs->smooth_ratio_state, coeffs->ratio);
|
||||||
}
|
}
|
||||||
@ -231,12 +233,12 @@ static inline void bw_comp_reset_state(const bw_comp_coeffs *BW_RESTRICT coeffs,
|
|||||||
|
|
||||||
static inline void bw_comp_update_coeffs_ctrl(bw_comp_coeffs *BW_RESTRICT coeffs) {
|
static inline void bw_comp_update_coeffs_ctrl(bw_comp_coeffs *BW_RESTRICT coeffs) {
|
||||||
bw_env_follow_update_coeffs_ctrl(&coeffs->env_follow_coeffs);
|
bw_env_follow_update_coeffs_ctrl(&coeffs->env_follow_coeffs);
|
||||||
bw_vol_update_coeffs_ctrl(&coeffs->vol_coeffs);
|
bw_gain_update_coeffs_ctrl(&coeffs->gain_coeffs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_comp_update_coeffs_audio(bw_comp_coeffs *BW_RESTRICT coeffs) {
|
static inline void bw_comp_update_coeffs_audio(bw_comp_coeffs *BW_RESTRICT coeffs) {
|
||||||
bw_env_follow_update_coeffs_audio(&coeffs->env_follow_coeffs);
|
bw_env_follow_update_coeffs_audio(&coeffs->env_follow_coeffs);
|
||||||
bw_vol_update_coeffs_audio(&coeffs->vol_coeffs);
|
bw_gain_update_coeffs_audio(&coeffs->gain_coeffs);
|
||||||
bw_one_pole_process1(&coeffs->smooth_coeffs, &coeffs->smooth_thresh_state, coeffs->thresh);
|
bw_one_pole_process1(&coeffs->smooth_coeffs, &coeffs->smooth_thresh_state, coeffs->thresh);
|
||||||
coeffs->kc = 1.f - bw_one_pole_process1(&coeffs->smooth_coeffs, &coeffs->smooth_ratio_state, coeffs->ratio);
|
coeffs->kc = 1.f - bw_one_pole_process1(&coeffs->smooth_coeffs, &coeffs->smooth_ratio_state, coeffs->ratio);
|
||||||
}
|
}
|
||||||
@ -245,7 +247,7 @@ static inline float bw_comp_process1(const bw_comp_coeffs *BW_RESTRICT coeffs, b
|
|||||||
const float env = bw_env_follow_process1(&coeffs->env_follow_coeffs, &state->env_follow_state, x_sc);
|
const float env = bw_env_follow_process1(&coeffs->env_follow_coeffs, &state->env_follow_state, x_sc);
|
||||||
const float thresh = bw_one_pole_get_y_z1(&coeffs->smooth_thresh_state);
|
const float thresh = bw_one_pole_get_y_z1(&coeffs->smooth_thresh_state);
|
||||||
const float y = env > thresh ? bw_pow2f_3(coeffs->kc * bw_log2f_3(thresh * bw_rcpf_2(env))) * x : x;
|
const float y = env > thresh ? bw_pow2f_3(coeffs->kc * bw_log2f_3(thresh * bw_rcpf_2(env))) * x : x;
|
||||||
return bw_vol_process1(&coeffs->vol_coeffs, y);
|
return bw_gain_process1(&coeffs->gain_coeffs, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_comp_process(bw_comp_coeffs *BW_RESTRICT coeffs, bw_comp_state *BW_RESTRICT state, const float *x, const float *x_sc, float *y, int n_samples) {
|
static inline void bw_comp_process(bw_comp_coeffs *BW_RESTRICT coeffs, bw_comp_state *BW_RESTRICT state, const float *x, const float *x_sc, float *y, int n_samples) {
|
||||||
@ -277,11 +279,11 @@ static inline void bw_comp_set_release_tau(bw_comp_coeffs *BW_RESTRICT coeffs, f
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_comp_set_gain_lin(bw_comp_coeffs *BW_RESTRICT coeffs, float value) {
|
static inline void bw_comp_set_gain_lin(bw_comp_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
bw_vol_set_volume_lin(&coeffs->vol_coeffs, value);
|
bw_gain_set_gain_lin(&coeffs->gain_coeffs, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_comp_set_gain_dB(bw_comp_coeffs *BW_RESTRICT coeffs, float value) {
|
static inline void bw_comp_set_gain_dB(bw_comp_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
bw_vol_set_volume_dB(&coeffs->vol_coeffs, value);
|
bw_gain_set_gain_dB(&coeffs->gain_coeffs, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -23,13 +23,14 @@
|
|||||||
* version {{{ 0.3.0 }}}
|
* version {{{ 0.3.0 }}}
|
||||||
* requires {{{ bw_config bw_common bw_math bw_one_pole }}}
|
* requires {{{ bw_config bw_common bw_math bw_one_pole }}}
|
||||||
* description {{{
|
* description {{{
|
||||||
* Volume control.
|
* Gain.
|
||||||
* }}}
|
* }}}
|
||||||
* changelog {{{
|
* changelog {{{
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Version <strong>0.3.0</strong>:
|
* <li>Version <strong>0.3.0</strong>:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Changed volume parameter API to express values in linear gain
|
* <li>Renamed as bw_gain.</li>
|
||||||
|
* <li>Changed gain parameter API to express values in linear gain
|
||||||
* and dB.</li>
|
* and dB.</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* </li>
|
* </li>
|
||||||
@ -47,8 +48,8 @@
|
|||||||
* }}}
|
* }}}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _BW_VOL_H
|
#ifndef _BW_GAIN_H
|
||||||
#define _BW_VOL_H
|
#define _BW_GAIN_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -57,71 +58,70 @@ extern "C" {
|
|||||||
#include <bw_common.h>
|
#include <bw_common.h>
|
||||||
|
|
||||||
/*! api {{{
|
/*! api {{{
|
||||||
* #### bw_vol_coeffs
|
* #### bw_gain_coeffs
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
typedef struct _bw_vol_coeffs bw_vol_coeffs;
|
typedef struct _bw_gain_coeffs bw_gain_coeffs;
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Coefficients and related.
|
* Coefficients and related.
|
||||||
*
|
*
|
||||||
* #### bw_vol_init()
|
* #### bw_gain_init()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_vol_init(bw_vol_coeffs *BW_RESTRICT coeffs);
|
static inline void bw_gain_init(bw_gain_coeffs *BW_RESTRICT coeffs);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Initializes input parameter values in `coeffs`.
|
* Initializes input parameter values in `coeffs`.
|
||||||
*
|
*
|
||||||
* #### bw_vol_set_sample_rate()
|
* #### bw_gain_set_sample_rate()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_vol_set_sample_rate(bw_vol_coeffs *BW_RESTRICT coeffs, float sample_rate);
|
static inline void bw_gain_set_sample_rate(bw_gain_coeffs *BW_RESTRICT coeffs, float sample_rate);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the `sample_rate` (Hz) value in `coeffs`.
|
* Sets the `sample_rate` (Hz) value in `coeffs`.
|
||||||
*
|
*
|
||||||
* #### bw_vol_reset_coeffs()
|
* #### bw_gain_reset_coeffs()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_vol_reset_coeffs(bw_vol_coeffs *BW_RESTRICT coeffs);
|
static inline void bw_gain_reset_coeffs(bw_gain_coeffs *BW_RESTRICT coeffs);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Resets coefficients in `coeffs` to assume their target values.
|
* Resets coefficients in `coeffs` to assume their target values.
|
||||||
*
|
*
|
||||||
* #### bw_vol_update_coeffs_ctrl()
|
* #### bw_gain_update_coeffs_ctrl()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_vol_update_coeffs_ctrl(bw_vol_coeffs *BW_RESTRICT coeffs);
|
static inline void bw_gain_update_coeffs_ctrl(bw_gain_coeffs *BW_RESTRICT coeffs);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Triggers control-rate update of coefficients in `coeffs`.
|
* Triggers control-rate update of coefficients in `coeffs`.
|
||||||
*
|
*
|
||||||
* #### bw_vol_update_coeffs_audio()
|
* #### bw_gain_update_coeffs_audio()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_vol_update_coeffs_audio(bw_vol_coeffs *BW_RESTRICT coeffs);
|
static inline void bw_gain_update_coeffs_audio(bw_gain_coeffs *BW_RESTRICT coeffs);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Triggers audio-rate update of coefficients in `coeffs`.
|
* Triggers audio-rate update of coefficients in `coeffs`.
|
||||||
*
|
*
|
||||||
* #### bw_vol_process1()
|
* #### bw_gain_process1()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline float bw_vol_process1(const bw_vol_coeffs *BW_RESTRICT coeffs, float x);
|
static inline float bw_gain_process1(const bw_gain_coeffs *BW_RESTRICT coeffs, float x);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Processes one input sample `x` using `coeffs` and returns the
|
* Processes one input sample `x` using `coeffs` and returns the
|
||||||
* corresponding output sample.
|
* corresponding output sample.
|
||||||
*
|
*
|
||||||
* #### bw_vol_process()
|
* #### bw_gain_process()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_vol_process(bw_vol_coeffs *BW_RESTRICT coeffs, const float *x, float *y, int n_samples);
|
static inline void bw_gain_process(bw_gain_coeffs *BW_RESTRICT coeffs, const float *x, float *y, int n_samples);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Processes the first `n_samples` of the input buffer `x` and fills the
|
* Processes the first `n_samples` of the input buffer `x` and fills the
|
||||||
* first `n_samples` of the output buffer `y`, while using and updating
|
* first `n_samples` of the output buffer `y`, while using and updating
|
||||||
* `coeffs` (control and audio rate).
|
* `coeffs` (control and audio rate).
|
||||||
*
|
*
|
||||||
* #### bw_vol_set_volume_lin()
|
* #### bw_gain_set_gain_lin()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_vol_set_volume_lin(bw_vol_coeffs *BW_RESTRICT coeffs, float value);
|
static inline void bw_gain_set_gain_lin(bw_gain_coeffs *BW_RESTRICT coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the volume parameter to the given `value` (linear gain) in
|
* Sets the gain parameter to the given `value` (linear gain) in `coeffs`.
|
||||||
* `coeffs`.
|
|
||||||
*
|
*
|
||||||
* Default value: `1.f`.
|
* Default value: `1.f`.
|
||||||
*
|
*
|
||||||
* #### bw_vol_set_volume_dB()
|
* #### bw_gain_set_gain_dB()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_vol_set_volume_dB(bw_vol_coeffs *BW_RESTRICT coeffs, float value);
|
static inline void bw_gain_set_gain_dB(bw_gain_coeffs *BW_RESTRICT coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the volume parameter to the given `value` (dB) in `coeffs`.
|
* Sets the gain parameter to the given `value` (dB) in `coeffs`.
|
||||||
*
|
*
|
||||||
* Default value: `0.f`.
|
* Default value: `0.f`.
|
||||||
* }}} */
|
* }}} */
|
||||||
@ -134,54 +134,54 @@ static inline void bw_vol_set_volume_dB(bw_vol_coeffs *BW_RESTRICT coeffs, float
|
|||||||
#include <bw_math.h>
|
#include <bw_math.h>
|
||||||
#include <bw_one_pole.h>
|
#include <bw_one_pole.h>
|
||||||
|
|
||||||
struct _bw_vol_coeffs {
|
struct _bw_gain_coeffs {
|
||||||
// Sub-components
|
// Sub-components
|
||||||
bw_one_pole_coeffs smooth_coeffs;
|
bw_one_pole_coeffs smooth_coeffs;
|
||||||
bw_one_pole_state smooth_state;
|
bw_one_pole_state smooth_state;
|
||||||
|
|
||||||
// Parameters
|
// Parameters
|
||||||
float volume;
|
float gain;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void bw_vol_init(bw_vol_coeffs *BW_RESTRICT coeffs) {
|
static inline void bw_gain_init(bw_gain_coeffs *BW_RESTRICT coeffs) {
|
||||||
bw_one_pole_init(&coeffs->smooth_coeffs);
|
bw_one_pole_init(&coeffs->smooth_coeffs);
|
||||||
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.05f);
|
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.05f);
|
||||||
coeffs->volume = 1.f;
|
coeffs->gain = 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_vol_set_sample_rate(bw_vol_coeffs *BW_RESTRICT coeffs, float sample_rate) {
|
static inline void bw_gain_set_sample_rate(bw_gain_coeffs *BW_RESTRICT coeffs, float sample_rate) {
|
||||||
bw_one_pole_set_sample_rate(&coeffs->smooth_coeffs, sample_rate);
|
bw_one_pole_set_sample_rate(&coeffs->smooth_coeffs, sample_rate);
|
||||||
bw_one_pole_reset_coeffs(&coeffs->smooth_coeffs);
|
bw_one_pole_reset_coeffs(&coeffs->smooth_coeffs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_vol_reset_coeffs(bw_vol_coeffs *BW_RESTRICT coeffs) {
|
static inline void bw_gain_reset_coeffs(bw_gain_coeffs *BW_RESTRICT coeffs) {
|
||||||
bw_one_pole_reset_state(&coeffs->smooth_coeffs, &coeffs->smooth_state, coeffs->volume);
|
bw_one_pole_reset_state(&coeffs->smooth_coeffs, &coeffs->smooth_state, coeffs->gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_vol_update_coeffs_ctrl(bw_vol_coeffs *BW_RESTRICT coeffs) {
|
static inline void bw_gain_update_coeffs_ctrl(bw_gain_coeffs *BW_RESTRICT coeffs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_vol_update_coeffs_audio(bw_vol_coeffs *BW_RESTRICT coeffs) {
|
static inline void bw_gain_update_coeffs_audio(bw_gain_coeffs *BW_RESTRICT coeffs) {
|
||||||
bw_one_pole_process1(&coeffs->smooth_coeffs, &coeffs->smooth_state, coeffs->volume);
|
bw_one_pole_process1(&coeffs->smooth_coeffs, &coeffs->smooth_state, coeffs->gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline float bw_vol_process1(const bw_vol_coeffs *BW_RESTRICT coeffs, float x) {
|
static inline float bw_gain_process1(const bw_gain_coeffs *BW_RESTRICT coeffs, float x) {
|
||||||
return bw_one_pole_get_y_z1(&coeffs->smooth_state) * x;
|
return bw_one_pole_get_y_z1(&coeffs->smooth_state) * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_vol_process(bw_vol_coeffs *BW_RESTRICT coeffs, const float *x, float *y, int n_samples) {
|
static inline void bw_gain_process(bw_gain_coeffs *BW_RESTRICT coeffs, const float *x, float *y, int n_samples) {
|
||||||
for (int i = 0; i < n_samples; i++) {
|
for (int i = 0; i < n_samples; i++) {
|
||||||
bw_vol_update_coeffs_audio(coeffs);
|
bw_gain_update_coeffs_audio(coeffs);
|
||||||
y[i] = bw_vol_process1(coeffs, x[i]);
|
y[i] = bw_gain_process1(coeffs, x[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_vol_set_volume_lin(bw_vol_coeffs *BW_RESTRICT coeffs, float value) {
|
static inline void bw_gain_set_gain_lin(bw_gain_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
coeffs->volume = value;
|
coeffs->gain = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_vol_set_volume_dB(bw_vol_coeffs *BW_RESTRICT coeffs, float value) {
|
static inline void bw_gain_set_gain_dB(bw_gain_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
coeffs->volume = bw_dB2linf_3(value);
|
coeffs->gain = bw_dB2linf_3(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
215
include/bw_lowpass1.h
Normal file
215
include/bw_lowpass1.h
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* along with Brickworks. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* File author: Stefano D'Angelo
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* module_type {{{ dsp }}}
|
||||||
|
* version {{{ 0.3.0 }}}
|
||||||
|
* requires {{{ bw_config bw_common bw_math bw_one_pole }}}
|
||||||
|
* description {{{
|
||||||
|
* First-order lowpass filter (6 dB/oct) with unitary DC gain.
|
||||||
|
*
|
||||||
|
* This is better suited to filtering actual audio than
|
||||||
|
* [bw_one_pole](bw_one_pole).
|
||||||
|
* }}}
|
||||||
|
* changelog {{{
|
||||||
|
* <ul>
|
||||||
|
* <li>Version <strong>0.3.0</strong>:
|
||||||
|
* <ul>
|
||||||
|
* <li>First release.</li>
|
||||||
|
* </ul>
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
* }}}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BW_LOWPASS1_H
|
||||||
|
#define _BW_LOWPASS1_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <bw_common.h>
|
||||||
|
|
||||||
|
/*! api {{{
|
||||||
|
* #### bw_lowpass1_coeffs
|
||||||
|
* ```>>> */
|
||||||
|
typedef struct _bw_lowpass1_coeffs bw_lowpass1_coeffs;
|
||||||
|
/*! <<<```
|
||||||
|
* Coefficients and related.
|
||||||
|
*
|
||||||
|
* #### bw_lowpass1_state
|
||||||
|
* ```>>> */
|
||||||
|
typedef struct _bw_lowpass1_state bw_lowpass1_state;
|
||||||
|
/*! <<<```
|
||||||
|
* Internal state and related.
|
||||||
|
*
|
||||||
|
* #### bw_lowpass1_init()
|
||||||
|
* ```>>> */
|
||||||
|
static inline void bw_lowpass1_init(bw_lowpass1_coeffs *BW_RESTRICT coeffs);
|
||||||
|
/*! <<<```
|
||||||
|
* Initializes input parameter values in `coeffs`.
|
||||||
|
*
|
||||||
|
* #### bw_lowpass1_set_sample_rate()
|
||||||
|
* ```>>> */
|
||||||
|
static inline void bw_lowpass1_set_sample_rate(bw_lowpass1_coeffs *BW_RESTRICT coeffs, float sample_rate);
|
||||||
|
/*! <<<```
|
||||||
|
* Sets the `sample_rate` (Hz) value in `coeffs`.
|
||||||
|
*
|
||||||
|
* #### bw_lowpass1_reset_coeffs()
|
||||||
|
* ```>>> */
|
||||||
|
static inline void bw_lowpass1_reset_coeffs(bw_lowpass1_coeffs *BW_RESTRICT coeffs);
|
||||||
|
/*! <<<```
|
||||||
|
* Resets coefficients in `coeffs` to assume their target values.
|
||||||
|
*
|
||||||
|
* #### bw_lowpass1_reset_state()
|
||||||
|
* ```>>> */
|
||||||
|
static inline void bw_lowpass1_reset_state(const bw_lowpass1_coeffs *BW_RESTRICT coeffs, bw_lowpass1_state *BW_RESTRICT state);
|
||||||
|
/*! <<<```
|
||||||
|
* Resets the given `state` to its initial values using the given `coeffs`.
|
||||||
|
*
|
||||||
|
* #### bw_lowpass1_update_coeffs_ctrl()
|
||||||
|
* ```>>> */
|
||||||
|
static inline void bw_lowpass1_update_coeffs_ctrl(bw_lowpass1_coeffs *BW_RESTRICT coeffs);
|
||||||
|
/*! <<<```
|
||||||
|
* Triggers control-rate update of coefficients in `coeffs`.
|
||||||
|
*
|
||||||
|
* #### bw_lowpass1_update_coeffs_audio()
|
||||||
|
* ```>>> */
|
||||||
|
static inline void bw_lowpass1_update_coeffs_audio(bw_lowpass1_coeffs *BW_RESTRICT coeffs);
|
||||||
|
/*! <<<```
|
||||||
|
* Triggers audio-rate update of coefficients in `coeffs`.
|
||||||
|
*
|
||||||
|
* #### bw_lowpass1_process1()
|
||||||
|
* ```>>> */
|
||||||
|
static inline float bw_lowpass1_process1(const bw_lowpass1_coeffs *BW_RESTRICT coeffs, bw_lowpass1_state *BW_RESTRICT state, float x);
|
||||||
|
/*! <<<```
|
||||||
|
* Processes one input sample `x` using `coeffs`, while using and updating
|
||||||
|
* `state`. Returns the corresponding output sample.
|
||||||
|
*
|
||||||
|
* #### bw_lowpass1_process()
|
||||||
|
* ```>>> */
|
||||||
|
static inline void bw_lowpass1_process(bw_lowpass1_coeffs *BW_RESTRICT coeffs, bw_lowpass1_state *BW_RESTRICT state, const float *x, float *y, int n_samples);
|
||||||
|
/*! <<<```
|
||||||
|
* Processes the first `n_samples` of the input buffer `x` and fills the
|
||||||
|
* first `n_samples` of the output buffer `y`, while using and updating both
|
||||||
|
* `coeffs` and `state` (control and audio rate).
|
||||||
|
*
|
||||||
|
* #### bw_lowpass1_set_cutoff()
|
||||||
|
* ```>>> */
|
||||||
|
static inline void bw_lowpass1_set_cutoff(bw_lowpass1_coeffs *BW_RESTRICT coeffs, float value);
|
||||||
|
/*! <<<```
|
||||||
|
* Sets the cutoff frequency `value` (Hz) in `coeffs`.
|
||||||
|
*
|
||||||
|
* Default value: `1e3f`.
|
||||||
|
* }}} */
|
||||||
|
|
||||||
|
/*** 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>
|
||||||
|
#include <bw_one_pole.h>
|
||||||
|
|
||||||
|
struct _bw_lowpass1_coeffs {
|
||||||
|
// Sub-components
|
||||||
|
bw_one_pole_coeffs smooth_coeffs;
|
||||||
|
bw_one_pole_state smooth_state;
|
||||||
|
|
||||||
|
// Coefficients
|
||||||
|
float t_k;
|
||||||
|
|
||||||
|
// Parameters
|
||||||
|
float cutoff;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _bw_lowpass1_state {
|
||||||
|
float y_z1;
|
||||||
|
float X_z1;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void bw_lowpass1_init(bw_lowpass1_coeffs *BW_RESTRICT coeffs) {
|
||||||
|
bw_one_pole_init(&coeffs->smooth_coeffs);
|
||||||
|
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.005f);
|
||||||
|
bw_one_pole_set_sticky_thresh(&coeffs->smooth_coeffs, 1e-3f);
|
||||||
|
coeffs->cutoff = 1e3f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_lowpass1_set_sample_rate(bw_lowpass1_coeffs *BW_RESTRICT coeffs, float sample_rate) {
|
||||||
|
bw_one_pole_set_sample_rate(&coeffs->smooth_coeffs, sample_rate);
|
||||||
|
bw_one_pole_reset_coeffs(&coeffs->smooth_coeffs);
|
||||||
|
coeffs->t_k = 3.141592653589793f / sample_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _bw_lowpass1_do_update_coeffs(bw_svf_coeffs *BW_RESTRICT coeffs, char force) {
|
||||||
|
float cutoff_cur = bw_one_pole_get_y_z1(&coeffs->smooth_state);
|
||||||
|
const char cutoff_changed = force || coeffs->cutoff != cutoff_cur;
|
||||||
|
if (cutoff_changed) {
|
||||||
|
cutoff_cur = bw_one_pole_process1_sticky_rel(&coeffs->smooth_coeffs, &coeffs->smooth_cutoff_state, coeffs->cutoff);
|
||||||
|
coeffs->t = bw_tanf_3(coeffs->t_k * cutoff_cur);
|
||||||
|
const float k = bw_rcpf_2(1.f + coeffs->t);
|
||||||
|
coeffs->X_x = k * cutoff_cur;
|
||||||
|
coeffs->X_X_z1 = k * coeffs->t;
|
||||||
|
coeffs->y_X = bw_rcpf_2(cutoff_cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_lowpass1_reset_coeffs(bw_lowpass1_coeffs *BW_RESTRICT coeffs) {
|
||||||
|
bw_one_pole_reset_state(&coeffs->smooth_coeffs, &coeffs->smooth_state, coeffs->cutoff);
|
||||||
|
_bw_lowpass1_do_update_coeffs(coeffs, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_lowpass1_reset_state(const bw_lowpass1_coeffs *BW_RESTRICT coeffs, bw_lowpass1_state *BW_RESTRICT state) {
|
||||||
|
state->y_z1 = 0.f;
|
||||||
|
state->X_z1 = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_lowpass1_update_coeffs_ctrl(bw_lowpass1_coeffs *BW_RESTRICT coeffs) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_lowpass1_update_coeffs_audio(bw_lowpass1_coeffs *BW_RESTRICT coeffs) {
|
||||||
|
_bw_lowpass1_do_update_coeffs(coeffs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float bw_lowpass1_process1(const bw_lowpass1_coeffs *BW_RESTRICT coeffs, bw_lowpass1_state *BW_RESTRICT state, float x) {
|
||||||
|
const float X = coeffs->X_x * (x - state->y_z1) - coeffs->X_X_z1 * state->X_z1;
|
||||||
|
const float y = x - coeffs->y_f * X;
|
||||||
|
state->y_z1 = y;
|
||||||
|
state->X_z1 = X;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_lowpass1_process(bw_lowpass1_coeffs *BW_RESTRICT coeffs, bw_lowpass1_state *BW_RESTRICT state, const float *x, float *y, int n_samples) {
|
||||||
|
for (int i = 0; i < n_samples; i++) {
|
||||||
|
bw_lowpass1_update_coeffs_audio(coeffs);
|
||||||
|
y[i] = bw_lowpass1_process1(coeffs, state, x[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_lowpass1_set_cutoff(bw_lowpass1_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
|
coeffs->cutoff = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -25,6 +25,9 @@
|
|||||||
* description {{{
|
* description {{{
|
||||||
* One-pole (6 dB/oct) lowpass filter with unitary DC gain, separate attack
|
* One-pole (6 dB/oct) lowpass filter with unitary DC gain, separate attack
|
||||||
* and decay time constants, and sticky target-reach threshold.
|
* and decay time constants, and sticky target-reach threshold.
|
||||||
|
*
|
||||||
|
* This is better suited to implement smoothing than
|
||||||
|
* [bw_lowpass1](bw_lowpass1).
|
||||||
* }}}
|
* }}}
|
||||||
* changelog {{{
|
* changelog {{{
|
||||||
* <ul>
|
* <ul>
|
||||||
|
Loading…
Reference in New Issue
Block a user