diff options
author | Robin Gareus <robin@gareus.org> | 2016-07-14 20:42:07 +0200 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2016-07-14 20:44:47 +0200 |
commit | 2b262dbfdd25808471244ddc0edede34f8230231 (patch) | |
tree | 62f6d3f70d87cf3cdea1074452b1ef024b45cdc3 /libs/plugins | |
parent | b620e5ab3fe49e96445f76af48dc88d445b10363 (diff) |
fix a-eq interpolation
Diffstat (limited to 'libs/plugins')
-rw-r--r-- | libs/plugins/a-eq.lv2/a-eq.c | 106 |
1 files changed, 66 insertions, 40 deletions
diff --git a/libs/plugins/a-eq.lv2/a-eq.c b/libs/plugins/a-eq.lv2/a-eq.c index a539c90825..bb9840d601 100644 --- a/libs/plugins/a-eq.lv2/a-eq.c +++ b/libs/plugins/a-eq.lv2/a-eq.c @@ -32,8 +32,6 @@ #define AEQ_URI "urn:ardour:a-eq" #define BANDS 6 -#define SMALL 0.0001f - #ifndef MIN #define MIN(A,B) ((A) < (B)) ? (A) : (B) #endif @@ -77,8 +75,8 @@ from_dB(double gdb) { } static inline bool -is_eq(float a, float b) { - return (fabsf(a - b) < SMALL); +is_eq(float a, float b, float small) { + return (fabsf(a - b) < small); } struct linear_svf { @@ -101,6 +99,7 @@ typedef struct { float* master; float srate; + float tau; float* input; float* output; @@ -109,7 +108,6 @@ typedef struct { float v_g[BANDS]; float v_bw[BANDS]; float v_f0[BANDS]; - float v_filtog[BANDS]; float v_master; bool need_expose; @@ -130,6 +128,7 @@ instantiate(const LV2_Descriptor* descriptor, { Aeq* aeq = (Aeq*)calloc(1, sizeof(Aeq)); aeq->srate = rate; + aeq->tau = (1.0 - exp(-2.0 * M_PI * 64 * 25. / aeq->srate)); // 25Hz time constant @ 64fpp #ifdef LV2_EXTENDED for (int i=0; features[i]; ++i) { @@ -353,51 +352,78 @@ run(LV2_Handle instance, uint32_t n_samples) const float* const input = aeq->input; float* const output = aeq->output; - float in0, out; - uint32_t i, j; + const float tau = aeq->tau; + uint32_t offset = 0; - // 15Hz time constant - const float tau = (1.0 - exp(-2.0 * M_PI * n_samples * 15. / aeq->srate)); + while (n_samples > 0) { + uint32_t block = n_samples; + bool any_changed = false; - for (i = 0; i < n_samples; i++) { - in0 = input[i]; - out = in0; - for (j = 0; j < BANDS; j++) { - out = run_linear_svf(&aeq->v_filter[j], out); + // TODO global en/disable + if (!is_eq(aeq->v_master, *aeq->master, 0.1)) { + aeq->v_master += tau * (*aeq->master - aeq->v_master); + any_changed = true; + } else { + aeq->v_master = *aeq->master; } - output[i] = out * from_dB(*(aeq->master)); - } - for (i = 0; i < BANDS; i++) { - if (!is_eq(aeq->v_filtog[i], *aeq->filtog[i])) { - aeq->v_filtog[i] = *(aeq->filtog[i]); - } - if (!is_eq(aeq->v_f0[i], *aeq->f0[i])) { - aeq->v_f0[i] += tau * (*aeq->f0[i] - aeq->v_f0[i]); - aeq->need_expose = true; - } - if (aeq->v_filtog[i] < 0.5) { - if (!is_eq(aeq->v_g[i], 0.f)) { - aeq->v_g[i] += tau * (0.0 - aeq->v_g[i]); - aeq->need_expose = true; + for (int i = 0; i < BANDS; ++i) { + bool changed = false; + + if (!is_eq(aeq->v_f0[i], *aeq->f0[i], 0.1)) { + aeq->v_f0[i] += tau * (*aeq->f0[i] - aeq->v_f0[i]); + changed = true; + } else { + aeq->v_f0[i] = *aeq->f0[i]; } - } else if (aeq->v_filtog[i] >= 0.5) { - if (!is_eq(aeq->v_g[i], *aeq->g[i])) { - aeq->v_g[i] += tau * (*aeq->g[i] - aeq->v_g[i]); - aeq->need_expose = true; + + if (*aeq->filtog[i] <= 0) { + if (!is_eq(aeq->v_g[i], 0.f, 0.05)) { + aeq->v_g[i] += tau * (0.0 - aeq->v_g[i]); + changed = true; + } else { + aeq->v_g[i] = 0.0; + } + } else { + if (!is_eq(aeq->v_g[i], *aeq->g[i], 0.05)) { + aeq->v_g[i] += tau * (*aeq->g[i] - aeq->v_g[i]); + changed = true; + } else { + aeq->v_g[i] = *aeq->g[i]; + } + } + + if (i != 0 && i != 5) { + if (!is_eq(aeq->v_bw[i], *aeq->bw[i], 0.001)) { + aeq->v_bw[i] += tau * (*aeq->bw[i] - aeq->v_bw[i]); + changed = true; + } else { + aeq->v_bw[i] = *aeq->bw[i]; + } + } + + if (changed) { + set_params(aeq, i); + any_changed = true; } } - if (i != 0 && i != 5 && !is_eq(aeq->v_bw[i], *aeq->bw[i])) { - aeq->v_bw[i] += tau * (*aeq->bw[i] - aeq->v_bw[i]); - aeq->need_expose = true; - } - if (!is_eq(aeq->v_master, *aeq->master)) { - aeq->v_master = *(aeq->master); + + if (any_changed) { aeq->need_expose = true; + block = MIN (64, n_samples); } - if (aeq->need_expose == true) { - set_params(aeq, i); + + for (uint32_t i = 0; i < block; ++i) { + float in0, out; + in0 = input[i + offset]; + out = in0; + for (uint32_t j = 0; j < BANDS; j++) { + out = run_linear_svf(&aeq->v_filter[j], out); + } + output[i + offset] = out * from_dB(*(aeq->master)); } + n_samples -= block; + offset += block; } #ifdef LV2_EXTENDED |