/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <stdlib.h>
#include "eq.h"
struct eq {
int n;
struct biquad biquad[MAX_BIQUADS_PER_EQ];
};
struct eq *eq_new()
{
struct eq *eq = (struct eq *)calloc(1, sizeof(*eq));
return eq;
}
void eq_free(struct eq *eq)
{
free(eq);
}
int eq_append_biquad(struct eq *eq, enum biquad_type type, float freq, float Q,
float gain)
{
if (eq->n >= MAX_BIQUADS_PER_EQ)
return -1;
biquad_set(&eq->biquad[eq->n++], type, freq, Q, gain);
return 0;
}
int eq_append_biquad_direct(struct eq *eq, const struct biquad *biquad)
{
if (eq->n >= MAX_BIQUADS_PER_EQ)
return -1;
eq->biquad[eq->n++] = *biquad;
return 0;
}
/* This is the prototype of the processing loop. */
void eq_process1(struct eq *eq, float *data, int count)
{
int i, j;
for (i = 0; i < eq->n; i++) {
struct biquad *q = &eq->biquad[i];
float x1 = q->x1;
float x2 = q->x2;
float y1 = q->y1;
float y2 = q->y2;
float b0 = q->b0;
float b1 = q->b1;
float b2 = q->b2;
float a1 = q->a1;
float a2 = q->a2;
for (j = 0; j < count; j++) {
float x = data[j];
float y = b0*x
+ b1*x1 + b2*x2
- a1*y1 - a2*y2;
data[j] = y;
x2 = x1;
x1 = x;
y2 = y1;
y1 = y;
}
q->x1 = x1;
q->x2 = x2;
q->y1 = y1;
q->y2 = y2;
}
}
/* This is the actual processing loop used. It is the unrolled version of the
* above prototype. */
void eq_process(struct eq *eq, float *data, int count)
{
int i, j;
for (i = 0; i < eq->n; i += 2) {
if (i + 1 == eq->n) {
struct biquad *q = &eq->biquad[i];
float x1 = q->x1;
float x2 = q->x2;
float y1 = q->y1;
float y2 = q->y2;
float b0 = q->b0;
float b1 = q->b1;
float b2 = q->b2;
float a1 = q->a1;
float a2 = q->a2;
for (j = 0; j < count; j++) {
float x = data[j];
float y = b0*x
+ b1*x1 + b2*x2
- a1*y1 - a2*y2;
data[j] = y;
x2 = x1;
x1 = x;
y2 = y1;
y1 = y;
}
q->x1 = x1;
q->x2 = x2;
q->y1 = y1;
q->y2 = y2;
} else {
struct biquad *q = &eq->biquad[i];
struct biquad *r = &eq->biquad[i+1];
float x1 = q->x1;
float x2 = q->x2;
float y1 = q->y1;
float y2 = q->y2;
float qb0 = q->b0;
float qb1 = q->b1;
float qb2 = q->b2;
float qa1 = q->a1;
float qa2 = q->a2;
float z1 = r->y1;
float z2 = r->y2;
float rb0 = r->b0;
float rb1 = r->b1;
float rb2 = r->b2;
float ra1 = r->a1;
float ra2 = r->a2;
for (j = 0; j < count; j++) {
float x = data[j];
float y = qb0*x
+ qb1*x1 + qb2*x2
- qa1*y1 - qa2*y2;
float z = rb0*y
+ rb1*y1 + rb2*y2
- ra1*z1 - ra2*z2;
data[j] = z;
x2 = x1;
x1 = x;
y2 = y1;
y1 = y;
z2 = z1;
z1 = z;
}
q->x1 = x1;
q->x2 = x2;
q->y1 = y1;
q->y2 = y2;
r->y1 = z1;
r->y2 = z2;
}
}
}