diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..791d824 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,7 @@ +0.2.0 +----- + Refactored API of DSP modules to avoid dynamic memory allocation. + +0.1.0 +----- + First release. diff --git a/examples/fx/src/bw_example_fx.c b/examples/fx/src/bw_example_fx.c index d58ffab..bb441d0 100644 --- a/examples/fx/src/bw_example_fx.c +++ b/examples/fx/src/bw_example_fx.c @@ -51,48 +51,36 @@ bw_example_fx bw_example_fx_new() { if (instance == NULL) return NULL; - instance->svf = bw_svf_new(); - if (instance->svf == NULL) { - BW_FREE(instance); - return NULL; - } + bw_svf_init(&instance->svf); + bw_env_follow_init(&instance->env_follow); - instance->env_follow = bw_env_follow_new(); - if (instance->env_follow == NULL) { - bw_svf_free(instance->svf); - BW_FREE(instance); - return NULL; - } - - bw_one_pole_set_cutoff_down(bw_env_follow_get_one_pole(instance->env_follow), 1.f); + bw_one_pole_set_cutoff_down(bw_env_follow_get_one_pole(&instance->env_follow), 1.f); return instance; } void bw_example_fx_free(bw_example_fx instance) { - bw_env_follow_free(instance->env_follow); - bw_svf_free(instance->svf); BW_FREE(instance); } void bw_example_fx_set_sample_rate(bw_example_fx instance, float sample_rate) { - bw_svf_set_sample_rate(instance->svf, sample_rate); - bw_env_follow_set_sample_rate(instance->env_follow, sample_rate); + bw_svf_set_sample_rate(&instance->svf, sample_rate); + bw_env_follow_set_sample_rate(&instance->env_follow, sample_rate); } void bw_example_fx_reset(bw_example_fx instance) { - bw_svf_reset(instance->svf); - bw_env_follow_reset(instance->env_follow); + bw_svf_reset(&instance->svf); + bw_env_follow_reset(&instance->env_follow); } void bw_example_fx_process(bw_example_fx instance, const float** x, float** y, int n_samples) { float a[n_samples]; - bw_svf_process(instance->svf, x[0], y[0], NULL, NULL, n_samples); + bw_svf_process(&instance->svf, x[0], y[0], NULL, NULL, n_samples); for (int i = 0; i < n_samples; i += BUFFER_SIZE) { const uint32_t n = bw_minu32(n_samples - i, BUFFER_SIZE); - bw_env_follow_process(instance->env_follow, y[0] + i, instance->buf, n); + bw_env_follow_process(&instance->env_follow, y[0] + i, instance->buf, n); instance->level = instance->buf[i + n - 1]; } } @@ -100,10 +88,10 @@ void bw_example_fx_process(bw_example_fx instance, const float** x, float** y, i void bw_example_fx_set_parameter(bw_example_fx instance, int index, float value) { switch (index) { case p_cutoff: - bw_svf_set_cutoff(instance->svf, (20e3f - 20.f) * value * value * value + 20.f); + bw_svf_set_cutoff(&instance->svf, (20e3f - 20.f) * value * value * value + 20.f); break; case p_Q: - bw_svf_set_Q(instance->svf, 0.5f + 9.5f * value); + bw_svf_set_Q(&instance->svf, 0.5f + 9.5f * value); break; } } diff --git a/examples/fx/src/config.h b/examples/fx/src/config.h index 5b395b6..aa0086c 100644 --- a/examples/fx/src/config.h +++ b/examples/fx/src/config.h @@ -50,7 +50,7 @@ struct config_parameter { #define COMPANY_MAILTO "mailto:info@orastron.com" #define PLUGIN_NAME "bw_example_fx" -#define PLUGIN_VERSION "0.1.0" +#define PLUGIN_VERSION "0.2.0" #define NUM_BUSES_IN 1 #define NUM_BUSES_OUT 1 diff --git a/examples/synth/src/bw_example_synth.c b/examples/synth/src/bw_example_synth.c index 7c296a5..beef66e 100644 --- a/examples/synth/src/bw_example_synth.c +++ b/examples/synth/src/bw_example_synth.c @@ -48,7 +48,7 @@ struct _bw_example_synth { // Sub-components bw_phase_gen phase_gen; bw_osc_pulse osc_pulse; - bw_osc_filt osc_filt; + bw_osc_filt osc_filt; bw_svf svf; bw_env_gen env_gen; bw_vol vol; @@ -70,108 +70,65 @@ bw_example_synth bw_example_synth_new() { if (instance == NULL) return NULL; - instance->phase_gen = bw_phase_gen_new(); - if (instance->phase_gen == NULL) - goto err_phase_gen; + bw_phase_gen_init(&instance->phase_gen); + 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_vol_init(&instance->vol); + bw_env_follow_init(&instance->env_follow); - instance->osc_pulse = bw_osc_pulse_new(); - if (instance->osc_pulse == NULL) - goto err_osc_pulse; - - instance->osc_filt = bw_osc_filt_new(); - if (instance->osc_filt == NULL) - goto err_osc_filt; - - instance->svf = bw_svf_new(); - if (instance->svf == NULL) - goto err_svf; - - instance->env_gen = bw_env_gen_new(); - if (instance->env_gen == NULL) - goto err_env_gen; - - instance->vol = bw_vol_new(); - if (instance->vol == NULL) - goto err_vol; - - instance->env_follow = bw_env_follow_new(); - if (instance->env_follow == NULL) - goto err_env_follow; - - bw_osc_pulse_set_antialiasing(instance->osc_pulse, 1); - bw_one_pole_set_cutoff_down(bw_env_follow_get_one_pole(instance->env_follow), 1.f); + bw_osc_pulse_set_antialiasing(&instance->osc_pulse, 1); + bw_one_pole_set_cutoff_down(bw_env_follow_get_one_pole(&instance->env_follow), 1.f); return instance; - -err_env_follow: - bw_vol_free(instance->vol); -err_vol: - bw_env_gen_free(instance->env_gen); -err_env_gen: - bw_svf_free(instance->svf); -err_svf: - bw_osc_filt_free(instance->osc_filt); -err_osc_filt: - bw_osc_pulse_free(instance->osc_pulse); -err_osc_pulse: - bw_phase_gen_free(instance->phase_gen); -err_phase_gen: - BW_FREE(instance); - return NULL; } void bw_example_synth_free(bw_example_synth instance) { - bw_env_follow_free(instance->env_follow); - bw_vol_free(instance->vol); - bw_env_gen_free(instance->env_gen); - bw_svf_free(instance->svf); - bw_osc_filt_free(instance->osc_filt); - bw_osc_pulse_free(instance->osc_pulse); - bw_phase_gen_free(instance->phase_gen); BW_FREE(instance); } void bw_example_synth_set_sample_rate(bw_example_synth instance, float sample_rate) { - bw_phase_gen_set_sample_rate(instance->phase_gen, sample_rate); - bw_osc_pulse_set_sample_rate(instance->osc_pulse, sample_rate); - bw_svf_set_sample_rate(instance->svf, sample_rate); - bw_env_gen_set_sample_rate(instance->env_gen, sample_rate); - bw_vol_set_sample_rate(instance->vol, sample_rate); - bw_env_follow_set_sample_rate(instance->env_follow, sample_rate); + bw_phase_gen_set_sample_rate(&instance->phase_gen, sample_rate); + bw_osc_pulse_set_sample_rate(&instance->osc_pulse, sample_rate); + bw_svf_set_sample_rate(&instance->svf, sample_rate); + bw_env_gen_set_sample_rate(&instance->env_gen, sample_rate); + bw_vol_set_sample_rate(&instance->vol, sample_rate); + bw_env_follow_set_sample_rate(&instance->env_follow, sample_rate); } void bw_example_synth_reset(bw_example_synth instance) { - bw_phase_gen_reset(instance->phase_gen); - bw_osc_pulse_reset(instance->osc_pulse); - bw_osc_filt_reset(instance->osc_filt); - bw_svf_reset(instance->svf); - bw_env_gen_reset(instance->env_gen); - bw_vol_reset(instance->vol); - bw_env_follow_reset(instance->env_follow); + bw_phase_gen_reset(&instance->phase_gen); + bw_osc_pulse_reset(&instance->osc_pulse); + bw_osc_filt_reset(&instance->osc_filt); + bw_svf_reset(&instance->svf); + bw_env_gen_reset(&instance->env_gen); + bw_vol_reset(&instance->vol); + bw_env_follow_reset(&instance->env_follow); instance->note = -1; } 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) { - bw_phase_gen_set_frequency(instance->phase_gen, + bw_phase_gen_set_frequency(&instance->phase_gen, 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); + bw_env_gen_set_gate(&instance->env_gen, 1); } else - bw_env_gen_set_gate(instance->env_gen, 0); + bw_env_gen_set_gate(&instance->env_gen, 0); for (int i = 0; i < n_samples; i += BUFFER_SIZE) { float *out = y[0] + i; const uint32_t n = bw_minu32(n_samples - i, BUFFER_SIZE); - bw_phase_gen_process(instance->phase_gen, NULL, out, instance->buf, n); - bw_osc_pulse_process(instance->osc_pulse, out, instance->buf, out, n); - bw_osc_filt_process(instance->osc_filt, out, out, n); - bw_svf_process(instance->svf, out, out, NULL, NULL, n); - bw_env_gen_process(instance->env_gen, instance->buf, n); + bw_phase_gen_process(&instance->phase_gen, NULL, out, instance->buf, n); + bw_osc_pulse_process(&instance->osc_pulse, out, instance->buf, out, n); + bw_osc_filt_process(&instance->osc_filt, out, out, n); + bw_svf_process(&instance->svf, out, out, NULL, NULL, n); + bw_env_gen_process(&instance->env_gen, instance->buf, n); for (int j = 0; j < n; j++) out[j] *= instance->buf[j]; - bw_vol_process(instance->vol, (const float **)&out, &out, 1, n); - bw_env_follow_process(instance->env_follow, out, instance->buf, n); + bw_vol_process(&instance->vol, (const float **)&out, &out, 1, n); + bw_env_follow_process(&instance->env_follow, out, instance->buf, n); instance->level = instance->buf[i + n - 1]; } } @@ -179,34 +136,34 @@ void bw_example_synth_process(bw_example_synth instance, const float** x, float* void bw_example_synth_set_parameter(bw_example_synth instance, int index, float value) { switch (index) { case p_volume: - bw_vol_set_volume(instance->vol, value); + bw_vol_set_volume(&instance->vol, value); break; case p_master_tune: instance->params[p_master_tune] = value; break; case p_portamento: - bw_phase_gen_set_portamento_tau(instance->phase_gen, value); + bw_phase_gen_set_portamento_tau(&instance->phase_gen, value); break; case p_pulse_width: - bw_osc_pulse_set_pulse_width(instance->osc_pulse, value); + bw_osc_pulse_set_pulse_width(&instance->osc_pulse, value); break; case p_cutoff: - bw_svf_set_cutoff(instance->svf, 20.f + (20e3f - 20.f) * value * value * value); + bw_svf_set_cutoff(&instance->svf, 20.f + (20e3f - 20.f) * value * value * value); break; case p_Q: - bw_svf_set_Q(instance->svf, 0.5f + 9.5f * value); + bw_svf_set_Q(&instance->svf, 0.5f + 9.5f * value); break; case p_attack: - bw_env_gen_set_attack(instance->env_gen, value); + bw_env_gen_set_attack(&instance->env_gen, value); break; case p_decay: - bw_env_gen_set_decay(instance->env_gen, value); + bw_env_gen_set_decay(&instance->env_gen, value); break; case p_sustain: - bw_env_gen_set_sustain(instance->env_gen, value); + bw_env_gen_set_sustain(&instance->env_gen, value); break; case p_release: - bw_env_gen_set_release(instance->env_gen, value); + bw_env_gen_set_release(&instance->env_gen, value); break; } } diff --git a/examples/synth/src/config.h b/examples/synth/src/config.h index 23d58c6..e69eae4 100644 --- a/examples/synth/src/config.h +++ b/examples/synth/src/config.h @@ -50,7 +50,7 @@ struct config_parameter { #define COMPANY_MAILTO "mailto:info@orastron.com" #define PLUGIN_NAME "bw_example_synth" -#define PLUGIN_VERSION "0.1.0" +#define PLUGIN_VERSION "0.2.0" #define NUM_BUSES_IN 0 #define NUM_BUSES_OUT 1 diff --git a/include/bw_env_follow.h b/include/bw_env_follow.h index d57d8d7..1b47aa2 100644 --- a/include/bw_env_follow.h +++ b/include/bw_env_follow.h @@ -19,7 +19,7 @@ /*! * module_type {{{ dsp }}} - * version {{{ 0.1.0 }}} + * version {{{ 0.2.0 }}} * requires {{{ bw_config bw_common bw_math bw_one_pole }}} * description {{{ * Envelope follower made of a full-wave rectifier followed by @@ -30,6 +30,11 @@ * }}} * changelog {{{ *