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

# User Rev Content
1 root 1.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