5 // x ---------+---------|---------+-------y
9 // +---<-----|---->----+
11 // | D | D's are delays
12 // | a2 | b2 | ">" represent multiplications
13 // +---<-----|---->----+
14 // To test this routine, use a biquad with a pole pair at z = (0.7 +- 0.1j),
15 // and a double zero at z = -1.0, which is a low-pass. The transfer function is:
17 // H(z) = ----------------------
18 // 1 - 1.4z^-1 + 0.5z^-2
23 // This filter conforms to the biquad test in BDT, since it has coefficients
24 // larger than 1.0 in magnitude, and b0=1. (Note that the a's have a negative
26 // This filter can be simulated in matlab. To simulate one biquad, use
27 // A = [1.0, -1.4, 0.5]
30 // To simulate two cascaded biquads, use
31 // Y=filter(B,A,filter(B,A,X))
32 // SCALED COEFFICIENTS:
33 // --------------------
34 // In order to conform to 1.15 representation, must scale coeffs by 0.5.
35 // This requires an additional internal re-scale. The equations for the Type II
37 // t1 = x + a1*t1*z^-1 + a2*t1*z^-2
38 // y = b0*t1 + b1*t1*z^-1 + b2*t1*z^-2
39 // (Note inclusion of term b0, which in the example is b0 = 1.)
40 // If all coeffs are replaced by
41 // ai --> ai' = 0.5*a1
42 // then the two equations become
43 // t1 = x + 2*a1'*t1*z^-1 + 2*a2'*t1*z^-2
44 // 0.5*y = b0'*t1 + b1'*t1*z^-1 + b2'*t1*z^-2
45 // which can be implemented as:
47 // x ---------+--->-----|---->----+-------y
51 // +---<-----|---->----+
55 // +---<-----|---->----+
56 // But, b0' can be eliminated by:
57 // x ---------+---------|---------+-------y
64 // +---<-----|---->----+
68 // +---<-----|---->----+
69 // Function biquadf() computes this implementation on float data.
72 // Cascaded biquads are simulated by simply cascading copies of the
73 // filter defined above. However, one must be careful with the resulting
74 // filter, as it is not very stable numerically (double poles in the
75 // vecinity of +1). It would of course be better to cascade different
76 // filters, as that would result in more stable structures.
77 // The functions biquadf() and biquadR() have been tested with up to 3
78 // stages using this technique, with inputs having small signal amplitude
79 // (less than 0.001) and under 300 samples.
81 // In order to pipeline, need to maintain two pointers into the state
82 // array: one to load (I0) and one to store (I2). This is required since
83 // the load of iteration i+1 is hoisted above the store of iteration i.
85 .include "testutils.inc"
89 // I3 points to input buffer
92 // P1 points to output buffer
98 LSETUP ( L$0 , L$0end ) LC0 = P2;
101 // I0 and I2 are pointers to state
108 R0.H = W [ I3 ++ ]; // load input value into RH0
109 A0.w = R0; // A0 holds x
112 LSETUP ( L$1 , L$1end ) LC1 = P2;
114 // load 2 coeffs into R1 and R2
115 // load state into R3
117 MNOP || R2 = [ I1 ++ ] || R3 = [ I0 ++ ];
121 // A1=b1*s0 A0=a1*s0+x
122 A1 = R1.L * R3.L, A0 += R1.H * R3.L || R1 = [ I1 ++ ] || NOP;
124 // A1+=b2*s1 A0+=a2*s1
125 // and move scaled value in A0 (t1) into RL4
126 A1 += R2.L * R3.H, R4.L = ( A0 += R2.H * R3.H ) (S2RND) || R2 = [ I1 ++ ] || NOP;
128 // Advance state. before:
130 // R3 = stat[1] stat[0]
133 R5 = PACK( R3.L , R4.L ) || R3 = [ I0 ++ ] || NOP;
135 // collect output into A0, and move to RL0.
136 // Keep output value in A0, since it is also
137 // the accumulator used to store the input to
138 // the next stage. Also, store updated state
140 R0.L = ( A0 += A1 ) || [ I2 ++ ] = R5 || NOP;
148 R0.L = W [ I2 ++ ]; DBGA ( R0.L , 0x0028 );
149 R0.L = W [ I2 ++ ]; DBGA ( R0.L , 0x0110 );
150 R0.L = W [ I2 ++ ]; DBGA ( R0.L , 0x0373 );
151 R0.L = W [ I2 ++ ]; DBGA ( R0.L , 0x075b );
152 R0.L = W [ I2 ++ ]; DBGA ( R0.L , 0x0c00 );
153 R0.L = W [ I2 ++ ]; DBGA ( R0.L , 0x1064 );
154 R0.L = W [ I2 ++ ]; DBGA ( R0.L , 0x13d3 );
155 R0.L = W [ I2 ++ ]; DBGA ( R0.L , 0x15f2 );
156 R0.L = W [ I2 ++ ]; DBGA ( R0.L , 0x16b9 );
157 R0.L = W [ I2 ++ ]; DBGA ( R0.L , 0x1650 );