From 7b65b75d925d948589c52031cc464cbad8c6555a Mon Sep 17 00:00:00 2001 From: Stefano D'Angelo Date: Fri, 15 Sep 2023 16:27:04 +0200 Subject: [PATCH] finalized bw_noise_gate + examples + fix bw_{comp,one_pole,slew_lim} + better bw_rcpf() doc --- README.md | 2 +- .../src/bw_example_fx_noise_gate.c | 2 +- examples/fx_noise_gate/vst3/Makefile | 3 + examples/fxpp_noise_gate/vst3/Makefile | 3 + include/bw_comp.h | 44 +- include/bw_math.h | 2 +- include/bw_noise_gate.h | 644 +++++++++++++++--- include/bw_one_pole.h | 4 +- include/bw_slew_lim.h | 8 +- 9 files changed, 595 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index be7152f..00f9317 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ You can find information and documentation [on the official web page](https://ww ## Subfolders -* examples: synth and an effect examples in VST3, Web Audio, and Daisy Seed formats; +* examples: synth and an effect examples in VST3, Web Audio, Daisy Seed, Android ap appp, and iOS app formats; * include: header files. ## Legal diff --git a/examples/fx_noise_gate/src/bw_example_fx_noise_gate.c b/examples/fx_noise_gate/src/bw_example_fx_noise_gate.c index 072f71c..7f8aab9 100644 --- a/examples/fx_noise_gate/src/bw_example_fx_noise_gate.c +++ b/examples/fx_noise_gate/src/bw_example_fx_noise_gate.c @@ -30,7 +30,7 @@ void bw_example_fx_noise_gate_set_sample_rate(bw_example_fx_noise_gate *instance void bw_example_fx_noise_gate_reset(bw_example_fx_noise_gate *instance) { bw_noise_gate_reset_coeffs(&instance->noise_gate_coeffs); - bw_noise_gate_reset_state(&instance->noise_gate_coeffs, &instance->noise_gate_state); + bw_noise_gate_reset_state(&instance->noise_gate_coeffs, &instance->noise_gate_state, 0.f, 0.f); } void bw_example_fx_noise_gate_process(bw_example_fx_noise_gate *instance, const float** x, float** y, int n_samples) { diff --git a/examples/fx_noise_gate/vst3/Makefile b/examples/fx_noise_gate/vst3/Makefile index bb6a30a..46b3460 100644 --- a/examples/fx_noise_gate/vst3/Makefile +++ b/examples/fx_noise_gate/vst3/Makefile @@ -4,3 +4,6 @@ NAME := bw_example_fx_noise_gate SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_noise_gate.c include ${ROOT_DIR}/../../common/vst3/vst3.mk + +CXXFLAGS += -DRELEASE=1 -DNDEBUG -DBW_NO_DEBUG +#CXXFLAGS += -DDEVELOPMENT=1 -DBW_DEBUG_DEEP diff --git a/examples/fxpp_noise_gate/vst3/Makefile b/examples/fxpp_noise_gate/vst3/Makefile index b46c61e..1ee4032 100644 --- a/examples/fxpp_noise_gate/vst3/Makefile +++ b/examples/fxpp_noise_gate/vst3/Makefile @@ -4,3 +4,6 @@ NAME := bw_example_fxpp_noise_gate SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fxpp_noise_gate.cpp include ${ROOT_DIR}/../../common/vst3/vst3.mk + +CXXFLAGS += -DRELEASE=1 -DNDEBUG -DBW_NO_DEBUG +#CXXFLAGS += -DDEVELOPMENT=1 -DBW_DEBUG_DEEP diff --git a/include/bw_comp.h b/include/bw_comp.h index 44799c7..1248a57 100644 --- a/include/bw_comp.h +++ b/include/bw_comp.h @@ -46,6 +46,9 @@ *
  • Added overloaded C++ process() function taking * C-style arrays as arguments.
  • *
  • Fixed missing smoothing filter initialization.
  • + *
  • Fixed missing forced coefficients' update in + * bw_comp_reset_coeffs().
  • + *
  • Improved and strengthened algorithm.
  • *
  • Removed usage of reserved identifiers.
  • *
  • Clearly specified parameter validity ranges.
  • *
  • Added debugging code.
  • @@ -364,6 +367,7 @@ struct bw_comp_coeffs { // Coefficients float kc; + float lt; // Parameters float thresh; @@ -420,6 +424,15 @@ static inline void bw_comp_set_sample_rate( BW_ASSERT_DEEP(coeffs->state == bw_comp_coeffs_state_set_sample_rate); } +static inline void bw_comp_do_update_coeffs_audio( + bw_comp_coeffs * BW_RESTRICT coeffs) { + bw_env_follow_update_coeffs_audio(&coeffs->env_follow_coeffs); + bw_gain_update_coeffs_audio(&coeffs->gain_coeffs); + 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->lt = bw_log2f(bw_one_pole_get_y_z1(&coeffs->smooth_thresh_state)); +} + static inline void bw_comp_reset_coeffs( bw_comp_coeffs * BW_RESTRICT coeffs) { BW_ASSERT(coeffs != NULL); @@ -430,6 +443,7 @@ static inline void bw_comp_reset_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_ratio_state, coeffs->ratio); + bw_comp_do_update_coeffs_audio(coeffs); #ifdef BW_DEBUG_DEEP coeffs->state = bw_comp_coeffs_state_reset_coeffs; @@ -449,19 +463,10 @@ static inline float bw_comp_reset_state( BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs); BW_ASSERT(state != NULL); BW_ASSERT(bw_is_finite(x_0)); + BW_ASSERT(bw_is_finite(x_sc_0)); const float env = bw_env_follow_reset_state(&coeffs->env_follow_coeffs, &state->env_follow_state, x_sc_0); - const float thresh = bw_one_pole_get_y_z1(&coeffs->smooth_thresh_state); - float y; - if (env > thresh) { - float v = thresh * bw_rcpf(env); - if (v >= 1.175494350822287e-38f) { - v = coeffs->kc * bw_log2f(v); - y = v > -126.f ? bw_pow2f(v) * x_0 : thresh; - } else - y = thresh; - } else - y = x_0; + float y = env > bw_one_pole_get_y_z1(&coeffs->smooth_thresh_state) ? bw_pow2f(coeffs->kc * (coeffs->lt - bw_log2f(env))) * x_0 : x_0; y = bw_gain_get_gain_cur(&coeffs->gain_coeffs) * y; #ifdef BW_DEBUG_DEEP @@ -526,6 +531,7 @@ static inline void bw_comp_update_coeffs_audio( bw_gain_update_coeffs_audio(&coeffs->gain_coeffs); 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->lt = bw_log2f(bw_one_pole_get_y_z1(&coeffs->smooth_thresh_state)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs); @@ -545,17 +551,7 @@ static inline float bw_comp_process1( BW_ASSERT(bw_is_finite(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); - float y; - if (env > thresh) { - float v = thresh * bw_rcpf(env); - if (v >= 1.175494350822287e-38f) { - v = coeffs->kc * bw_log2f(v); - y = v > -126.f ? bw_pow2f(v) * x : thresh; - } else - y = thresh; - } else - y = x; + float y = env > bw_one_pole_get_y_z1(&coeffs->smooth_thresh_state) ? bw_pow2f(coeffs->kc * (coeffs->lt - bw_log2f(env))) * x : x; y = bw_gain_process1(&coeffs->gain_coeffs, y); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); @@ -580,6 +576,8 @@ static inline void bw_comp_process( BW_ASSERT_DEEP(bw_comp_state_is_valid(coeffs, state)); BW_ASSERT(x != NULL); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); + BW_ASSERT(x_sc != NULL); + BW_ASSERT_DEEP(bw_has_only_finite(x_sc, n_samples)); BW_ASSERT(y != NULL); bw_comp_update_coeffs_ctrl(coeffs); @@ -748,6 +746,8 @@ static inline char bw_comp_coeffs_is_valid( if (coeffs->state >= bw_comp_coeffs_state_reset_coeffs) { if (!bw_is_finite(coeffs->kc) || coeffs->kc < 0.f || coeffs->kc > 1.f) return 0; + if (!bw_is_finite(coeffs->lt)) + return 0; if (!bw_one_pole_state_is_valid(&coeffs->smooth_coeffs, &coeffs->smooth_thresh_state)) return 0; diff --git a/include/bw_math.h b/include/bw_math.h index 3f706e9..6cfa6f6 100644 --- a/include/bw_math.h +++ b/include/bw_math.h @@ -307,7 +307,7 @@ static inline float bw_rcpf( /*! <<<``` * Returns the reciprocal of `x` (i.e., `1.f / x`). * - * |`x`| must be in [2^-90, 2^90]. + * |`x`| must be in [`8.077935669463161e-28f`, `1.237940039285380e+27`]. * * Relative error < 0.0013%. * diff --git a/include/bw_noise_gate.h b/include/bw_noise_gate.h index b07ddc4..0af77b8 100644 --- a/include/bw_noise_gate.h +++ b/include/bw_noise_gate.h @@ -29,6 +29,12 @@ *