1 /*
2 * lingot, a musical instrument tuner.
3 *
4 * Copyright (C) 2004-2018 Iban Cereijo.
5 * Copyright (C) 2004-2008 Jairo Chapela.
6
7 *
8 * This file is part of lingot.
9 *
10 * lingot is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * lingot is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with lingot; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25 #include <memory.h>
26 #include <math.h>
27
28 #include "lingot-complex.h"
29 #include "lingot-filter.h"
30
31 #define max(a,b) (((a)<(b))?(b):(a))
32
33 // given each polynomial order and coefs, with optional initial status.
lingot_filter_new(LingotFilter * filter,unsigned int Na,unsigned int Nb,const FLT * a,const FLT * b)34 void lingot_filter_new(LingotFilter* filter, unsigned int Na, unsigned int Nb, const FLT* a,
35 const FLT* b) {
36 unsigned int i;
37 filter->N = max(Na, Nb);
38
39 filter->a = malloc((filter->N + 1) * sizeof(FLT));
40 filter->b = malloc((filter->N + 1) * sizeof(FLT));
41 filter->s = malloc((filter->N + 1) * sizeof(FLT));
42
43 for (i = 0; i <= filter->N; i++) {
44 filter->a[i] = 0.0;
45 filter->b[i] = 0.0;
46 filter->s[i] = 0.0;
47 }
48
49 memcpy(filter->a, a, (Na + 1) * sizeof(FLT));
50 memcpy(filter->b, b, (Nb + 1) * sizeof(FLT));
51
52 for (i = 0; i <= filter->N; i++) {
53 filter->a[i] /= a[0]; // polynomial normalization.
54 filter->b[i] /= a[0];
55 }
56 }
57
lingot_filter_reset(LingotFilter * filter)58 void lingot_filter_reset(LingotFilter* filter) {
59 unsigned int i;
60 for (i = 0; i <= filter->N; i++) {
61 filter->s[i] = 0.0;
62 }
63 }
64
lingot_filter_destroy(LingotFilter * filter)65 void lingot_filter_destroy(LingotFilter* filter) {
66 free(filter->a);
67 free(filter->b);
68 free(filter->s);
69 }
70
71 // Digital Filter Implementation II, in & out can overlap.
lingot_filter_filter(LingotFilter * filter,unsigned int n,const FLT * in,FLT * out)72 void lingot_filter_filter(LingotFilter* filter, unsigned int n, const FLT* in,
73 FLT* out) {
74 FLT w, y;
75 register unsigned int i;
76 register int j;
77
78 for (i = 0; i < n; i++) {
79
80 w = in[i];
81 y = 0.0;
82
83 for (j = filter->N - 1; j >= 0; j--) {
84 w -= filter->a[j + 1] * filter->s[j];
85 y += filter->b[j + 1] * filter->s[j];
86 filter->s[j + 1] = filter->s[j];
87 }
88
89 y += w * filter->b[0];
90 filter->s[0] = w;
91
92 out[i] = y;
93 }
94 }
95
96 // single sample filtering
lingot_filter_filter_sample(LingotFilter * filter,FLT in)97 FLT lingot_filter_filter_sample(LingotFilter* filter, FLT in) {
98 FLT result;
99
100 lingot_filter_filter(filter, 1, &in, &result);
101 return result;
102 }
103
104 // vector prod
lingot_filter_vector_product(int n,LingotComplex * vector,LingotComplex result)105 void lingot_filter_vector_product(int n, LingotComplex* vector,
106 LingotComplex result) {
107 register int i;
108 LingotComplex aux1;
109
110 result[0] = 1.0;
111 result[1] = 0.0;
112
113 for (i = 0; i < n; i++) {
114 aux1[0] = -vector[i][0];
115 aux1[1] = -vector[i][1];
116 lingot_complex_mul_by(result, aux1);
117 }
118
119 }
120
121 // Chebyshev filters
lingot_filter_cheby_design(LingotFilter * filter,unsigned int n,FLT Rp,FLT wc)122 void lingot_filter_cheby_design(LingotFilter* filter, unsigned int n, FLT Rp, FLT wc) {
123 unsigned int i; // loops
124 unsigned int k;
125 unsigned int p;
126
127 FLT a[n + 1];
128 FLT b[n + 1];
129
130 FLT new_a[n + 1];
131 FLT new_b[n + 1];
132
133 // locate poles
134 LingotComplex pole[n];
135
136 for (i = 0; i < n; i++) {
137 pole[i][0] = 0.0;
138 pole[i][1] = 0.0;
139 }
140
141 FLT T = 2.0;
142 // 2Hz
143 FLT W = 2.0 / T * tan(M_PI * wc / T);
144
145 FLT epsilon = sqrt(pow(10.0, 0.1 * Rp) - 1);
146 FLT v0 = asinh(1 / epsilon) / n;
147
148 FLT sv0 = sinh(v0);
149 FLT cv0 = cosh(v0);
150
151 FLT t;
152
153 for (i = -(n - 1), k = 0; k < n; i += 2, k++) {
154 t = M_PI * i / (2.0 * n);
155 pole[k][0] = -sv0 * cos(t);
156 pole[k][1] = cv0 * sin(t);
157 }
158
159 LingotComplex gain;
160 lingot_filter_vector_product(n, pole, gain);
161
162 if ((n & 1) == 0) { // even
163 FLT f = pow(10.0, -0.05 * Rp);
164 gain[0] *= f;
165 gain[1] *= f;
166 }
167
168 FLT f = pow(W, n);
169 gain[0] *= f;
170 gain[1] *= f;
171
172 for (i = 0; i < n; i++) {
173 pole[i][0] *= W;
174 pole[i][1] *= W;
175 }
176
177 // bilinear transform
178 LingotComplex sp[n];
179
180 for (i = 0; i < n; i++) {
181 sp[i][0] = (2.0 - pole[i][0] * T) / T;
182 sp[i][1] = (0.0 - pole[i][1] * T) / T;
183 }
184
185 LingotComplex tmp1;
186 LingotComplex aux2;
187
188 lingot_filter_vector_product(n, sp, tmp1);
189
190 lingot_complex_div_by(gain, tmp1);
191
192 for (i = 0; i < n; i++) {
193 tmp1[0] = (2.0 + pole[i][0] * T);
194 tmp1[1] = (0.0 + pole[i][1] * T);
195 aux2[0] = (2.0 - pole[i][0] * T);
196 aux2[1] = (0.0 - pole[i][1] * T);
197 lingot_complex_div(tmp1, aux2, pole[i]);
198 }
199
200 // compute filter coefficients from pole/zero values
201 a[0] = 1.0;
202 b[0] = 1.0;
203 new_a[0] = 1.0;
204 new_b[0] = 1.0;
205
206 for (i = 1; i <= n; i++) {
207 a[i] = 0.0;
208 b[i] = 0.0;
209 new_a[i] = 0.0;
210 new_b[i] = 0.0;
211 }
212
213 if (n & 1) { // odd
214 // first subfilter is first order
215 a[1] = -pole[n / 2][0];
216 b[1] = 1.0;
217 }
218
219 // iterate over the conjugate pairs
220 for (p = 0; p < n / 2; p++) {
221 FLT b1 = 2.0;
222 FLT b2 = 1.0;
223
224 FLT a1 = -2.0 * pole[p][0];
225 FLT a2 = pole[p][0] * pole[p][0] + pole[p][1] * pole[p][1];
226
227 // 2nd order subfilter per each pair
228 new_a[1] = a[1] + a1 * a[0];
229 new_b[1] = b[1] + b1 * b[0];
230
231 // poly multiplication
232 for (i = 2; i <= n; i++) {
233 new_a[i] = a[i] + a1 * a[i - 1] + a2 * a[i - 2];
234 new_b[i] = b[i] + b1 * b[i - 1] + b2 * b[i - 2];
235 }
236 for (i = 1; i <= n; i++) {
237 a[i] = new_a[i];
238 b[i] = new_b[i];
239 }
240 }
241
242 gain[0] = fabs(gain[0]);
243 for (i = 0; i <= n; i++) {
244 b[i] *= gain[0];
245 }
246
247 lingot_filter_new(filter, n, n, a, b);
248 }
249