Home | History | Annotate | Download | only in dsp
      1 /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
      2  * Use of this source code is governed by a BSD-style license that can be
      3  * found in the LICENSE file.
      4  */
      5 
      6 #include <stdlib.h>
      7 #include "eq.h"
      8 
      9 struct eq {
     10 	int n;
     11 	struct biquad biquad[MAX_BIQUADS_PER_EQ];
     12 };
     13 
     14 struct eq *eq_new()
     15 {
     16 	struct eq *eq = (struct eq *)calloc(1, sizeof(*eq));
     17 	return eq;
     18 }
     19 
     20 void eq_free(struct eq *eq)
     21 {
     22 	free(eq);
     23 }
     24 
     25 int eq_append_biquad(struct eq *eq, enum biquad_type type, float freq, float Q,
     26 		      float gain)
     27 {
     28 	if (eq->n >= MAX_BIQUADS_PER_EQ)
     29 		return -1;
     30 	biquad_set(&eq->biquad[eq->n++], type, freq, Q, gain);
     31 	return 0;
     32 }
     33 
     34 int eq_append_biquad_direct(struct eq *eq, const struct biquad *biquad)
     35 {
     36 	if (eq->n >= MAX_BIQUADS_PER_EQ)
     37 		return -1;
     38 	eq->biquad[eq->n++] = *biquad;
     39 	return 0;
     40 }
     41 
     42 /* This is the prototype of the processing loop. */
     43 void eq_process1(struct eq *eq, float *data, int count)
     44 {
     45 	int i, j;
     46 	for (i = 0; i < eq->n; i++) {
     47 		struct biquad *q = &eq->biquad[i];
     48 		float x1 = q->x1;
     49 		float x2 = q->x2;
     50 		float y1 = q->y1;
     51 		float y2 = q->y2;
     52 		float b0 = q->b0;
     53 		float b1 = q->b1;
     54 		float b2 = q->b2;
     55 		float a1 = q->a1;
     56 		float a2 = q->a2;
     57 		for (j = 0; j < count; j++) {
     58 			float x = data[j];
     59 			float y = b0*x
     60 				+ b1*x1 + b2*x2
     61 				- a1*y1 - a2*y2;
     62 			data[j] = y;
     63 			x2 = x1;
     64 			x1 = x;
     65 			y2 = y1;
     66 			y1 = y;
     67 		}
     68 		q->x1 = x1;
     69 		q->x2 = x2;
     70 		q->y1 = y1;
     71 		q->y2 = y2;
     72 	}
     73 }
     74 
     75 /* This is the actual processing loop used. It is the unrolled version of the
     76  * above prototype. */
     77 void eq_process(struct eq *eq, float *data, int count)
     78 {
     79 	int i, j;
     80 	for (i = 0; i < eq->n; i += 2) {
     81 		if (i + 1 == eq->n) {
     82 			struct biquad *q = &eq->biquad[i];
     83 			float x1 = q->x1;
     84 			float x2 = q->x2;
     85 			float y1 = q->y1;
     86 			float y2 = q->y2;
     87 			float b0 = q->b0;
     88 			float b1 = q->b1;
     89 			float b2 = q->b2;
     90 			float a1 = q->a1;
     91 			float a2 = q->a2;
     92 			for (j = 0; j < count; j++) {
     93 				float x = data[j];
     94 				float y = b0*x
     95 					+ b1*x1 + b2*x2
     96 					- a1*y1 - a2*y2;
     97 				data[j] = y;
     98 				x2 = x1;
     99 				x1 = x;
    100 				y2 = y1;
    101 				y1 = y;
    102 			}
    103 			q->x1 = x1;
    104 			q->x2 = x2;
    105 			q->y1 = y1;
    106 			q->y2 = y2;
    107 		} else {
    108 			struct biquad *q = &eq->biquad[i];
    109 			struct biquad *r = &eq->biquad[i+1];
    110 			float x1 = q->x1;
    111 			float x2 = q->x2;
    112 			float y1 = q->y1;
    113 			float y2 = q->y2;
    114 			float qb0 = q->b0;
    115 			float qb1 = q->b1;
    116 			float qb2 = q->b2;
    117 			float qa1 = q->a1;
    118 			float qa2 = q->a2;
    119 
    120 			float z1 = r->y1;
    121 			float z2 = r->y2;
    122 			float rb0 = r->b0;
    123 			float rb1 = r->b1;
    124 			float rb2 = r->b2;
    125 			float ra1 = r->a1;
    126 			float ra2 = r->a2;
    127 
    128 			for (j = 0; j < count; j++) {
    129 				float x = data[j];
    130 				float y = qb0*x
    131 					+ qb1*x1 + qb2*x2
    132 					- qa1*y1 - qa2*y2;
    133 				float z = rb0*y
    134 					+ rb1*y1 + rb2*y2
    135 					- ra1*z1 - ra2*z2;
    136 				data[j] = z;
    137 				x2 = x1;
    138 				x1 = x;
    139 				y2 = y1;
    140 				y1 = y;
    141 				z2 = z1;
    142 				z1 = z;
    143 			}
    144 			q->x1 = x1;
    145 			q->x2 = x2;
    146 			q->y1 = y1;
    147 			q->y2 = y2;
    148 			r->y1 = z1;
    149 			r->y2 = z2;
    150 		}
    151 	}
    152 }
    153