CSL  6.0
FIR.cpp
Go to the documentation of this file.
1 //
2 // FIR.cpp -- CSL FIR filter class
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5 
6 #include "FIR.h"
7 #include <stdlib.h>
8 #include <math.h>
9 #include <string.h>
10 
11 using namespace csl;
12 
13 // FilterSpecification class
14 
15 // Constants used by the design algorithm
16 
17 #define BANDPASS 1
18 #define DIFFERENTIATOR 2
19 #define HILBERT 3
20 
21 // Constructors
22 
23 FilterSpecification::FilterSpecification (unsigned numTaps, unsigned numBands, double *freqs, double *resps, double *weights)
24  : mTapData(NULL), mNumTaps(numTaps), mNumBands(numBands), mFrequencies(NULL), mResponses(NULL), mWeights(NULL) {
25  setNumTaps(numTaps);
26  setFrequencies(freqs);
27  setResponses(resps);
28  setWeights(weights);
29  if (freqs != NULL && resps != NULL && weights != NULL)
30  planFilter();
31 }
32 
34  delete[] mFrequencies;
35  delete[] mResponses;
36  delete[] mWeights;
37  delete[] mTapData;
38 }
39 
40 // Accessors
41 
42 void FilterSpecification::setFrequencies(double *frequencies) {
43  if (mFrequencies == NULL)
44  mFrequencies = new double[mNumBands * 2];
45  if (frequencies != NULL)
46  memcpy(mFrequencies, frequencies, (mNumBands * 2 * sizeof(double)));
47 }
48 
49 void FilterSpecification::setResponses(double *responses) {
50  if (mResponses == NULL)
51  mResponses = new double[mNumBands];
52  if (responses != NULL)
53  memcpy(mResponses, responses, (mNumBands * sizeof(double)));
54 }
55 
56 void FilterSpecification::setWeights(double *weights) {
57  if (mWeights == NULL)
58  mWeights = new double[mNumBands];
59  if (weights != NULL)
60  memcpy(mWeights, weights, (mNumBands * sizeof(double)));
61 }
62 
63 void FilterSpecification::setNumTaps(unsigned numTaps) {
64 // if (numTaps < 128) {
65  mNumTaps = numTaps;
66  if (mTapData != NULL)
67  delete[] mTapData;
68  mTapData = new double[mNumTaps];
69 // } else
70  if (numTaps > 128)
71  logMsg("Use convolution for long FIRs.");
72 }
73 
74 // method to plan the filter (execute the search/iterate algorithm)
75 
76 void remez(double h[], int numtaps, int numband, double bands[], double des[], double weight[], int type);
77 
79  bool shouldNormalize = false;
80  unsigned i; // check of the frequencies values are normalized (0.0 - 0.5 Fs) or not
81  for (i = 0; i < (mNumBands * 2); i++) {
82  if (mFrequencies[i] > 0.5) {
83  shouldNormalize = true;
84  break;
85  }
86  }
87  if (shouldNormalize) // normalize the frequencies if they're given in Hz
88  for (i = 0; i < (mNumBands * 2); i++)
90  // now call the iterative design function
91 // remez(double h[], int numtaps, int numband, double bands[], double des[], double weight[], int type)
93 }
94 
95 // FIR class
96 
97 FIR::FIR(UnitGenerator & in, unsigned numTaps, float * tapDelays) : Effect(in) {
99  setTaps(numTaps, tapDelays);
100 
101  if (tapDelays == NULL) { // If passed num taps, but no IR, then just make a cheap lowpass averaging filter.
102  for (unsigned i = 0; i < numTaps; i++)
103  mFilterSpec->mTapData[i] = 0.5;
104  }
105 }
106 
107 // Read in a tap data file
108 FIR::FIR(UnitGenerator & in, char * fileName) : Effect(in) {
110  readTaps(fileName);
111 }
112 
113 // give it a filter specification object
114 
115 FIR::FIR (FilterSpecification & fs) : mFilterSpec(&fs) {
116  resetDLine();
117  fs.planFilter();
118 }
119 
120 FIR::FIR (UnitGenerator & in, FilterSpecification & fs) : Effect(in), mFilterSpec(&fs) {
121  resetDLine();
122  fs.planFilter();
123 }
124 
126  delete[] mDLine;
127 }
128 
131  for (unsigned i = 0; i < mFilterSpec->mNumTaps; i++) // empty the delay line
132  mDLine[i] = 0.0;
133  mOffset = 0;
134 }
135 
136 void FIR::setTaps(unsigned numTaps, float *tapDelays) {
137  mFilterSpec->setNumTaps(numTaps);
138  if (tapDelays != NULL)
139  memcpy(mFilterSpec->mTapData, tapDelays, (numTaps * sizeof(double)));
140  resetDLine();
141  mOffset = 0;
142 }
143 
144 void FIR::readTaps(char * fileName) {
145  unsigned i, numTaps;
146  FILE * configData;
147 
148  configData = fopen(fileName, "r"); // open config file
149  fscanf(configData, "%d\n", &numTaps); // read # of taps
150 
151  float * theTapData = new float[numTaps];
152  for (i = 0; i < numTaps; i++) // read tap coefficients
153  fscanf(configData, "%f\n", &theTapData[i]);
154  setTaps(numTaps, theTapData);
155  fclose(configData);
156 
157 #ifdef CSL_DEBUG
158  logMsg("Taps:"); // print out the tap data
159  for (i = 0; i < numTaps; i++)
160  logMsg("\t%g\n ", theTapData[i]);
161 #endif
162  resetDLine();
163 }
164 
166  unsigned nt = mFilterSpec->mNumTaps;
167  double * tapDataPtr = mFilterSpec->mTapData;
168  logMsg("Taps (%d): ", nt); // print out the tap data
169  for (unsigned i = 0; i < nt; i++)
170  logMsgNN("%g, ", *tapDataPtr++);
171  logMsg("");
172 }
173 
174 void FIR::nextBuffer(Buffer &outputBuffer, unsigned outBufNum) throw (CException) {
175  float sum;
176  int tap;
177  sample * outPtr = outputBuffer.buffer(outBufNum);
178  unsigned numFrames = outputBuffer.mNumFrames;
179  unsigned numTaps = mFilterSpec->mNumTaps;
180  double *tapDataPtr = mFilterSpec->mTapData;
181 #ifdef CSL_DEBUG
182  logMsg("FIR nextBuffer");
183 #endif
184  Effect::pullInput(numFrames); // get some input
185  sample *inputPtr = mInputPtr;
186 
187  for (unsigned i = 0; i < numFrames; i++) { // sample block loop
188  sum = 0.0; // output sample accumulator
189  mDLine[mOffset] = inputPtr[i]; // write input sample into delay line
190  tap = mOffset; // initial reader tap position
191  for (unsigned j = 0; j < numTaps; j++) { // loop through delay line taps
192  sum += mDLine[tap] * tapDataPtr[j]; // sum scaled d_line data (previous sample * weighting)
193  tap--; // decrement tap offset
194  if (tap < 0) tap = numTaps - 1; // wrap around
195  } // end of tap-per-sample loop
196  outPtr[i] = sum; // write sum sample to output buffer
197  mOffset++; // increment and wrap offset
198  mOffset %= numTaps; // "%=" means modulo-assignment
199  } // end of sample block loop
200  return;
201 }
202 
203 ///////////////////////////////////////////////////////////////////////////////////
204 
205 /**************************************************************************
206  * Parks-McClellan algorithm for FIR filter design (C version)
207  *-------------------------------------------------
208  * Copyright (c) 1995,1998 Jake Janovetz (janovetz@uiuc.edu)
209  *
210  * This library is free software; you can redistribute it and/or
211  * modify it under the terms of the GNU Library General Public
212  * License as published by the Free Software Foundation; either
213  * version 2 of the License, or (at your option) any later version.
214  *
215  * This library is distributed in the hope that it will be useful,
216  * but WITHOUT ANY WARRANTY; without even the implied warranty of
217  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
218  * Library General Public License for more details.
219 
220  * You should have received a copy of the GNU Library General Public
221  * License along with this library; if not, write to the Free
222  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
223  *
224  *************************************************************************/
225 
226 #define NEGATIVE 0
227 #define POSITIVE 1
228 
229 #define Pi 3.1415926535897932
230 #define Pi2 6.2831853071795865
231 #define GRIDDENSITY 16
232 #define MAXITERATIONS 40
233 
234 /*******************
235  * CreateDenseGrid
236  *=================
237  * Creates the dense grid of frequencies from the specified bands.
238  * Also creates the Desired Frequency Response function (D[]) and
239  * the Weight function (W[]) on that dense grid
240  *
241  *
242  * INPUT:
243  * ------
244  * int r - 1/2 the number of filter coefficients
245  * int numtaps - Number of taps in the resulting filter
246  * int numband - Number of bands in user specification
247  * double bands[] - User-specified band edges [2*numband]
248  * double des[] - Desired response per band [numband]
249  * double weight[] - Weight per band [numband]
250  * int symmetry - Symmetry of filter - used for grid check
251  *
252  * OUTPUT:
253  * -------
254  * int gridsize - Number of elements in the dense frequency grid
255  * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize]
256  * double D[] - Desired response on the dense grid [gridsize]
257  * double W[] - Weight function on the dense grid [gridsize]
258  *******************/
259 
260 void CreateDenseGrid(int r, int numtaps, int numband, double bands[],
261  double des[], double weight[], int *gridsize,
262  double Grid[], double D[], double W[],
263  int symmetry)
264 {
265  int i, j, k, band;
266  double delf, lowf, highf;
267 
268  delf = 0.5/(GRIDDENSITY*r);
269 
270 /*
271  * For differentiator, hilbert,
272  * symmetry is odd and Grid[0] = max(delf, band[0])
273  */
274 
275  if ((symmetry == NEGATIVE) && (delf > bands[0]))
276  bands[0] = delf;
277 
278  j=0;
279  for (band=0; band < numband; band++)
280  {
281  Grid[j] = bands[2*band];
282  lowf = bands[2*band];
283  highf = bands[2*band + 1];
284  k = (int)((highf - lowf)/delf + 0.5); /* .5 for rounding */
285  for (i=0; i<k; i++)
286  {
287  D[j] = des[band];
288  W[j] = weight[band];
289  Grid[j] = lowf;
290  lowf += delf;
291  j++;
292  }
293  Grid[j-1] = highf;
294  }
295 
296 /*
297  * Similar to above, if odd symmetry, last grid point can't be .5
298  * - but, if there are even taps, leave the last grid point at .5
299  */
300  if ((symmetry == NEGATIVE) &&
301  (Grid[*gridsize-1] > (0.5 - delf)) &&
302  (numtaps % 2))
303  {
304  Grid[*gridsize-1] = 0.5-delf;
305  }
306 }
307 
308 
309 /********************
310  * InitialGuess
311  *==============
312  * Places Extremal Frequencies evenly throughout the dense grid.
313  *
314  *
315  * INPUT:
316  * ------
317  * int r - 1/2 the number of filter coefficients
318  * int gridsize - Number of elements in the dense frequency grid
319  *
320  * OUTPUT:
321  * -------
322  * int Ext[] - Extremal indexes to dense frequency grid [r+1]
323  ********************/
324 
325 void InitialGuess(int r, int Ext[], int gridsize)
326 {
327  int i;
328 
329  for (i=0; i<=r; i++)
330  Ext[i] = i * (gridsize-1) / r;
331 }
332 
333 
334 /***********************
335  * CalcParms
336  *===========
337  *
338  *
339  * INPUT:
340  * ------
341  * int r - 1/2 the number of filter coefficients
342  * int Ext[] - Extremal indexes to dense frequency grid [r+1]
343  * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize]
344  * double D[] - Desired response on the dense grid [gridsize]
345  * double W[] - Weight function on the dense grid [gridsize]
346  *
347  * OUTPUT:
348  * -------
349  * double ad[] - 'b' in Oppenheim & Schafer [r+1]
350  * double x[] - [r+1]
351  * double y[] - 'C' in Oppenheim & Schafer [r+1]
352  ***********************/
353 
354 void CalcParms(int r, int Ext[], double Grid[], double D[], double W[],
355  double ad[], double x[], double y[])
356 {
357  int i, j, k, ld;
358  double sign, xi, delta, denom, numer;
359 
360 /*
361  * Find x[]
362  */
363  for (i=0; i<=r; i++)
364  x[i] = cos(Pi2 * Grid[Ext[i]]);
365 
366 /*
367  * Calculate ad[] - Oppenheim & Schafer eq 7.132
368  */
369  ld = (r-1)/15 + 1; /* Skips around to avoid round errors */
370  for (i=0; i<=r; i++)
371  {
372  denom = 1.0;
373  xi = x[i];
374  for (j=0; j<ld; j++)
375  {
376  for (k=j; k<=r; k+=ld)
377  if (k != i)
378  denom *= 2.0*(xi - x[k]);
379  }
380  if (fabs(denom)<0.00001)
381  denom = 0.00001;
382  ad[i] = 1.0/denom;
383  }
384 
385 /*
386  * Calculate delta - Oppenheim & Schafer eq 7.131
387  */
388  numer = denom = 0;
389  sign = 1;
390  for (i=0; i<=r; i++)
391  {
392  numer += ad[i] * D[Ext[i]];
393  denom += sign * ad[i]/W[Ext[i]];
394  sign = -sign;
395  }
396  delta = numer/denom;
397  sign = 1;
398 
399 /*
400  * Calculate y[] - Oppenheim & Schafer eq 7.133b
401  */
402  for (i=0; i<=r; i++)
403  {
404  y[i] = D[Ext[i]] - sign * delta/W[Ext[i]];
405  sign = -sign;
406  }
407 }
408 
409 
410 /*********************
411  * ComputeA
412  *==========
413  * Using values calculated in CalcParms, ComputeA calculates the
414  * actual filter response at a given frequency (freq). Uses
415  * eq 7.133a from Oppenheim & Schafer.
416  *
417  *
418  * INPUT:
419  * ------
420  * double freq - Frequency (0 to 0.5) at which to calculate A
421  * int r - 1/2 the number of filter coefficients
422  * double ad[] - 'b' in Oppenheim & Schafer [r+1]
423  * double x[] - [r+1]
424  * double y[] - 'C' in Oppenheim & Schafer [r+1]
425  *
426  * OUTPUT:
427  * -------
428  * Returns double value of A[freq]
429  *********************/
430 
431 double ComputeA(double freq, int r, double ad[], double x[], double y[])
432 {
433  int i;
434  double xc, c, denom, numer;
435 
436  denom = numer = 0;
437  xc = cos(Pi2 * freq);
438  for (i=0; i<=r; i++)
439  {
440  c = xc - x[i];
441  if (fabs(c) < 1.0e-7)
442  {
443  numer = y[i];
444  denom = 1;
445  break;
446  }
447  c = ad[i]/c;
448  denom += c;
449  numer += c*y[i];
450  }
451  return numer/denom;
452 }
453 
454 
455 /************************
456  * CalcError
457  *===========
458  * Calculates the Error function from the desired frequency response
459  * on the dense grid (D[]), the weight function on the dense grid (W[]),
460  * and the present response calculation (A[])
461  *
462  *
463  * INPUT:
464  * ------
465  * int r - 1/2 the number of filter coefficients
466  * double ad[] - [r+1]
467  * double x[] - [r+1]
468  * double y[] - [r+1]
469  * int gridsize - Number of elements in the dense frequency grid
470  * double Grid[] - Frequencies on the dense grid [gridsize]
471  * double D[] - Desired response on the dense grid [gridsize]
472  * double W[] - Weight function on the desnse grid [gridsize]
473  *
474  * OUTPUT:
475  * -------
476  * double E[] - Error function on dense grid [gridsize]
477  ************************/
478 
479 void CalcError(int r, double ad[], double x[], double y[],
480  int gridsize, double Grid[],
481  double D[], double W[], double E[])
482 {
483  int i;
484  double A;
485 
486  for (i=0; i<gridsize; i++)
487  {
488  A = ComputeA(Grid[i], r, ad, x, y);
489  E[i] = W[i] * (D[i] - A);
490  }
491 }
492 
493 /************************
494  * Search
495  *========
496  * Searches for the maxima/minima of the error curve. If more than
497  * r+1 extrema are found, it uses the following heuristic (thanks
498  * Chris Hanson):
499  * 1) Adjacent non-alternating extrema deleted first.
500  * 2) If there are more than one excess extrema, delete the
501  * one with the smallest error. This will create a non-alternation
502  * condition that is fixed by 1).
503  * 3) If there is exactly one excess extremum, delete the smaller
504  * of the first/last extremum
505  *
506  *
507  * INPUT:
508  * ------
509  * int r - 1/2 the number of filter coefficients
510  * int Ext[] - Indexes to Grid[] of extremal frequencies [r+1]
511  * int gridsize - Number of elements in the dense frequency grid
512  * double E[] - Array of error values. [gridsize]
513  * OUTPUT:
514  * -------
515  * int Ext[] - New indexes to extremal frequencies [r+1]
516  ************************/
517 
518 void Search(int r, int Ext[],
519  int gridsize, double E[])
520 {
521  int i, j, k, l, extra; /* Counters */
522  int up, alt;
523  int *foundExt; /* Array of found extremals */
524 
525 /*
526  * Allocate enough space for found extremals.
527  */
528  foundExt = (int *)malloc((2*r) * sizeof(int));
529  k = 0;
530 
531 /*
532  * Check for extremum at 0.
533  */
534  if (((E[0]>0.0) && (E[0]>E[1])) ||
535  ((E[0]<0.0) && (E[0]<E[1])))
536  foundExt[k++] = 0;
537 
538 /*
539  * Check for extrema inside dense grid
540  */
541  for (i=1; i<gridsize-1; i++)
542  {
543  if (((E[i]>=E[i-1]) && (E[i]>E[i+1]) && (E[i]>0.0)) ||
544  ((E[i]<=E[i-1]) && (E[i]<E[i+1]) && (E[i]<0.0)))
545  foundExt[k++] = i;
546  }
547 
548 /*
549  * Check for extremum at 0.5
550  */
551  j = gridsize-1;
552  if (((E[j]>0.0) && (E[j]>E[j-1])) ||
553  ((E[j]<0.0) && (E[j]<E[j-1])))
554  foundExt[k++] = j;
555 
556 
557 /*
558  * Remove extra extremals
559  */
560  extra = k - (r+1);
561 
562  while (extra > 0)
563  {
564  if (E[foundExt[0]] > 0.0)
565  up = 1; /* first one is a maxima */
566  else
567  up = 0; /* first one is a minima */
568 
569  l=0;
570  alt = 1;
571  for (j=1; j<k; j++)
572  {
573  if (fabs(E[foundExt[j]]) < fabs(E[foundExt[l]]))
574  l = j; /* new smallest error. */
575  if ((up) && (E[foundExt[j]] < 0.0))
576  up = 0; /* switch to a minima */
577  else if (( ! up) && (E[foundExt[j]] > 0.0))
578  up = 1; /* switch to a maxima */
579  else
580  {
581  alt = 0;
582  break; /* Ooops, found two non-alternating */
583  } /* extrema. Delete smallest of them */
584  } /* if the loop finishes, all extrema are alternating */
585 
586 /*
587  * If there's only one extremal and all are alternating,
588  * delete the smallest of the first/last extremals.
589  */
590  if ((alt) && (extra == 1))
591  {
592  if (fabs(E[foundExt[k-1]]) < fabs(E[foundExt[0]]))
593  l = foundExt[k-1]; /* Delete last extremal */
594  else
595  l = foundExt[0]; /* Delete first extremal */
596  }
597 
598  for (j=l; j<k; j++) /* Loop that does the deletion */
599  {
600  foundExt[j] = foundExt[j+1];
601  }
602  k--;
603  extra--;
604  }
605 
606  for (i=0; i<=r; i++)
607  {
608  Ext[i] = foundExt[i]; /* Copy found extremals to Ext[] */
609  }
610 
611  free(foundExt);
612 }
613 
614 
615 /*********************
616  * FreqSample
617  *============
618  * Simple frequency sampling algorithm to determine the impulse
619  * response h[] from A's found in ComputeA
620  *
621  *
622  * INPUT:
623  * ------
624  * int N - Number of filter coefficients
625  * double A[] - Sample points of desired response [N/2]
626  * int symmetry - Symmetry of desired filter
627  *
628  * OUTPUT:
629  * -------
630  * double h[] - Impulse Response of final filter [N]
631  *********************/
632 void FreqSample(int N, double A[], double h[], int symm)
633 {
634  int n, k;
635  double x, val, M;
636 
637  M = (N-1.0)/2.0;
638  if (symm == POSITIVE)
639  {
640  if (N%2)
641  {
642  for (n=0; n<N; n++)
643  {
644  val = A[0];
645  x = Pi2 * (n - M)/N;
646  for (k=1; k<=M; k++)
647  val += 2.0 * A[k] * cos(x*k);
648  h[n] = val/N;
649  }
650  }
651  else
652  {
653  for (n=0; n<N; n++)
654  {
655  val = A[0];
656  x = Pi2 * (n - M)/N;
657  for (k=1; k<=(N/2-1); k++)
658  val += 2.0 * A[k] * cos(x*k);
659  h[n] = val/N;
660  }
661  }
662  }
663  else
664  {
665  if (N%2)
666  {
667  for (n=0; n<N; n++)
668  {
669  val = 0;
670  x = Pi2 * (n - M)/N;
671  for (k=1; k<=M; k++)
672  val += 2.0 * A[k] * sin(x*k);
673  h[n] = val/N;
674  }
675  }
676  else
677  {
678  for (n=0; n<N; n++)
679  {
680  val = A[N/2] * sin(Pi * (n - M));
681  x = Pi2 * (n - M)/N;
682  for (k=1; k<=(N/2-1); k++)
683  val += 2.0 * A[k] * sin(x*k);
684  h[n] = val/N;
685  }
686  }
687  }
688 }
689 
690 /*******************
691  * isDone
692  *========
693  * Checks to see if the error function is small enough to consider
694  * the result to have converged.
695  *
696  * INPUT:
697  * ------
698  * int r - 1/2 the number of filter coeffiecients
699  * int Ext[] - Indexes to extremal frequencies [r+1]
700  * double E[] - Error function on the dense grid [gridsize]
701  *
702  * OUTPUT:
703  * -------
704  * Returns 1 if the result converged
705  * Returns 0 if the result has not converged
706  ********************/
707 
708 short isDone(int r, int Ext[], double E[])
709 {
710  int i;
711  double min, max, current;
712 
713  min = max = fabs(E[Ext[0]]);
714  for (i=1; i<=r; i++)
715  {
716  int off = Ext[i];
717  current = fabs(E[off]);
718  if (current < min)
719  min = current;
720  if (current > max)
721  max = current;
722  }
723  if (((max-min)/max) < 0.0001)
724  return 1;
725  return 0;
726 }
727 
728 /********************
729  * remez
730  *=======
731  * Calculates the optimal (in the Chebyshev/minimax sense)
732  * FIR filter impulse response given a set of band edges,
733  * the desired reponse on those bands, and the weight given to
734  * the error in those bands.
735  *
736  * INPUT:
737  * ------
738  * int numtaps - Number of filter coefficients
739  * int numband - Number of bands in filter specification
740  * double bands[] - User-specified band edges [2 * numband]
741  * double des[] - User-specified band responses [numband]
742  * double weight[] - User-specified error weights [numband]
743  * int type - Type of filter
744  *
745  * OUTPUT:
746  * -------
747  * double h[] - Impulse response of final filter [numtaps]
748  ********************/
749 
750 void remez(double h[], int numtaps,
751  int numband, double bands[], double des[], double weight[],
752  int type)
753 {
754  double *Grid, *W, *D, *E;
755  int i, iter, gridsize, r, *Ext;
756  double *taps, c;
757  double *x, *y, *ad;
758  int symmetry;
759 
760  if (type == BANDPASS)
761  symmetry = POSITIVE;
762  else
763  symmetry = NEGATIVE;
764 
765  r = numtaps/2; /* number of extrema */
766  if ((numtaps%2) && (symmetry == POSITIVE))
767  r++;
768 
769 /*
770  * Predict dense grid size in advance for memory allocation
771  * .5 is so we round up, not truncate
772  */
773  gridsize = 0;
774  for (i=0; i<numband; i++)
775  {
776  gridsize += (int)(2*r*GRIDDENSITY*(bands[2*i+1] - bands[2*i]) + .5);
777  }
778  if (symmetry == NEGATIVE)
779  {
780  gridsize--;
781  }
782 
783 /*
784  * Dynamically allocate memory for arrays with proper sizes
785  */
786  Grid = (double *)malloc(gridsize * sizeof(double));
787  D = (double *)malloc(gridsize * sizeof(double));
788  W = (double *)malloc(gridsize * sizeof(double));
789  E = (double *)malloc(gridsize * sizeof(double));
790  Ext = (int *)malloc((r+1) * sizeof(int));
791  taps = (double *)malloc((r+1) * sizeof(double));
792  x = (double *)malloc((r+1) * sizeof(double));
793  y = (double *)malloc((r+1) * sizeof(double));
794  ad = (double *)malloc((r+1) * sizeof(double));
795 
796 /*
797  * Create dense frequency grid
798  */
799  CreateDenseGrid(r, numtaps, numband, bands, des, weight,
800  &gridsize, Grid, D, W, symmetry);
801  InitialGuess(r, Ext, gridsize);
802 
803 /*
804  * For Differentiator: (fix grid)
805  */
806  if (type == DIFFERENTIATOR)
807  {
808  for (i=0; i<gridsize; i++)
809  {
810 /* D[i] = D[i]*Grid[i]; */
811  if (D[i] > 0.0001)
812  W[i] = W[i]/Grid[i];
813  }
814  }
815 
816 /*
817  * For odd or Negative symmetry filters, alter the
818  * D[] and W[] according to Parks McClellan
819  */
820  if (symmetry == POSITIVE)
821  {
822  if (numtaps % 2 == 0)
823  {
824  for (i=0; i<gridsize; i++)
825  {
826  c = cos(Pi * Grid[i]);
827  D[i] /= c;
828  W[i] *= c;
829  }
830  }
831  }
832  else
833  {
834  if (numtaps % 2)
835  {
836  for (i=0; i<gridsize; i++)
837  {
838  c = sin(Pi2 * Grid[i]);
839  D[i] /= c;
840  W[i] *= c;
841  }
842  }
843  else
844  {
845  for (i=0; i<gridsize; i++)
846  {
847  c = sin(Pi * Grid[i]);
848  D[i] /= c;
849  W[i] *= c;
850  }
851  }
852  }
853 
854 /*
855  * Perform the Remez Exchange algorithm
856  */
857  for (iter=0; iter<MAXITERATIONS; iter++)
858  {
859  CalcParms(r, Ext, Grid, D, W, ad, x, y);
860  CalcError(r, ad, x, y, gridsize, Grid, D, W, E);
861  Search(r, Ext, gridsize, E);
862  if (isDone(r, Ext, E))
863  break;
864  }
865  if (iter == MAXITERATIONS)
866  {
867  printf("Reached maximum iteration count.\nResults may be bad.\n");
868  }
869 
870  CalcParms(r, Ext, Grid, D, W, ad, x, y);
871 
872 /*
873  * Find the 'taps' of the filter for use with Frequency
874  * Sampling. If odd or Negative symmetry, fix the taps
875  * according to Parks McClellan
876  */
877  for (i=0; i<=numtaps/2; i++)
878  {
879  if (symmetry == POSITIVE)
880  {
881  if (numtaps%2)
882  c = 1;
883  else
884  c = cos(Pi * (double)i/numtaps);
885  }
886  else
887  {
888  if (numtaps%2)
889  c = sin(Pi2 * (double)i/numtaps);
890  else
891  c = sin(Pi * (double)i/numtaps);
892  }
893  taps[i] = ComputeA((double)i/numtaps, r, ad, x, y)*c;
894  }
895 
896 /*
897  * Frequency sampling design with calculated taps
898  */
899  FreqSample(numtaps, taps, h, symmetry);
900 
901 /*
902  * Delete allocated memory
903  */
904  free(Grid);
905  free(W);
906  free(D);
907  free(E);
908  free(Ext);
909  free(x);
910  free(y);
911  free(ad);
912 }
void setNumTaps(unsigned numTaps)
Definition: FIR.cpp:63
#define max(a, b)
Definition: matrix.h:156
void logMsg(const char *format,...)
These are the public logging messages.
Definition: CGestalt.cpp:292
void pullInput(Buffer &outputBuffer)
Definition: CSL_Core.cpp:1122
#define NEGATIVE
Definition: FIR.cpp:226
#define DIFFERENTIATOR
Definition: FIR.cpp:18
void resetDLine()
zero-out mDline and reallocate memory if necessary;
Definition: FIR.cpp:129
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
Definition: Accessor.h:17
forward declaration
Definition: FIR.h:25
Effect – mix-in for classes that have unit generators as inputs (like filters).
Definition: CSL_Core.h:466
sample * mDLine
mNumTaps length delay line
Definition: FIR.h:95
#define min(a, b)
Definition: matrix.h:157
void FreqSample(int N, double A[], double h[], int symm)
Definition: FIR.cpp:632
void remez(double h[], int numtaps, int numband, double bands[], double des[], double weight[], int type)
Definition: FIR.cpp:750
#define Pi
Definition: FIR.cpp:229
void nextBuffer(Buffer &outputBuffer, unsigned outBufNum)
The work method...
Definition: FIR.cpp:174
#define BANDPASS
Definition: FIR.cpp:17
#define MAXITERATIONS
Definition: FIR.cpp:232
void setFrequencies(double *frequencies)
Accessors.
Definition: FIR.cpp:42
void CreateDenseGrid(int r, int numtaps, int numband, double bands[], double des[], double weight[], int *gridsize, double Grid[], double D[], double W[], int symmetry)
Definition: FIR.cpp:260
static float frameRateF()
default frame rate as a float
Definition: CGestalt.cpp:52
void print_taps()
Definition: FIR.cpp:165
#define GRIDDENSITY
Definition: FIR.cpp:231
short isDone(int r, int Ext[], double E[])
Definition: FIR.cpp:708
#define POSITIVE
Definition: FIR.cpp:227
~FIR()
Definition: FIR.cpp:125
unsigned mNumTaps
number of taps desired
Definition: FIR.h:39
double * mTapData
the FIR tap weights (created by the planFilter method)
Definition: FIR.h:42
float sample
(could be changed to int, or double)
Definition: CSL_Types.h:191
void Search(int r, int Ext[], int gridsize, double E[])
Definition: FIR.cpp:518
void InitialGuess(int r, int Ext[], int gridsize)
Definition: FIR.cpp:325
void planFilter()
method to plan the filter (execute the search/iterate algorithm)
Definition: FIR.cpp:78
void CalcError(int r, double ad[], double x[], double y[], int gridsize, double Grid[], double D[], double W[], double E[])
Definition: FIR.cpp:479
FilterSpecification(unsigned numTaps=0, unsigned numBands=0, double *freqs=NULL, double *resps=NULL, double *weights=NULL)
Constructors.
Definition: FIR.cpp:23
#define Pi2
Definition: FIR.cpp:230
double * mWeights
band error weights (mNumBands)
Definition: FIR.h:48
unsigned mOffset
offset "pointer" for loop counting Here are the sample buffers (dynamically allocated) ...
Definition: FIR.h:93
double ComputeA(double freq, int r, double ad[], double x[], double y[])
Definition: FIR.cpp:431
void CalcParms(int r, int Ext[], double Grid[], double D[], double W[], double ad[], double x[], double y[])
Definition: FIR.cpp:354
unsigned mNumBands
length of specification
Definition: FIR.h:45
Buffer – the multi-channel sample buffer class (passed around between generators and IO guys)...
Definition: CSL_Core.h:106
double * mResponses
band responses (mNumBands)
Definition: FIR.h:47
void logMsgNN(const char *format,...)
no-newline versions
Definition: CGestalt.cpp:299
FIR(UnitGenerator &in, unsigned numTaps=2, float *tapDelay=NULL)
Various constructors Takes a UGen, and optionally the number of taps and the tap IR array...
Definition: FIR.cpp:97
void setResponses(double *responses)
Definition: FIR.cpp:49
void setWeights(double *weights)
Definition: FIR.cpp:56
forward declaration
Definition: CSL_Core.h:241
double * mFrequencies
band edge frequencies (2 * mNumBands)
Definition: FIR.h:46
void readTaps(char *fileName)
Definition: FIR.cpp:144
void setTaps(unsigned numTaps, float *tapDelays)
Definition: FIR.cpp:136
Base class of CSL exceptions (written upper-case). Has a string message.
FilterSpecification * mFilterSpec
Definition: FIR.h:92