ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/PDL-Audio/remez.c
Revision: 1.1
Committed: Tue Dec 28 01:05:16 2004 UTC (19 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-1_1, rel-1_2, HEAD
Log Message:
*** empty log message ***

File Contents

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