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 "crossover.h"
      7 #include "biquad.h"
      8 
      9 static void lr4_set(struct lr4 *lr4, enum biquad_type type, float freq)
     10 {
     11 	struct biquad q;
     12 	biquad_set(&q, type, freq, 0, 0);
     13 	lr4->b0 = q.b0;
     14 	lr4->b1 = q.b1;
     15 	lr4->b2 = q.b2;
     16 	lr4->a1 = q.a1;
     17 	lr4->a2 = q.a2;
     18 	lr4->x1 = 0;
     19 	lr4->x2 = 0;
     20 	lr4->y1 = 0;
     21 	lr4->y2 = 0;
     22 	lr4->z1 = 0;
     23 	lr4->z2 = 0;
     24 }
     25 
     26 /* Split input data using two LR4 filters, put the result into the input array
     27  * and another array.
     28  *
     29  * data0 --+-- lp --> data0
     30  *         |
     31  *         \-- hp --> data1
     32  */
     33 static void lr4_split(struct lr4 *lp, struct lr4 *hp, int count, float *data0,
     34 		      float *data1)
     35 {
     36 	float lx1 = lp->x1;
     37 	float lx2 = lp->x2;
     38 	float ly1 = lp->y1;
     39 	float ly2 = lp->y2;
     40 	float lz1 = lp->z1;
     41 	float lz2 = lp->z2;
     42 	float lb0 = lp->b0;
     43 	float lb1 = lp->b1;
     44 	float lb2 = lp->b2;
     45 	float la1 = lp->a1;
     46 	float la2 = lp->a2;
     47 
     48 	float hx1 = hp->x1;
     49 	float hx2 = hp->x2;
     50 	float hy1 = hp->y1;
     51 	float hy2 = hp->y2;
     52 	float hz1 = hp->z1;
     53 	float hz2 = hp->z2;
     54 	float hb0 = hp->b0;
     55 	float hb1 = hp->b1;
     56 	float hb2 = hp->b2;
     57 	float ha1 = hp->a1;
     58 	float ha2 = hp->a2;
     59 
     60 	int i;
     61 	for (i = 0; i < count; i++) {
     62 		float x, y, z;
     63 		x = data0[i];
     64 		y = lb0*x + lb1*lx1 + lb2*lx2 - la1*ly1 - la2*ly2;
     65 		z = lb0*y + lb1*ly1 + lb2*ly2 - la1*lz1 - la2*lz2;
     66 		lx2 = lx1;
     67 		lx1 = x;
     68 		ly2 = ly1;
     69 		ly1 = y;
     70 		lz2 = lz1;
     71 		lz1 = z;
     72 		data0[i] = z;
     73 
     74 		y = hb0*x + hb1*hx1 + hb2*hx2 - ha1*hy1 - ha2*hy2;
     75 		z = hb0*y + hb1*hy1 + hb2*hy2 - ha1*hz1 - ha2*hz2;
     76 		hx2 = hx1;
     77 		hx1 = x;
     78 		hy2 = hy1;
     79 		hy1 = y;
     80 		hz2 = hz1;
     81 		hz1 = z;
     82 		data1[i] = z;
     83 	}
     84 
     85 	lp->x1 = lx1;
     86 	lp->x2 = lx2;
     87 	lp->y1 = ly1;
     88 	lp->y2 = ly2;
     89 	lp->z1 = lz1;
     90 	lp->z2 = lz2;
     91 
     92 	hp->x1 = hx1;
     93 	hp->x2 = hx2;
     94 	hp->y1 = hy1;
     95 	hp->y2 = hy2;
     96 	hp->z1 = hz1;
     97 	hp->z2 = hz2;
     98 }
     99 
    100 /* Split input data using two LR4 filters and sum them back to the original
    101  * data array.
    102  *
    103  * data --+-- lp --+--> data
    104  *        |        |
    105  *        \-- hp --/
    106  */
    107 static void lr4_merge(struct lr4 *lp, struct lr4 *hp, int count, float *data)
    108 {
    109 	float lx1 = lp->x1;
    110 	float lx2 = lp->x2;
    111 	float ly1 = lp->y1;
    112 	float ly2 = lp->y2;
    113 	float lz1 = lp->z1;
    114 	float lz2 = lp->z2;
    115 	float lb0 = lp->b0;
    116 	float lb1 = lp->b1;
    117 	float lb2 = lp->b2;
    118 	float la1 = lp->a1;
    119 	float la2 = lp->a2;
    120 
    121 	float hx1 = hp->x1;
    122 	float hx2 = hp->x2;
    123 	float hy1 = hp->y1;
    124 	float hy2 = hp->y2;
    125 	float hz1 = hp->z1;
    126 	float hz2 = hp->z2;
    127 	float hb0 = hp->b0;
    128 	float hb1 = hp->b1;
    129 	float hb2 = hp->b2;
    130 	float ha1 = hp->a1;
    131 	float ha2 = hp->a2;
    132 
    133 	int i;
    134 	for (i = 0; i < count; i++) {
    135 		float x, y, z;
    136 		x = data[i];
    137 		y = lb0*x + lb1*lx1 + lb2*lx2 - la1*ly1 - la2*ly2;
    138 		z = lb0*y + lb1*ly1 + lb2*ly2 - la1*lz1 - la2*lz2;
    139 		lx2 = lx1;
    140 		lx1 = x;
    141 		ly2 = ly1;
    142 		ly1 = y;
    143 		lz2 = lz1;
    144 		lz1 = z;
    145 
    146 		y = hb0*x + hb1*hx1 + hb2*hx2 - ha1*hy1 - ha2*hy2;
    147 		z = hb0*y + hb1*hy1 + hb2*hy2 - ha1*hz1 - ha2*hz2;
    148 		hx2 = hx1;
    149 		hx1 = x;
    150 		hy2 = hy1;
    151 		hy1 = y;
    152 		hz2 = hz1;
    153 		hz1 = z;
    154 		data[i] = z + lz1;
    155 	}
    156 
    157 	lp->x1 = lx1;
    158 	lp->x2 = lx2;
    159 	lp->y1 = ly1;
    160 	lp->y2 = ly2;
    161 	lp->z1 = lz1;
    162 	lp->z2 = lz2;
    163 
    164 	hp->x1 = hx1;
    165 	hp->x2 = hx2;
    166 	hp->y1 = hy1;
    167 	hp->y2 = hy2;
    168 	hp->z1 = hz1;
    169 	hp->z2 = hz2;
    170 }
    171 
    172 void crossover_init(struct crossover *xo, float freq1, float freq2)
    173 {
    174 	int i;
    175 	for (i = 0; i < 3; i++) {
    176 		float f = (i == 0) ? freq1 : freq2;
    177 		lr4_set(&xo->lp[i], BQ_LOWPASS, f);
    178 		lr4_set(&xo->hp[i], BQ_HIGHPASS, f);
    179 	}
    180 }
    181 
    182 void crossover_process(struct crossover *xo, int count, float *data0,
    183 		       float *data1, float *data2)
    184 {
    185 	lr4_split(&xo->lp[0], &xo->hp[0], count, data0, data1);
    186 	lr4_merge(&xo->lp[1], &xo->hp[1], count, data0);
    187 	lr4_split(&xo->lp[2], &xo->hp[2], count, data1, data2);
    188 }
    189