summaryrefslogtreecommitdiff
path: root/libs/plugins
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2016-07-14 02:03:08 +1000
committerDamien Zammit <damien@zamaudio.com>2016-07-14 02:03:08 +1000
commit0fdbbac99dfcbb23c1df1bdca89254af84954685 (patch)
tree41a40646a791f1ec3a6508d0efd4dbd52cdfb90e /libs/plugins
parent0b3d09b01151990252c3b79ac2098ee91387c455 (diff)
a-EQ: Tidy transfer function calculation
Diffstat (limited to 'libs/plugins')
-rw-r--r--libs/plugins/a-eq.lv2/a-eq.c149
1 files changed, 101 insertions, 48 deletions
diff --git a/libs/plugins/a-eq.lv2/a-eq.c b/libs/plugins/a-eq.lv2/a-eq.c
index dd49909242..fb799d8d8e 100644
--- a/libs/plugins/a-eq.lv2/a-eq.c
+++ b/libs/plugins/a-eq.lv2/a-eq.c
@@ -130,7 +130,7 @@ instantiate(const LV2_Descriptor* descriptor,
{
Aeq* aeq = (Aeq*)calloc(1, sizeof(Aeq));
aeq->srate = rate;
-
+
#ifdef LV2_EXTENDED
for (int i=0; features[i]; ++i) {
if (!strcmp(features[i]->URI, LV2_INLINEDISPLAY__queue_draw)) {
@@ -447,93 +447,146 @@ run(LV2_Handle instance, uint32_t n_samples)
#endif
}
+static double
+calc_peq(Aeq* self, int i, double omega) {
+ double complex H = 0.0;
+ double complex z = cexp(I * omega);
+ double complex zz = cexp(2. * I * omega);
+ double complex zm = z - 1.0;
+ double complex zp = z + 1.0;
+ double complex zzm = zz - 1.0;
-#ifdef LV2_EXTENDED
-static float
-eq_curve (Aeq* self, float f) {
- float SR = self->srate;
- double complex H = 1.0;
- double theta = f * 2. * M_PI / SR;
- double complex z = cexp(I * theta);
- double complex zz = cexp(2 * I * theta);
+ double A = pow(10.0, self->v_g[i]/40.0);
+ double g = self->v_filter[i].g;
+ double k = self->v_filter[i].k;
+ double m1 = k * (A * A - 1.0) / A;
+
+ H = (g*k*zzm + A*(g*zp*(m1*zm) + (zm*zm + g*g*zp*zp))) / (g*k*zzm + A*(zm*zm + g*g*zp*zp));
+ return cabs(H);
+}
+
+static double
+calc_lowpass(Aeq* self, double omega) {
+ double complex H = 0.0;
+ double complex z = cexp(I * omega);
+ double complex zz = cexp(2. * I * omega);
double complex zm = z - 1.0;
double complex zp = z + 1.0;
double complex zzm = zz - 1.0;
- double A;
- double m0, m1, m2, g, k;
+ double g = self->v_filter[5].g;
+ double k = self->v_filter[5].k;
+
+ H = (g*g*zp*zp) / (zm*zm + g*g*zp*zp + g*k*zzm);
+ return cabs(H);
+}
+
+static double
+calc_highpass(Aeq* self, double omega) {
+ double complex H = 0.0;
+ double complex z = cexp(I * omega);
+ double complex zz = cexp(2. * I * omega);
+ double complex zm = z - 1.0;
+ double complex zp = z + 1.0;
+ double complex zzm = zz - 1.0;
+
+ double g = self->v_filter[0].g;
+ double k = self->v_filter[0].k;
+
+ H = zm*zm / (zm*zm + g*g*zp*zp + g*k*zzm);
+ return cabs(H);
+}
+
+static double
+calc_lowshelf(Aeq* self, double omega) {
+ double complex H = 0.0;
+ double complex z = cexp(I * omega);
+ double complex zz = cexp(2. * I * omega);
+ double complex zm = z - 1.0;
+ double complex zp = z + 1.0;
+ double complex zzm = zz - 1.0;
+
+ double A = pow(10.0, self->v_g[0]/40.0);
+ double g = self->v_filter[0].g;
+ double k = self->v_filter[0].k;
+ double m0 = self->v_filter[0].m[0];
+ double m1 = self->v_filter[0].m[1];
+ double m2 = self->v_filter[0].m[2];
+
+ H = (A*m0*zm*zm + g*g*(m0+m2)*zp*zp + sqrt(A)*g*(k*m0+m1) * zzm) / (A*zm*zm + g*g*zp*zp + sqrt(A)*g*k*zzm);
+ return cabs(H);
+}
+
+static double
+calc_highshelf(Aeq* self, double omega) {
+ double complex H = 0.0;
+ double complex z = cexp(I * omega);
+ double complex zz = cexp(2. * I * omega);
+ double complex zm = z - 1.0;
+ double complex zp = z + 1.0;
+ double complex zzm = zz - 1.0;
+
+ double A = pow(10.0, self->v_g[5]/40.0);
+ double g = self->v_filter[5].g;
+ double k = self->v_filter[5].k;
+ double m0 = self->v_filter[5].m[0];
+ double m1 = self->v_filter[5].m[1];
+ double m2 = self->v_filter[5].m[2];
+
+ H = ( sqrt(A) * g * zp * (m1 * zm + sqrt(A)*g*m2*zp) + m0 * ( zm*zm + A*g*g*zp*zp + sqrt(A)*g*k*zzm)) / (zm*zm + A*g*g*zp*zp + sqrt(A)*g*k*zzm);
+ return cabs(H);
+}
+
+#ifdef LV2_EXTENDED
+static float
+eq_curve (Aeq* self, float f) {
+ double complex response = 1.0;
+ double SR = (double)self->srate;
+ double omega = f * 2. * M_PI / SR;
// low
if (self->v_filtog[0]) {
- A = pow(10.0, self->v_g[0]/40.0);
- m0 = self->v_filter[0].m[0];
- m1 = self->v_filter[0].m[1];
- m2 = self->v_filter[0].m[2];
- g = self->v_filter[0].g;
- k = self->v_filter[0].k;
if (self->v_shelftogl) {
// lowshelf
- H *= (A*m0*zm*zm + g*g*(m0+m2)*zp*zp + sqrt(A)*g*(k*m0+m1) * zzm) / (A*zm*zm + g*g*zp*zp + sqrt(A)*g*k*zzm);
+ response *= calc_lowshelf(self, omega);
} else {
// hp:
- H *= zm*zm / (zm*zm + g*g*zp*zp + g*k*zzm);
+ response *= calc_highpass(self, omega);
}
}
// peq1:
if (self->v_filtog[1]) {
- A = pow(10.0, self->v_g[1]/40.0);
- m1 = self->v_filter[1].m[1] / A;
- g = self->v_filter[1].g;
- k = self->v_filter[1].k;
- H *= (g*k*zzm + A*(g*zp*(m1*zm + g*m2*zp) + (zm*zm + g*g*zp*zp))) / (g*k*zzm + A*(zm*zm + g*g*zp*zp));
+ response *= calc_peq(self, 1, omega);
}
// peq2:
if (self->v_filtog[2]) {
- A = pow(10.0, self->v_g[2]/40.0);
- m1 = self->v_filter[2].m[1] / A;
- g = self->v_filter[2].g;
- k = self->v_filter[2].k;
- H *= (g*k*zzm + A*(g*zp*(m1*zm + g*m2*zp) + (zm*zm + g*g*zp*zp))) / (g*k*zzm + A*(zm*zm + g*g*zp*zp));
+ response *= calc_peq(self, 2, omega);
}
// peq3:
if (self->v_filtog[3]) {
- A = pow(10.0, self->v_g[3]/40.0);
- m1 = self->v_filter[3].m[1] / A;
- g = self->v_filter[3].g;
- k = self->v_filter[3].k;
- H *= (g*k*zzm + A*(g*zp*(m1*zm + g*m2*zp) + (zm*zm + g*g*zp*zp))) / (g*k*zzm + A*(zm*zm + g*g*zp*zp));
+ response *= calc_peq(self, 3, omega);
}
// peq4:
if (self->v_filtog[4]) {
- A = pow(10.0, self->v_g[4]/40.0);
- m1 = self->v_filter[4].m[1] / A;
- g = self->v_filter[4].g;
- k = self->v_filter[4].k;
- H *= (g*k*zzm + A*(g*zp*(m1*zm + g*m2*zp) + (zm*zm + g*g*zp*zp))) / (g*k*zzm + A*(zm*zm + g*g*zp*zp));
+ response *= calc_peq(self, 4, omega);
}
// high
if (self->v_filtog[5]) {
- A = pow(10.0, self->v_g[5]/40.0);
- m0 = self->v_filter[5].m[0];
- m1 = self->v_filter[5].m[1];
- m2 = self->v_filter[5].m[2];
- g = self->v_filter[5].g;
- k = self->v_filter[5].k;
if (self->v_shelftogh) {
// highshelf:
- H *= ( sqrt(A) * g * zp * (m1 * zm + sqrt(A)*g*m2*zp) + m0 * ( zm*zm + A*g*g*zp*zp + sqrt(A)*g*k*zzm)) / (zm*zm + A*g*g*zp*zp + sqrt(A)*g*k*zzm);
+ response *= calc_highshelf(self, omega);
} else {
// lp:
- H *= (g*g*zp*zp) / (zm*zm + g*g*zp*zp + g*k*zzm);
+ response *= calc_lowpass(self, omega);
}
}
- return cabs(H);
+ return response;
}
static LV2_Inline_Display_Image_Surface *