comparison libao2/remez.c @ 3482:3f041e737e62

code by Jake Janovetz to find FIR filter coefficients using the Parks-McClellan algorithm
author steve
date Thu, 13 Dec 2001 23:33:50 +0000
parents
children b608086bf84e
comparison
equal deleted inserted replaced
3481:79e046b9e877 3482:3f041e737e62
1 /**************************************************************************
2 * Parks-McClellan algorithm for FIR filter design (C version)
3 *-------------------------------------------------
4 * Copyright (c) 1995,1998 Jake Janovetz (janovetz@uiuc.edu)
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 *************************************************************************/
21
22
23 #include "remez.h"
24 #include <math.h>
25
26 /*******************
27 * CreateDenseGrid
28 *=================
29 * Creates the dense grid of frequencies from the specified bands.
30 * Also creates the Desired Frequency Response function (D[]) and
31 * the Weight function (W[]) on that dense grid
32 *
33 *
34 * INPUT:
35 * ------
36 * int r - 1/2 the number of filter coefficients
37 * int numtaps - Number of taps in the resulting filter
38 * int numband - Number of bands in user specification
39 * double bands[] - User-specified band edges [2*numband]
40 * double des[] - Desired response per band [numband]
41 * double weight[] - Weight per band [numband]
42 * int symmetry - Symmetry of filter - used for grid check
43 *
44 * OUTPUT:
45 * -------
46 * int gridsize - Number of elements in the dense frequency grid
47 * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize]
48 * double D[] - Desired response on the dense grid [gridsize]
49 * double W[] - Weight function on the dense grid [gridsize]
50 *******************/
51
52 void CreateDenseGrid(int r, int numtaps, int numband, double bands[],
53 double des[], double weight[], int *gridsize,
54 double Grid[], double D[], double W[],
55 int symmetry)
56 {
57 int i, j, k, band;
58 double delf, lowf, highf;
59
60 delf = 0.5/(GRIDDENSITY*r);
61
62 /*
63 * For differentiator, hilbert,
64 * symmetry is odd and Grid[0] = max(delf, band[0])
65 */
66
67 if ((symmetry == NEGATIVE) && (delf > bands[0]))
68 bands[0] = delf;
69
70 j=0;
71 for (band=0; band < numband; band++)
72 {
73 Grid[j] = bands[2*band];
74 lowf = bands[2*band];
75 highf = bands[2*band + 1];
76 k = (int)((highf - lowf)/delf + 0.5); /* .5 for rounding */
77 for (i=0; i<k; i++)
78 {
79 D[j] = des[band];
80 W[j] = weight[band];
81 Grid[j] = lowf;
82 lowf += delf;
83 j++;
84 }
85 Grid[j-1] = highf;
86 }
87
88 /*
89 * Similar to above, if odd symmetry, last grid point can't be .5
90 * - but, if there are even taps, leave the last grid point at .5
91 */
92 if ((symmetry == NEGATIVE) &&
93 (Grid[*gridsize-1] > (0.5 - delf)) &&
94 (numtaps % 2))
95 {
96 Grid[*gridsize-1] = 0.5-delf;
97 }
98 }
99
100
101 /********************
102 * InitialGuess
103 *==============
104 * Places Extremal Frequencies evenly throughout the dense grid.
105 *
106 *
107 * INPUT:
108 * ------
109 * int r - 1/2 the number of filter coefficients
110 * int gridsize - Number of elements in the dense frequency grid
111 *
112 * OUTPUT:
113 * -------
114 * int Ext[] - Extremal indexes to dense frequency grid [r+1]
115 ********************/
116
117 void InitialGuess(int r, int Ext[], int gridsize)
118 {
119 int i;
120
121 for (i=0; i<=r; i++)
122 Ext[i] = i * (gridsize-1) / r;
123 }
124
125
126 /***********************
127 * CalcParms
128 *===========
129 *
130 *
131 * INPUT:
132 * ------
133 * int r - 1/2 the number of filter coefficients
134 * int Ext[] - Extremal indexes to dense frequency grid [r+1]
135 * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize]
136 * double D[] - Desired response on the dense grid [gridsize]
137 * double W[] - Weight function on the dense grid [gridsize]
138 *
139 * OUTPUT:
140 * -------
141 * double ad[] - 'b' in Oppenheim & Schafer [r+1]
142 * double x[] - [r+1]
143 * double y[] - 'C' in Oppenheim & Schafer [r+1]
144 ***********************/
145
146 void CalcParms(int r, int Ext[], double Grid[], double D[], double W[],
147 double ad[], double x[], double y[])
148 {
149 int i, j, k, ld;
150 double sign, xi, delta, denom, numer;
151
152 /*
153 * Find x[]
154 */
155 for (i=0; i<=r; i++)
156 x[i] = cos(Pi2 * Grid[Ext[i]]);
157
158 /*
159 * Calculate ad[] - Oppenheim & Schafer eq 7.132
160 */
161 ld = (r-1)/15 + 1; /* Skips around to avoid round errors */
162 for (i=0; i<=r; i++)
163 {
164 denom = 1.0;
165 xi = x[i];
166 for (j=0; j<ld; j++)
167 {
168 for (k=j; k<=r; k+=ld)
169 if (k != i)
170 denom *= 2.0*(xi - x[k]);
171 }
172 if (fabs(denom)<0.00001)
173 denom = 0.00001;
174 ad[i] = 1.0/denom;
175 }
176
177 /*
178 * Calculate delta - Oppenheim & Schafer eq 7.131
179 */
180 numer = denom = 0;
181 sign = 1;
182 for (i=0; i<=r; i++)
183 {
184 numer += ad[i] * D[Ext[i]];
185 denom += sign * ad[i]/W[Ext[i]];
186 sign = -sign;
187 }
188 delta = numer/denom;
189 sign = 1;
190
191 /*
192 * Calculate y[] - Oppenheim & Schafer eq 7.133b
193 */
194 for (i=0; i<=r; i++)
195 {
196 y[i] = D[Ext[i]] - sign * delta/W[Ext[i]];
197 sign = -sign;
198 }
199 }
200
201
202 /*********************
203 * ComputeA
204 *==========
205 * Using values calculated in CalcParms, ComputeA calculates the
206 * actual filter response at a given frequency (freq). Uses
207 * eq 7.133a from Oppenheim & Schafer.
208 *
209 *
210 * INPUT:
211 * ------
212 * double freq - Frequency (0 to 0.5) at which to calculate A
213 * int r - 1/2 the number of filter coefficients
214 * double ad[] - 'b' in Oppenheim & Schafer [r+1]
215 * double x[] - [r+1]
216 * double y[] - 'C' in Oppenheim & Schafer [r+1]
217 *
218 * OUTPUT:
219 * -------
220 * Returns double value of A[freq]
221 *********************/
222
223 double ComputeA(double freq, int r, double ad[], double x[], double y[])
224 {
225 int i;
226 double xc, c, denom, numer;
227
228 denom = numer = 0;
229 xc = cos(Pi2 * freq);
230 for (i=0; i<=r; i++)
231 {
232 c = xc - x[i];
233 if (fabs(c) < 1.0e-7)
234 {
235 numer = y[i];
236 denom = 1;
237 break;
238 }
239 c = ad[i]/c;
240 denom += c;
241 numer += c*y[i];
242 }
243 return numer/denom;
244 }
245
246
247 /************************
248 * CalcError
249 *===========
250 * Calculates the Error function from the desired frequency response
251 * on the dense grid (D[]), the weight function on the dense grid (W[]),
252 * and the present response calculation (A[])
253 *
254 *
255 * INPUT:
256 * ------
257 * int r - 1/2 the number of filter coefficients
258 * double ad[] - [r+1]
259 * double x[] - [r+1]
260 * double y[] - [r+1]
261 * int gridsize - Number of elements in the dense frequency grid
262 * double Grid[] - Frequencies on the dense grid [gridsize]
263 * double D[] - Desired response on the dense grid [gridsize]
264 * double W[] - Weight function on the desnse grid [gridsize]
265 *
266 * OUTPUT:
267 * -------
268 * double E[] - Error function on dense grid [gridsize]
269 ************************/
270
271 void CalcError(int r, double ad[], double x[], double y[],
272 int gridsize, double Grid[],
273 double D[], double W[], double E[])
274 {
275 int i;
276 double A;
277
278 for (i=0; i<gridsize; i++)
279 {
280 A = ComputeA(Grid[i], r, ad, x, y);
281 E[i] = W[i] * (D[i] - A);
282 }
283 }
284
285 /************************
286 * Search
287 *========
288 * Searches for the maxima/minima of the error curve. If more than
289 * r+1 extrema are found, it uses the following heuristic (thanks
290 * Chris Hanson):
291 * 1) Adjacent non-alternating extrema deleted first.
292 * 2) If there are more than one excess extrema, delete the
293 * one with the smallest error. This will create a non-alternation
294 * condition that is fixed by 1).
295 * 3) If there is exactly one excess extremum, delete the smaller
296 * of the first/last extremum
297 *
298 *
299 * INPUT:
300 * ------
301 * int r - 1/2 the number of filter coefficients
302 * int Ext[] - Indexes to Grid[] of extremal frequencies [r+1]
303 * int gridsize - Number of elements in the dense frequency grid
304 * double E[] - Array of error values. [gridsize]
305 * OUTPUT:
306 * -------
307 * int Ext[] - New indexes to extremal frequencies [r+1]
308 ************************/
309
310 void Search(int r, int Ext[],
311 int gridsize, double E[])
312 {
313 int i, j, k, l, extra; /* Counters */
314 int up, alt;
315 int *foundExt; /* Array of found extremals */
316
317 /*
318 * Allocate enough space for found extremals.
319 */
320 foundExt = (int *)malloc((2*r) * sizeof(int));
321 k = 0;
322
323 /*
324 * Check for extremum at 0.
325 */
326 if (((E[0]>0.0) && (E[0]>E[1])) ||
327 ((E[0]<0.0) && (E[0]<E[1])))
328 foundExt[k++] = 0;
329
330 /*
331 * Check for extrema inside dense grid
332 */
333 for (i=1; i<gridsize-1; i++)
334 {
335 if (((E[i]>=E[i-1]) && (E[i]>E[i+1]) && (E[i]>0.0)) ||
336 ((E[i]<=E[i-1]) && (E[i]<E[i+1]) && (E[i]<0.0)))
337 foundExt[k++] = i;
338 }
339
340 /*
341 * Check for extremum at 0.5
342 */
343 j = gridsize-1;
344 if (((E[j]>0.0) && (E[j]>E[j-1])) ||
345 ((E[j]<0.0) && (E[j]<E[j-1])))
346 foundExt[k++] = j;
347
348
349 /*
350 * Remove extra extremals
351 */
352 extra = k - (r+1);
353
354 while (extra > 0)
355 {
356 if (E[foundExt[0]] > 0.0)
357 up = 1; /* first one is a maxima */
358 else
359 up = 0; /* first one is a minima */
360
361 l=0;
362 alt = 1;
363 for (j=1; j<k; j++)
364 {
365 if (fabs(E[foundExt[j]]) < fabs(E[foundExt[l]]))
366 l = j; /* new smallest error. */
367 if ((up) && (E[foundExt[j]] < 0.0))
368 up = 0; /* switch to a minima */
369 else if ((!up) && (E[foundExt[j]] > 0.0))
370 up = 1; /* switch to a maxima */
371 else
372 {
373 alt = 0;
374 break; /* Ooops, found two non-alternating */
375 } /* extrema. Delete smallest of them */
376 } /* if the loop finishes, all extrema are alternating */
377
378 /*
379 * If there's only one extremal and all are alternating,
380 * delete the smallest of the first/last extremals.
381 */
382 if ((alt) && (extra == 1))
383 {
384 if (fabs(E[foundExt[k-1]]) < fabs(E[foundExt[0]]))
385 l = foundExt[k-1]; /* Delete last extremal */
386 else
387 l = foundExt[0]; /* Delete first extremal */
388 }
389
390 for (j=l; j<k; j++) /* Loop that does the deletion */
391 {
392 foundExt[j] = foundExt[j+1];
393 }
394 k--;
395 extra--;
396 }
397
398 for (i=0; i<=r; i++)
399 {
400 Ext[i] = foundExt[i]; /* Copy found extremals to Ext[] */
401 }
402
403 free(foundExt);
404 }
405
406
407 /*********************
408 * FreqSample
409 *============
410 * Simple frequency sampling algorithm to determine the impulse
411 * response h[] from A's found in ComputeA
412 *
413 *
414 * INPUT:
415 * ------
416 * int N - Number of filter coefficients
417 * double A[] - Sample points of desired response [N/2]
418 * int symmetry - Symmetry of desired filter
419 *
420 * OUTPUT:
421 * -------
422 * double h[] - Impulse Response of final filter [N]
423 *********************/
424 void FreqSample(int N, double A[], double h[], int symm)
425 {
426 int n, k;
427 double x, val, M;
428
429 M = (N-1.0)/2.0;
430 if (symm == POSITIVE)
431 {
432 if (N%2)
433 {
434 for (n=0; n<N; n++)
435 {
436 val = A[0];
437 x = Pi2 * (n - M)/N;
438 for (k=1; k<=M; k++)
439 val += 2.0 * A[k] * cos(x*k);
440 h[n] = val/N;
441 }
442 }
443 else
444 {
445 for (n=0; n<N; n++)
446 {
447 val = A[0];
448 x = Pi2 * (n - M)/N;
449 for (k=1; k<=(N/2-1); k++)
450 val += 2.0 * A[k] * cos(x*k);
451 h[n] = val/N;
452 }
453 }
454 }
455 else
456 {
457 if (N%2)
458 {
459 for (n=0; n<N; n++)
460 {
461 val = 0;
462 x = Pi2 * (n - M)/N;
463 for (k=1; k<=M; k++)
464 val += 2.0 * A[k] * sin(x*k);
465 h[n] = val/N;
466 }
467 }
468 else
469 {
470 for (n=0; n<N; n++)
471 {
472 val = A[N/2] * sin(Pi * (n - M));
473 x = Pi2 * (n - M)/N;
474 for (k=1; k<=(N/2-1); k++)
475 val += 2.0 * A[k] * sin(x*k);
476 h[n] = val/N;
477 }
478 }
479 }
480 }
481
482 /*******************
483 * isDone
484 *========
485 * Checks to see if the error function is small enough to consider
486 * the result to have converged.
487 *
488 * INPUT:
489 * ------
490 * int r - 1/2 the number of filter coeffiecients
491 * int Ext[] - Indexes to extremal frequencies [r+1]
492 * double E[] - Error function on the dense grid [gridsize]
493 *
494 * OUTPUT:
495 * -------
496 * Returns 1 if the result converged
497 * Returns 0 if the result has not converged
498 ********************/
499
500 short isDone(int r, int Ext[], double E[])
501 {
502 int i;
503 double min, max, current;
504
505 min = max = fabs(E[Ext[0]]);
506 for (i=1; i<=r; i++)
507 {
508 current = fabs(E[Ext[i]]);
509 if (current < min)
510 min = current;
511 if (current > max)
512 max = current;
513 }
514 if (((max-min)/max) < 0.0001)
515 return 1;
516 return 0;
517 }
518
519 /********************
520 * remez
521 *=======
522 * Calculates the optimal (in the Chebyshev/minimax sense)
523 * FIR filter impulse response given a set of band edges,
524 * the desired reponse on those bands, and the weight given to
525 * the error in those bands.
526 *
527 * INPUT:
528 * ------
529 * int numtaps - Number of filter coefficients
530 * int numband - Number of bands in filter specification
531 * double bands[] - User-specified band edges [2 * numband]
532 * double des[] - User-specified band responses [numband]
533 * double weight[] - User-specified error weights [numband]
534 * int type - Type of filter
535 *
536 * OUTPUT:
537 * -------
538 * double h[] - Impulse response of final filter [numtaps]
539 ********************/
540
541 void remez(double h[], int numtaps,
542 int numband, double bands[], double des[], double weight[],
543 int type)
544 {
545 double *Grid, *W, *D, *E;
546 int i, iter, gridsize, r, *Ext;
547 double *taps, c;
548 double *x, *y, *ad;
549 int symmetry;
550
551 if (type == BANDPASS)
552 symmetry = POSITIVE;
553 else
554 symmetry = NEGATIVE;
555
556 r = numtaps/2; /* number of extrema */
557 if ((numtaps%2) && (symmetry == POSITIVE))
558 r++;
559
560 /*
561 * Predict dense grid size in advance for memory allocation
562 * .5 is so we round up, not truncate
563 */
564 gridsize = 0;
565 for (i=0; i<numband; i++)
566 {
567 gridsize += (int)(2*r*GRIDDENSITY*(bands[2*i+1] - bands[2*i]) + .5);
568 }
569 if (symmetry == NEGATIVE)
570 {
571 gridsize--;
572 }
573
574 /*
575 * Dynamically allocate memory for arrays with proper sizes
576 */
577 Grid = (double *)malloc(gridsize * sizeof(double));
578 D = (double *)malloc(gridsize * sizeof(double));
579 W = (double *)malloc(gridsize * sizeof(double));
580 E = (double *)malloc(gridsize * sizeof(double));
581 Ext = (int *)malloc((r+1) * sizeof(int));
582 taps = (double *)malloc((r+1) * sizeof(double));
583 x = (double *)malloc((r+1) * sizeof(double));
584 y = (double *)malloc((r+1) * sizeof(double));
585 ad = (double *)malloc((r+1) * sizeof(double));
586
587 /*
588 * Create dense frequency grid
589 */
590 CreateDenseGrid(r, numtaps, numband, bands, des, weight,
591 &gridsize, Grid, D, W, symmetry);
592 InitialGuess(r, Ext, gridsize);
593
594 /*
595 * For Differentiator: (fix grid)
596 */
597 if (type == DIFFERENTIATOR)
598 {
599 for (i=0; i<gridsize; i++)
600 {
601 /* D[i] = D[i]*Grid[i]; */
602 if (D[i] > 0.0001)
603 W[i] = W[i]/Grid[i];
604 }
605 }
606
607 /*
608 * For odd or Negative symmetry filters, alter the
609 * D[] and W[] according to Parks McClellan
610 */
611 if (symmetry == POSITIVE)
612 {
613 if (numtaps % 2 == 0)
614 {
615 for (i=0; i<gridsize; i++)
616 {
617 c = cos(Pi * Grid[i]);
618 D[i] /= c;
619 W[i] *= c;
620 }
621 }
622 }
623 else
624 {
625 if (numtaps % 2)
626 {
627 for (i=0; i<gridsize; i++)
628 {
629 c = sin(Pi2 * Grid[i]);
630 D[i] /= c;
631 W[i] *= c;
632 }
633 }
634 else
635 {
636 for (i=0; i<gridsize; i++)
637 {
638 c = sin(Pi * Grid[i]);
639 D[i] /= c;
640 W[i] *= c;
641 }
642 }
643 }
644
645 /*
646 * Perform the Remez Exchange algorithm
647 */
648 for (iter=0; iter<MAXITERATIONS; iter++)
649 {
650 CalcParms(r, Ext, Grid, D, W, ad, x, y);
651 CalcError(r, ad, x, y, gridsize, Grid, D, W, E);
652 Search(r, Ext, gridsize, E);
653 if (isDone(r, Ext, E))
654 break;
655 }
656 if (iter == MAXITERATIONS)
657 {
658 printf("Reached maximum iteration count.\nResults may be bad.\n");
659 }
660
661 CalcParms(r, Ext, Grid, D, W, ad, x, y);
662
663 /*
664 * Find the 'taps' of the filter for use with Frequency
665 * Sampling. If odd or Negative symmetry, fix the taps
666 * according to Parks McClellan
667 */
668 for (i=0; i<=numtaps/2; i++)
669 {
670 if (symmetry == POSITIVE)
671 {
672 if (numtaps%2)
673 c = 1;
674 else
675 c = cos(Pi * (double)i/numtaps);
676 }
677 else
678 {
679 if (numtaps%2)
680 c = sin(Pi2 * (double)i/numtaps);
681 else
682 c = sin(Pi * (double)i/numtaps);
683 }
684 taps[i] = ComputeA((double)i/numtaps, r, ad, x, y)*c;
685 }
686
687 /*
688 * Frequency sampling design with calculated taps
689 */
690 FreqSample(numtaps, taps, h, symmetry);
691
692 /*
693 * Delete allocated memory
694 */
695 free(Grid);
696 free(W);
697 free(D);
698 free(E);
699 free(Ext);
700 free(x);
701 free(y);
702 free(ad);
703 }
704