a-EQ, a-Reverb: Tweaks to parameter smoothing
authorDamien Zammit <damien@zamaudio.com>
Thu, 14 Jul 2016 06:38:40 +0000 (16:38 +1000)
committerDamien Zammit <damien@zamaudio.com>
Thu, 14 Jul 2016 06:41:26 +0000 (16:41 +1000)
libs/plugins/a-eq.lv2/a-eq.c
libs/plugins/a-eq.lv2/a-eq.ttl.in
libs/plugins/a-reverb.lv2/a-reverb.c

index 8dd81673ef5210fa749901bcffa2737c04306117..8083d4742d20259965ec1fd9225027d0005e90ca 100644 (file)
@@ -32,6 +32,7 @@
 
 #define AEQ_URI        "urn:ardour:a-eq"
 #define BANDS  6
+#define SMALL  0.0001f
 
 #ifndef MIN
 #define MIN(A,B) ((A) < (B)) ? (A) : (B)
@@ -77,6 +78,11 @@ from_dB(double gdb) {
        return (exp(gdb/20.0*log(10.0)));
 }
 
+static inline bool
+is_eq(float a, float b) {
+       return (fabsf(a - b) < SMALL);
+}
+
 struct linear_svf {
        double g, k;
        double a[3];
@@ -142,8 +148,6 @@ instantiate(const LV2_Descriptor* descriptor,
        for (int i = 0; i < BANDS; i++)
                linear_svf_reset(&aeq->v_filter[i]);
 
-       // TODO initialize self->v_
-
        aeq->need_expose = true;
 #ifdef LV2_EXTENDED
        aeq->display = NULL;
@@ -370,6 +374,33 @@ static float run_linear_svf(struct linear_svf *self, float in)
        return (float)out;
 }
 
+static void set_params(LV2_Handle instance, int band) {
+       Aeq* aeq = (Aeq*)instance;
+
+       switch (band) {
+       case 0:
+               if (aeq->v_shelftogl > 0.5) {
+                       linear_svf_set_lowshelf(&aeq->v_filter[0], aeq->v_g[0], aeq->srate, aeq->v_f0[0], 0.7071068);
+               } else {
+                       linear_svf_set_hp(&aeq->v_filter[0], aeq->srate, aeq->v_f0[0], 0.7071068);
+               }
+               break;
+       case 1:
+       case 2:
+       case 3:
+       case 4:
+               linear_svf_set_peq(&aeq->v_filter[band], aeq->v_g[band], aeq->srate, aeq->v_f0[band], aeq->v_bw[band]);
+               break;
+       case 5:
+               if (aeq->v_shelftogh > 0.5) {
+                       linear_svf_set_highshelf(&aeq->v_filter[5], aeq->v_g[5], aeq->srate, aeq->v_f0[5], 0.7071068);
+               } else {
+                       linear_svf_set_lp(&aeq->v_filter[5], aeq->srate, aeq->v_f0[5], 0.7071068);
+               }
+               break;
+       }
+}
+
 static void
 run(LV2_Handle instance, uint32_t n_samples)
 {
@@ -378,65 +409,59 @@ run(LV2_Handle instance, uint32_t n_samples)
        const float* const input = aeq->input;
        float* const output = aeq->output;
 
-       float srate = aeq->srate;
        float in0, out;
        uint32_t i, j;
 
-       if (*(aeq->shelftogl) > 0.5) {
-               linear_svf_set_lowshelf(&aeq->v_filter[0], *(aeq->g[0]), srate, *(aeq->f0[0]), 0.7071068);
-       } else {
-               linear_svf_set_hp(&aeq->v_filter[0], srate, *(aeq->f0[0]), 0.7071068);
-       }
-       linear_svf_set_peq(&aeq->v_filter[1], *(aeq->g[1]), srate, *(aeq->f0[1]), *(aeq->bw[1]));
-       linear_svf_set_peq(&aeq->v_filter[2], *(aeq->g[2]), srate, *(aeq->f0[2]), *(aeq->bw[2]));
-       linear_svf_set_peq(&aeq->v_filter[3], *(aeq->g[3]), srate, *(aeq->f0[3]), *(aeq->bw[3]));
-       linear_svf_set_peq(&aeq->v_filter[4], *(aeq->g[4]), srate, *(aeq->f0[4]), *(aeq->bw[4]));
-
-       if (*(aeq->shelftogh) > 0.5) {
-               linear_svf_set_highshelf(&aeq->v_filter[5], *(aeq->g[5]), srate, *(aeq->f0[5]), 0.7071068);
-       } else {
-               linear_svf_set_lp(&aeq->v_filter[5], srate, *(aeq->f0[5]), 0.7071068);
-       }
+       // 15Hz time constant
+       const float tau = (1.0 - exp(-2.0 * M_PI * n_samples * 15. / aeq->srate));
 
        for (i = 0; i < n_samples; i++) {
                in0 = input[i];
                out = in0;
                for (j = 0; j < BANDS; j++) {
-                       if (*(aeq->filtog[j]) > 0.5)
-                               out = run_linear_svf(&aeq->v_filter[j], out);
+                       out = run_linear_svf(&aeq->v_filter[j], out);
                }
                output[i] = out * from_dB(*(aeq->master));
        }
 
        for (i = 0; i < BANDS; i++) {
-               if (aeq->v_f0[i] != *(aeq->f0[i])) {
-                       aeq->v_f0[i] = *(aeq->f0[i]);
-                       aeq->need_expose = true;
+               if (!is_eq(aeq->v_filtog[i], *aeq->filtog[i])) {
+                       aeq->v_filtog[i] = *(aeq->filtog[i]);
                }
-               if (aeq->v_g[i] != *(aeq->g[i])) {
-                       aeq->v_g[i] = *(aeq->g[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 (i != 0 && i != 5 && aeq->v_bw[i] != *(aeq->bw[i])) {
-                       aeq->v_bw[i] = *(aeq->bw[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;
+                       }
+               } 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->v_filtog[i] != *(aeq->filtog[i])) {
-                       aeq->v_filtog[i] = *(aeq->filtog[i]);
+               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 (aeq->v_shelftogl != *(aeq->shelftogl)) {
+               if (!is_eq(aeq->v_shelftogl, *aeq->shelftogl)) {
                        aeq->v_shelftogl = *(aeq->shelftogl);
                        aeq->need_expose = true;
                }
-               if (aeq->v_shelftogh != *(aeq->shelftogh)) {
+               if (!is_eq(aeq->v_shelftogh, *aeq->shelftogh)) {
                        aeq->v_shelftogh = *(aeq->shelftogh);
                        aeq->need_expose = true;
                }
-               if (aeq->v_master != *(aeq->master)) {
+               if (!is_eq(aeq->v_master, *aeq->master)) {
                        aeq->v_master = *(aeq->master);
                        aeq->need_expose = true;
                }
+               if (aeq->need_expose == true) {
+                       set_params(aeq, i);
+               }
        }
 
 #ifdef LV2_EXTENDED
@@ -540,53 +565,41 @@ calc_highshelf(Aeq* self, double omega) {
 #ifdef LV2_EXTENDED
 static float
 eq_curve (Aeq* self, float f) {
-       double complex response = 1.0;
+       double response = 1.0;
        double SR = (double)self->srate;
        double omega = f * 2. * M_PI / SR;
 
        // low
-       if (self->v_filtog[0]) {
-               if (self->v_shelftogl) {
-                       // lowshelf
-                       response *= calc_lowshelf(self, omega);
-               } else {
-                       // hp:
-                       response *= calc_highpass(self, omega);
-               }
+       if (self->v_shelftogl) {
+               // lowshelf
+               response *= calc_lowshelf(self, omega);
+       } else {
+               // hp:
+               response *= calc_highpass(self, omega);
        }
 
        // peq1:
-       if (self->v_filtog[1]) {
-               response *= calc_peq(self, 1, omega);
-       }
+       response *= calc_peq(self, 1, omega);
 
        // peq2:
-       if (self->v_filtog[2]) {
-               response *= calc_peq(self, 2, omega);
-       }
+       response *= calc_peq(self, 2, omega);
 
        // peq3:
-       if (self->v_filtog[3]) {
-               response *= calc_peq(self, 3, omega);
-       }
+       response *= calc_peq(self, 3, omega);
 
        // peq4:
-       if (self->v_filtog[4]) {
-               response *= calc_peq(self, 4, omega);
-       }
+       response *= calc_peq(self, 4, omega);
 
        // high
-       if (self->v_filtog[5]) {
-               if (self->v_shelftogh) {
-                       // highshelf:
-                       response *= calc_highshelf(self, omega);
-               } else {
-                       // lp:
-                       response *= calc_lowpass(self, omega);
-               }
+       if (self->v_shelftogh) {
+               // highshelf:
+               response *= calc_highshelf(self, omega);
+       } else {
+               // lp:
+               response *= calc_lowpass(self, omega);
        }
 
-       return response;
+       return (float)response;
 }
 
 static LV2_Inline_Display_Image_Surface *
index dcfc99db49dcbff0c00e5205312130c44a86bf3b..b7b4f50452cbb333469175e1e17b5cf2b66ffd08 100644 (file)
@@ -38,6 +38,8 @@ unit:hz0
         lv2:minimum 0.000000 ;
         lv2:maximum 1.000000 ;
         lv2:portProperty lv2:toggled ;
+        lv2:portProperty <http://lv2plug.in/ns/ext/port-props#causesArtifacts> ;
+        lv2:portProperty <http://lv2plug.in/ns/ext/port-props#notAutomatic> ;
     ],
     [
         a lv2:InputPort, lv2:ControlPort ;
@@ -193,6 +195,8 @@ unit:hz0
         lv2:minimum 0.000000 ;
         lv2:maximum 1.000000 ;
         lv2:portProperty lv2:toggled ;
+        lv2:portProperty <http://lv2plug.in/ns/ext/port-props#causesArtifacts> ;
+        lv2:portProperty <http://lv2plug.in/ns/ext/port-props#notAutomatic> ;
     ],
     [
         a lv2:InputPort, lv2:ControlPort ;
index 4c5251d217576c77fa9f886a13f84c4bc4c9e7ae..87637585d30171d8824837887b86b6d53913f2e6 100644 (file)
@@ -318,8 +318,8 @@ run (LV2_Handle instance, uint32_t n_samples)
        float* const      output0 = self->output0;
        float* const      output1 = self->output1;
 
-       // 25Hz update
-       const float tau = (1.0 - exp(-2.0 * M_PI * n_samples * 25 / self->srate));
+       // 15Hz time constant
+       const float tau = (1.0 - exp(-2.0 * M_PI * n_samples * 15. / self->srate));
 
        if (*self->mix != self->v_mix) {
                self->v_mix += tau * ( *self->mix - self->v_mix);