fix a-eq interpolation

This commit is contained in:
Robin Gareus 2016-07-14 20:42:07 +02:00
parent b620e5ab3f
commit 2b262dbfdd

View file

@ -32,8 +32,6 @@
#define AEQ_URI "urn:ardour:a-eq" #define AEQ_URI "urn:ardour:a-eq"
#define BANDS 6 #define BANDS 6
#define SMALL 0.0001f
#ifndef MIN #ifndef MIN
#define MIN(A,B) ((A) < (B)) ? (A) : (B) #define MIN(A,B) ((A) < (B)) ? (A) : (B)
#endif #endif
@ -77,8 +75,8 @@ from_dB(double gdb) {
} }
static inline bool static inline bool
is_eq(float a, float b) { is_eq(float a, float b, float small) {
return (fabsf(a - b) < SMALL); return (fabsf(a - b) < small);
} }
struct linear_svf { struct linear_svf {
@ -101,6 +99,7 @@ typedef struct {
float* master; float* master;
float srate; float srate;
float tau;
float* input; float* input;
float* output; float* output;
@ -109,7 +108,6 @@ typedef struct {
float v_g[BANDS]; float v_g[BANDS];
float v_bw[BANDS]; float v_bw[BANDS];
float v_f0[BANDS]; float v_f0[BANDS];
float v_filtog[BANDS];
float v_master; float v_master;
bool need_expose; bool need_expose;
@ -130,6 +128,7 @@ instantiate(const LV2_Descriptor* descriptor,
{ {
Aeq* aeq = (Aeq*)calloc(1, sizeof(Aeq)); Aeq* aeq = (Aeq*)calloc(1, sizeof(Aeq));
aeq->srate = rate; aeq->srate = rate;
aeq->tau = (1.0 - exp(-2.0 * M_PI * 64 * 25. / aeq->srate)); // 25Hz time constant @ 64fpp
#ifdef LV2_EXTENDED #ifdef LV2_EXTENDED
for (int i=0; features[i]; ++i) { 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; const float* const input = aeq->input;
float* const output = aeq->output; float* const output = aeq->output;
float in0, out; const float tau = aeq->tau;
uint32_t i, j; uint32_t offset = 0;
// 15Hz time constant while (n_samples > 0) {
const float tau = (1.0 - exp(-2.0 * M_PI * n_samples * 15. / aeq->srate)); uint32_t block = n_samples;
bool any_changed = false;
for (i = 0; i < n_samples; i++) { // TODO global en/disable
in0 = input[i]; if (!is_eq(aeq->v_master, *aeq->master, 0.1)) {
out = in0; aeq->v_master += tau * (*aeq->master - aeq->v_master);
for (j = 0; j < BANDS; j++) { any_changed = true;
out = run_linear_svf(&aeq->v_filter[j], out); } else {
aeq->v_master = *aeq->master;
} }
output[i] = out * from_dB(*(aeq->master));
}
for (i = 0; i < BANDS; i++) { for (int i = 0; i < BANDS; ++i) {
if (!is_eq(aeq->v_filtog[i], *aeq->filtog[i])) { bool changed = false;
aeq->v_filtog[i] = *(aeq->filtog[i]);
} if (!is_eq(aeq->v_f0[i], *aeq->f0[i], 0.1)) {
if (!is_eq(aeq->v_f0[i], *aeq->f0[i])) { aeq->v_f0[i] += tau * (*aeq->f0[i] - aeq->v_f0[i]);
aeq->v_f0[i] += tau * (*aeq->f0[i] - aeq->v_f0[i]); changed = true;
aeq->need_expose = true; } else {
} aeq->v_f0[i] = *aeq->f0[i];
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;
} }
} else if (aeq->v_filtog[i] >= 0.5) {
if (!is_eq(aeq->v_g[i], *aeq->g[i])) { if (*aeq->filtog[i] <= 0) {
aeq->v_g[i] += tau * (*aeq->g[i] - aeq->v_g[i]); if (!is_eq(aeq->v_g[i], 0.f, 0.05)) {
aeq->need_expose = true; 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]); if (any_changed) {
aeq->need_expose = true; aeq->need_expose = true;
block = MIN (64, n_samples);
} }
if (!is_eq(aeq->v_master, *aeq->master)) {
aeq->v_master = *(aeq->master); for (uint32_t i = 0; i < block; ++i) {
aeq->need_expose = true; float in0, out;
} in0 = input[i + offset];
if (aeq->need_expose == true) { out = in0;
set_params(aeq, i); 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 #ifdef LV2_EXTENDED