PageRenderTime 43ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/R2006-03-17/octave-forge/main/signal/remez.cc

#
C++ | 916 lines | 514 code | 81 blank | 321 comment | 148 complexity | 07d2971df0a3491e73995c5875ba5045 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, GPL-3.0, LGPL-3.0
  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. * Sep 1999 - Paul Kienzle (pkienzle@cs.indiana.edu)
  22. * Modified for use in octave as a replacement for the matlab function
  23. * remez.mex. In particular, magnitude responses are required for all
  24. * band edges rather than one per band, griddensity is a parameter,
  25. * and errors are returned rather than printed directly.
  26. * Mar 2000 - Kai Habel (kahacjde@linux.zrz.tu-berlin.de)
  27. * Change: ColumnVector x=arg(i).vector_value();
  28. * to: ColumnVector x(arg(i).vector_value());
  29. * There appear to be some problems with the routine Search. See comments
  30. * therein [search for PAK:]. I haven't looked closely at the rest
  31. * of the code---it may also have some problems.
  32. *************************************************************************/
  33. #include <octave/oct.h>
  34. #include <cmath>
  35. #ifndef OCTAVE_LOCAL_BUFFER
  36. #include <vector>
  37. #define OCTAVE_LOCAL_BUFFER(T, buf, size) \
  38. std::vector<T> buf ## _vector (size); \
  39. T *buf = &(buf ## _vector[0])
  40. #endif
  41. #define CONST const
  42. #define BANDPASS 1
  43. #define DIFFERENTIATOR 2
  44. #define HILBERT 3
  45. #define NEGATIVE 0
  46. #define POSITIVE 1
  47. #define Pi 3.1415926535897932
  48. #define Pi2 6.2831853071795865
  49. #define GRIDDENSITY 16
  50. #define MAXITERATIONS 40
  51. /*******************
  52. * CreateDenseGrid
  53. *=================
  54. * Creates the dense grid of frequencies from the specified bands.
  55. * Also creates the Desired Frequency Response function (D[]) and
  56. * the Weight function (W[]) on that dense grid
  57. *
  58. *
  59. * INPUT:
  60. * ------
  61. * int r - 1/2 the number of filter coefficients
  62. * int numtaps - Number of taps in the resulting filter
  63. * int numband - Number of bands in user specification
  64. * double bands[] - User-specified band edges [2*numband]
  65. * double des[] - Desired response per band [2*numband]
  66. * double weight[] - Weight per band [numband]
  67. * int symmetry - Symmetry of filter - used for grid check
  68. * int griddensity
  69. *
  70. * OUTPUT:
  71. * -------
  72. * int gridsize - Number of elements in the dense frequency grid
  73. * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize]
  74. * double D[] - Desired response on the dense grid [gridsize]
  75. * double W[] - Weight function on the dense grid [gridsize]
  76. *******************/
  77. void CreateDenseGrid(int r, int numtaps, int numband, const double bands[],
  78. const double des[], const double weight[], int gridsize,
  79. double Grid[], double D[], double W[],
  80. int symmetry, int griddensity)
  81. {
  82. int i, j, k, band;
  83. double delf, lowf, highf, grid0;
  84. delf = 0.5/(griddensity*r);
  85. /*
  86. * For differentiator, hilbert,
  87. * symmetry is odd and Grid[0] = max(delf, bands[0])
  88. */
  89. grid0 = (symmetry == NEGATIVE) && (delf > bands[0]) ? delf : bands[0];
  90. j=0;
  91. for (band=0; band < numband; band++)
  92. {
  93. lowf = (band==0 ? grid0 : bands[2*band]);
  94. highf = bands[2*band + 1];
  95. k = (int)((highf - lowf)/delf + 0.5); /* .5 for rounding */
  96. for (i=0; i<k; i++)
  97. {
  98. D[j] = des[2*band] + i*(des[2*band+1]-des[2*band])/(k-1);
  99. W[j] = weight[band];
  100. Grid[j] = lowf;
  101. lowf += delf;
  102. j++;
  103. }
  104. Grid[j-1] = highf;
  105. }
  106. /*
  107. * Similar to above, if odd symmetry, last grid point can't be .5
  108. * - but, if there are even taps, leave the last grid point at .5
  109. */
  110. if ((symmetry == NEGATIVE) &&
  111. (Grid[gridsize-1] > (0.5 - delf)) &&
  112. (numtaps % 2))
  113. {
  114. Grid[gridsize-1] = 0.5-delf;
  115. }
  116. }
  117. /********************
  118. * InitialGuess
  119. *==============
  120. * Places Extremal Frequencies evenly throughout the dense grid.
  121. *
  122. *
  123. * INPUT:
  124. * ------
  125. * int r - 1/2 the number of filter coefficients
  126. * int gridsize - Number of elements in the dense frequency grid
  127. *
  128. * OUTPUT:
  129. * -------
  130. * int Ext[] - Extremal indexes to dense frequency grid [r+1]
  131. ********************/
  132. void InitialGuess(int r, int Ext[], int gridsize)
  133. {
  134. int i;
  135. for (i=0; i<=r; i++)
  136. Ext[i] = i * (gridsize-1) / r;
  137. }
  138. /***********************
  139. * CalcParms
  140. *===========
  141. *
  142. *
  143. * INPUT:
  144. * ------
  145. * int r - 1/2 the number of filter coefficients
  146. * int Ext[] - Extremal indexes to dense frequency grid [r+1]
  147. * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize]
  148. * double D[] - Desired response on the dense grid [gridsize]
  149. * double W[] - Weight function on the dense grid [gridsize]
  150. *
  151. * OUTPUT:
  152. * -------
  153. * double ad[] - 'b' in Oppenheim & Schafer [r+1]
  154. * double x[] - [r+1]
  155. * double y[] - 'C' in Oppenheim & Schafer [r+1]
  156. ***********************/
  157. void CalcParms(int r, int Ext[], double Grid[], double D[], double W[],
  158. double ad[], double x[], double y[])
  159. {
  160. int i, j, k, ld;
  161. double sign, xi, delta, denom, numer;
  162. /*
  163. * Find x[]
  164. */
  165. for (i=0; i<=r; i++)
  166. x[i] = cos(Pi2 * Grid[Ext[i]]);
  167. /*
  168. * Calculate ad[] - Oppenheim & Schafer eq 7.132
  169. */
  170. ld = (r-1)/15 + 1; /* Skips around to avoid round errors */
  171. for (i=0; i<=r; i++)
  172. {
  173. denom = 1.0;
  174. xi = x[i];
  175. for (j=0; j<ld; j++)
  176. {
  177. for (k=j; k<=r; k+=ld)
  178. if (k != i)
  179. denom *= 2.0*(xi - x[k]);
  180. }
  181. if (fabs(denom)<0.00001)
  182. denom = 0.00001;
  183. ad[i] = 1.0/denom;
  184. }
  185. /*
  186. * Calculate delta - Oppenheim & Schafer eq 7.131
  187. */
  188. numer = denom = 0;
  189. sign = 1;
  190. for (i=0; i<=r; i++)
  191. {
  192. numer += ad[i] * D[Ext[i]];
  193. denom += sign * ad[i]/W[Ext[i]];
  194. sign = -sign;
  195. }
  196. delta = numer/denom;
  197. sign = 1;
  198. /*
  199. * Calculate y[] - Oppenheim & Schafer eq 7.133b
  200. */
  201. for (i=0; i<=r; i++)
  202. {
  203. y[i] = D[Ext[i]] - sign * delta/W[Ext[i]];
  204. sign = -sign;
  205. }
  206. }
  207. /*********************
  208. * ComputeA
  209. *==========
  210. * Using values calculated in CalcParms, ComputeA calculates the
  211. * actual filter response at a given frequency (freq). Uses
  212. * eq 7.133a from Oppenheim & Schafer.
  213. *
  214. *
  215. * INPUT:
  216. * ------
  217. * double freq - Frequency (0 to 0.5) at which to calculate A
  218. * int r - 1/2 the number of filter coefficients
  219. * double ad[] - 'b' in Oppenheim & Schafer [r+1]
  220. * double x[] - [r+1]
  221. * double y[] - 'C' in Oppenheim & Schafer [r+1]
  222. *
  223. * OUTPUT:
  224. * -------
  225. * Returns double value of A[freq]
  226. *********************/
  227. double ComputeA(double freq, int r, double ad[], double x[], double y[])
  228. {
  229. int i;
  230. double xc, c, denom, numer;
  231. denom = numer = 0;
  232. xc = cos(Pi2 * freq);
  233. for (i=0; i<=r; i++)
  234. {
  235. c = xc - x[i];
  236. if (fabs(c) < 1.0e-7)
  237. {
  238. numer = y[i];
  239. denom = 1;
  240. break;
  241. }
  242. c = ad[i]/c;
  243. denom += c;
  244. numer += c*y[i];
  245. }
  246. return numer/denom;
  247. }
  248. /************************
  249. * CalcError
  250. *===========
  251. * Calculates the Error function from the desired frequency response
  252. * on the dense grid (D[]), the weight function on the dense grid (W[]),
  253. * and the present response calculation (A[])
  254. *
  255. *
  256. * INPUT:
  257. * ------
  258. * int r - 1/2 the number of filter coefficients
  259. * double ad[] - [r+1]
  260. * double x[] - [r+1]
  261. * double y[] - [r+1]
  262. * int gridsize - Number of elements in the dense frequency grid
  263. * double Grid[] - Frequencies on the dense grid [gridsize]
  264. * double D[] - Desired response on the dense grid [gridsize]
  265. * double W[] - Weight function on the desnse grid [gridsize]
  266. *
  267. * OUTPUT:
  268. * -------
  269. * double E[] - Error function on dense grid [gridsize]
  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. for (i=0; i<gridsize; i++)
  278. {
  279. A = ComputeA(Grid[i], r, ad, x, y);
  280. E[i] = W[i] * (D[i] - A);
  281. }
  282. }
  283. /************************
  284. * Search
  285. *========
  286. * Searches for the maxima/minima of the error curve. If more than
  287. * r+1 extrema are found, it uses the following heuristic (thanks
  288. * Chris Hanson):
  289. * 1) Adjacent non-alternating extrema deleted first.
  290. * 2) If there are more than one excess extrema, delete the
  291. * one with the smallest error. This will create a non-alternation
  292. * condition that is fixed by 1).
  293. * 3) If there is exactly one excess extremum, delete the smaller
  294. * of the first/last extremum
  295. *
  296. *
  297. * INPUT:
  298. * ------
  299. * int r - 1/2 the number of filter coefficients
  300. * int Ext[] - Indexes to Grid[] of extremal frequencies [r+1]
  301. * int gridsize - Number of elements in the dense frequency grid
  302. * double E[] - Array of error values. [gridsize]
  303. * OUTPUT:
  304. * -------
  305. * int Ext[] - New indexes to extremal frequencies [r+1]
  306. ************************/
  307. int Search(int r, int Ext[],
  308. int gridsize, double E[])
  309. {
  310. int i, j, k, l, extra; /* Counters */
  311. int up, alt;
  312. int *foundExt; /* Array of found extremals */
  313. /*
  314. * Allocate enough space for found extremals.
  315. */
  316. foundExt = (int *)malloc((2*r) * sizeof(int));
  317. k = 0;
  318. /*
  319. * Check for extremum at 0.
  320. */
  321. if (((E[0]>0.0) && (E[0]>E[1])) ||
  322. ((E[0]<0.0) && (E[0]<E[1])))
  323. foundExt[k++] = 0;
  324. /*
  325. * Check for extrema inside dense grid
  326. */
  327. for (i=1; i<gridsize-1; i++)
  328. {
  329. if (((E[i]>=E[i-1]) && (E[i]>E[i+1]) && (E[i]>0.0)) ||
  330. ((E[i]<=E[i-1]) && (E[i]<E[i+1]) && (E[i]<0.0))) {
  331. // PAK: we sometimes get too many extremal frequencies
  332. if (k >= 2*r) return -3;
  333. foundExt[k++] = i;
  334. }
  335. }
  336. /*
  337. * Check for extremum at 0.5
  338. */
  339. j = gridsize-1;
  340. if (((E[j]>0.0) && (E[j]>E[j-1])) ||
  341. ((E[j]<0.0) && (E[j]<E[j-1]))) {
  342. if (k >= 2*r) return -3;
  343. foundExt[k++] = j;
  344. }
  345. // PAK: we sometimes get not enough extremal frequencies
  346. if (k < r+1) return -2;
  347. /*
  348. * Remove extra extremals
  349. */
  350. extra = k - (r+1);
  351. assert(extra >= 0);
  352. while (extra > 0)
  353. {
  354. if (E[foundExt[0]] > 0.0)
  355. up = 1; /* first one is a maxima */
  356. else
  357. up = 0; /* first one is a minima */
  358. l=0;
  359. alt = 1;
  360. for (j=1; j<k; j++)
  361. {
  362. if (fabs(E[foundExt[j]]) < fabs(E[foundExt[l]]))
  363. l = j; /* new smallest error. */
  364. if ((up) && (E[foundExt[j]] < 0.0))
  365. up = 0; /* switch to a minima */
  366. else if ((!up) && (E[foundExt[j]] > 0.0))
  367. up = 1; /* switch to a maxima */
  368. else
  369. {
  370. alt = 0;
  371. // PAK: break now and you will delete the smallest overall
  372. // extremal. If you want to delete the smallest of the
  373. // pair of non-alternating extremals, then you must do:
  374. //
  375. // if (fabs(E[foundExt[j]]) < fabs(E[foundExt[j-1]])) l=j;
  376. // else l=j-1;
  377. break; /* Ooops, found two non-alternating */
  378. } /* extrema. Delete smallest of them */
  379. } /* if the loop finishes, all extrema are alternating */
  380. /*
  381. * If there's only one extremal and all are alternating,
  382. * delete the smallest of the first/last extremals.
  383. */
  384. if ((alt) && (extra == 1))
  385. {
  386. if (fabs(E[foundExt[k-1]]) < fabs(E[foundExt[0]]))
  387. /* Delete last extremal */
  388. l = k-1;
  389. // PAK: changed from l = foundExt[k-1];
  390. else
  391. /* Delete first extremal */
  392. l = 0;
  393. // PAK: changed from l = foundExt[0];
  394. }
  395. for (j=l; j<k-1; j++) /* Loop that does the deletion */
  396. {
  397. foundExt[j] = foundExt[j+1];
  398. assert(foundExt[j]<gridsize);
  399. }
  400. k--;
  401. extra--;
  402. }
  403. for (i=0; i<=r; i++)
  404. {
  405. assert(foundExt[i]<gridsize);
  406. Ext[i] = foundExt[i]; /* Copy found extremals to Ext[] */
  407. }
  408. free(foundExt);
  409. return 0;
  410. }
  411. /*********************
  412. * FreqSample
  413. *============
  414. * Simple frequency sampling algorithm to determine the impulse
  415. * response h[] from A's found in ComputeA
  416. *
  417. *
  418. * INPUT:
  419. * ------
  420. * int N - Number of filter coefficients
  421. * double A[] - Sample points of desired response [N/2]
  422. * int symmetry - Symmetry of desired filter
  423. *
  424. * OUTPUT:
  425. * -------
  426. * double h[] - Impulse Response of final filter [N]
  427. *********************/
  428. void FreqSample(int N, double A[], double h[], int symm)
  429. {
  430. int n, k;
  431. double x, val, M;
  432. M = (N-1.0)/2.0;
  433. if (symm == POSITIVE)
  434. {
  435. if (N%2)
  436. {
  437. for (n=0; n<N; n++)
  438. {
  439. val = A[0];
  440. x = Pi2 * (n - M)/N;
  441. for (k=1; k<=M; k++)
  442. val += 2.0 * A[k] * cos(x*k);
  443. h[n] = val/N;
  444. }
  445. }
  446. else
  447. {
  448. for (n=0; n<N; n++)
  449. {
  450. val = A[0];
  451. x = Pi2 * (n - M)/N;
  452. for (k=1; k<=(N/2-1); k++)
  453. val += 2.0 * A[k] * cos(x*k);
  454. h[n] = val/N;
  455. }
  456. }
  457. }
  458. else
  459. {
  460. if (N%2)
  461. {
  462. for (n=0; n<N; n++)
  463. {
  464. val = 0;
  465. x = Pi2 * (n - M)/N;
  466. for (k=1; k<=M; k++)
  467. val += 2.0 * A[k] * sin(x*k);
  468. h[n] = val/N;
  469. }
  470. }
  471. else
  472. {
  473. for (n=0; n<N; n++)
  474. {
  475. val = A[N/2] * sin(Pi * (n - M));
  476. x = Pi2 * (n - M)/N;
  477. for (k=1; k<=(N/2-1); k++)
  478. val += 2.0 * A[k] * sin(x*k);
  479. h[n] = val/N;
  480. }
  481. }
  482. }
  483. }
  484. /*******************
  485. * isDone
  486. *========
  487. * Checks to see if the error function is small enough to consider
  488. * the result to have converged.
  489. *
  490. * INPUT:
  491. * ------
  492. * int r - 1/2 the number of filter coeffiecients
  493. * int Ext[] - Indexes to extremal frequencies [r+1]
  494. * double E[] - Error function on the dense grid [gridsize]
  495. *
  496. * OUTPUT:
  497. * -------
  498. * Returns 1 if the result converged
  499. * Returns 0 if the result has not converged
  500. ********************/
  501. int isDone(int r, int Ext[], double E[])
  502. {
  503. int i;
  504. double min, max, current;
  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. return (((max-min)/max) < 0.0001);
  515. }
  516. /********************
  517. * remez
  518. *=======
  519. * Calculates the optimal (in the Chebyshev/minimax sense)
  520. * FIR filter impulse response given a set of band edges,
  521. * the desired reponse on those bands, and the weight given to
  522. * the error in those bands.
  523. *
  524. * INPUT:
  525. * ------
  526. * int numtaps - Number of filter coefficients
  527. * int numband - Number of bands in filter specification
  528. * double bands[] - User-specified band edges [2 * numband]
  529. * double des[] - User-specified band responses [numband]
  530. * double weight[] - User-specified error weights [numband]
  531. * int type - Type of filter
  532. *
  533. * OUTPUT:
  534. * -------
  535. * double h[] - Impulse response of final filter [numtaps]
  536. * returns - true on success, false on failure to converge
  537. ********************/
  538. int remez(double h[], int numtaps,
  539. int numband, const double bands[],
  540. const double des[], const double weight[],
  541. int type, int griddensity)
  542. {
  543. double *Grid, *W, *D, *E;
  544. int i, iter, gridsize, r, *Ext;
  545. double *taps, c;
  546. double *x, *y, *ad;
  547. int symmetry;
  548. if (type == BANDPASS)
  549. symmetry = POSITIVE;
  550. else
  551. symmetry = NEGATIVE;
  552. r = numtaps/2; /* number of extrema */
  553. if ((numtaps%2) && (symmetry == POSITIVE))
  554. r++;
  555. /*
  556. * Predict dense grid size in advance for memory allocation
  557. * .5 is so we round up, not truncate
  558. */
  559. gridsize = 0;
  560. for (i=0; i<numband; i++)
  561. {
  562. gridsize += (int)(2*r*griddensity*(bands[2*i+1] - bands[2*i]) + .5);
  563. }
  564. if (symmetry == NEGATIVE)
  565. {
  566. gridsize--;
  567. }
  568. /*
  569. * Dynamically allocate memory for arrays with proper sizes
  570. */
  571. Grid = (double *)malloc(gridsize * sizeof(double));
  572. D = (double *)malloc(gridsize * sizeof(double));
  573. W = (double *)malloc(gridsize * sizeof(double));
  574. E = (double *)malloc(gridsize * sizeof(double));
  575. Ext = (int *)malloc((r+1) * sizeof(int));
  576. taps = (double *)malloc((r+1) * sizeof(double));
  577. x = (double *)malloc((r+1) * sizeof(double));
  578. y = (double *)malloc((r+1) * sizeof(double));
  579. ad = (double *)malloc((r+1) * sizeof(double));
  580. /*
  581. * Create dense frequency grid
  582. */
  583. CreateDenseGrid(r, numtaps, numband, bands, des, weight,
  584. gridsize, Grid, D, W, symmetry, griddensity);
  585. InitialGuess(r, Ext, gridsize);
  586. /*
  587. * For Differentiator: (fix grid)
  588. */
  589. if (type == DIFFERENTIATOR)
  590. {
  591. for (i=0; i<gridsize; i++)
  592. {
  593. /* D[i] = D[i]*Grid[i]; */
  594. if (D[i] > 0.0001)
  595. W[i] = W[i]/Grid[i];
  596. }
  597. }
  598. /*
  599. * For odd or Negative symmetry filters, alter the
  600. * D[] and W[] according to Parks McClellan
  601. */
  602. if (symmetry == POSITIVE)
  603. {
  604. if (numtaps % 2 == 0)
  605. {
  606. for (i=0; i<gridsize; i++)
  607. {
  608. c = cos(Pi * Grid[i]);
  609. D[i] /= c;
  610. W[i] *= c;
  611. }
  612. }
  613. }
  614. else
  615. {
  616. if (numtaps % 2)
  617. {
  618. for (i=0; i<gridsize; i++)
  619. {
  620. c = sin(Pi2 * Grid[i]);
  621. D[i] /= c;
  622. W[i] *= c;
  623. }
  624. }
  625. else
  626. {
  627. for (i=0; i<gridsize; i++)
  628. {
  629. c = sin(Pi * Grid[i]);
  630. D[i] /= c;
  631. W[i] *= c;
  632. }
  633. }
  634. }
  635. /*
  636. * Perform the Remez Exchange algorithm
  637. */
  638. for (iter=0; iter<MAXITERATIONS; iter++)
  639. {
  640. CalcParms(r, Ext, Grid, D, W, ad, x, y);
  641. CalcError(r, ad, x, y, gridsize, Grid, D, W, E);
  642. int err = Search(r, Ext, gridsize, E);
  643. if (err) return err;
  644. for(int i=0; i <= r; i++) assert(Ext[i]<gridsize);
  645. if (isDone(r, Ext, E))
  646. break;
  647. }
  648. CalcParms(r, Ext, Grid, D, W, ad, x, y);
  649. /*
  650. * Find the 'taps' of the filter for use with Frequency
  651. * Sampling. If odd or Negative symmetry, fix the taps
  652. * according to Parks McClellan
  653. */
  654. for (i=0; i<=numtaps/2; i++)
  655. {
  656. if (symmetry == POSITIVE)
  657. {
  658. if (numtaps%2)
  659. c = 1;
  660. else
  661. c = cos(Pi * (double)i/numtaps);
  662. }
  663. else
  664. {
  665. if (numtaps%2)
  666. c = sin(Pi2 * (double)i/numtaps);
  667. else
  668. c = sin(Pi * (double)i/numtaps);
  669. }
  670. taps[i] = ComputeA((double)i/numtaps, r, ad, x, y)*c;
  671. }
  672. /*
  673. * Frequency sampling design with calculated taps
  674. */
  675. FreqSample(numtaps, taps, h, symmetry);
  676. /*
  677. * Delete allocated memory
  678. */
  679. free(Grid);
  680. free(W);
  681. free(D);
  682. free(E);
  683. free(Ext);
  684. free(x);
  685. free(y);
  686. free(ad);
  687. return iter<MAXITERATIONS?0:-1;
  688. }
  689. /* == Octave interface starts here ====================================== */
  690. DEFUN_DLD (remez, args, ,
  691. "b = remez(n, f, a [, w] [, ftype] [, griddensity])\n\
  692. Parks-McClellan optimal FIR filter design.\n\
  693. n gives the number of taps in the returned filter\n\
  694. f gives frequency at the band edges [ b1 e1 b2 e2 b3 e3 ...]\n\
  695. a gives amplitude at the band edges [ a(b1) a(e1) a(b2) a(e2) ...]\n\
  696. w gives weighting applied to each band\n\
  697. ftype is 'bandpass', 'hilbert' or 'differentiator'\n\
  698. griddensity determines how accurately the filter will be\n\
  699. constructed. The minimum value is 16, but higher numbers are\n\
  700. slower to compute.\n\
  701. \n\
  702. Frequency is in the range (0, 1), with 1 being the nyquist frequency")
  703. {
  704. octave_value_list retval;
  705. int i;
  706. int nargin = args.length();
  707. if (nargin < 3 || nargin > 6) {
  708. print_usage("remez");
  709. return retval;
  710. }
  711. int numtaps = NINT (args(0).double_value()) + 1; // #coeff = filter order+1
  712. if (numtaps < 4) {
  713. error("remez: number of taps must be an integer greater than 3");
  714. return retval;
  715. }
  716. ColumnVector o_bands(args(1).vector_value());
  717. int numbands = o_bands.length()/2;
  718. OCTAVE_LOCAL_BUFFER(double, bands, numbands*2);
  719. if (numbands < 1 || o_bands.length()%2 == 1) {
  720. error("remez: must have an even number of band edges");
  721. return retval;
  722. }
  723. for (i=1; i < o_bands.length(); i++) {
  724. if (o_bands(i)<o_bands(i-1)) {
  725. error("band edges must be nondecreasing");
  726. return retval;
  727. }
  728. }
  729. if (o_bands(0) < 0 || o_bands(1) > 1) {
  730. error("band edges must be in the range [0,1]");
  731. return retval;
  732. }
  733. for(i=0; i < 2*numbands; i++) bands[i] = o_bands(i)/2.0;
  734. ColumnVector o_response(args(2).vector_value());
  735. OCTAVE_LOCAL_BUFFER (double, response, numbands*2);
  736. if (o_response.length() != o_bands.length()) {
  737. error("remez: must have one response magnitude for each band edge");
  738. return retval;
  739. }
  740. for(i=0; i < 2*numbands; i++) response[i] = o_response(i);
  741. std::string stype = std::string("bandpass");
  742. int density = 16;
  743. OCTAVE_LOCAL_BUFFER (double, weight, numbands);
  744. for (i=0; i < numbands; i++) weight[i] = 1.0;
  745. if (nargin > 3) {
  746. if (args(3).is_real_matrix()) {
  747. ColumnVector o_weight(args(3).vector_value());
  748. if (o_weight.length() != numbands) {
  749. error("remez: need one weight for each band [=length(band)/2]");
  750. return retval;
  751. }
  752. for (i=0; i < numbands; i++) weight[i] = o_weight(i);
  753. }
  754. else if (args(3).is_string())
  755. stype = args(3).string_value();
  756. else if (args(3).is_real_scalar())
  757. density = NINT(args(3).double_value());
  758. else {
  759. error("remez: incorrect argument list");
  760. return retval;
  761. }
  762. }
  763. if (nargin > 4) {
  764. if (args(4).is_string() && !args(3).is_string())
  765. stype = args(4).string_value();
  766. else if (args(4).is_real_scalar() && !args(3).is_real_scalar())
  767. density = NINT(args(4).double_value());
  768. else {
  769. error("remez: incorrect argument list");
  770. return retval;
  771. }
  772. }
  773. if (nargin > 5) {
  774. if (args(5).is_real_scalar()
  775. && !args(4).is_real_scalar()
  776. && !args(3).is_real_scalar())
  777. density = NINT(args(4).double_value());
  778. else {
  779. error("remez: incorrect argument list");
  780. return retval;
  781. }
  782. }
  783. int itype;
  784. if (stype == "bandpass")
  785. itype = BANDPASS;
  786. else if (stype == "differentiator")
  787. itype = DIFFERENTIATOR;
  788. else if (stype == "hilbert")
  789. itype = HILBERT;
  790. else {
  791. error("remez: unknown ftype '%s'", stype.data());
  792. return retval;
  793. }
  794. if (density < 16) {
  795. error("remez: griddensity is too low; must be greater than 16");
  796. return retval;
  797. }
  798. OCTAVE_LOCAL_BUFFER (double, coeff, numtaps+5);
  799. int err = remez(coeff,numtaps,numbands,bands,response,weight,itype,density);
  800. if (err == -1)
  801. warning("remez: -- failed to converge -- returned filter may be bad.");
  802. else if (err == -2) {
  803. error("remez: insufficient extremals--cannot continue");
  804. return retval;
  805. }
  806. else if (err == -3) {
  807. error("remez: too many extremals--cannot continue");
  808. return retval;
  809. }
  810. ColumnVector h(numtaps);
  811. while(numtaps--) h(numtaps) = coeff[numtaps];
  812. return octave_value(h);
  813. }
  814. /*
  815. %!test
  816. %! b = [
  817. %! 0.0415131831103279
  818. %! 0.0581639884202646
  819. %! -0.0281579212691008
  820. %! -0.0535575358002337
  821. %! -0.0617245915143180
  822. %! 0.0507753178978075
  823. %! 0.2079018331396460
  824. %! 0.3327160895375440
  825. %! 0.3327160895375440
  826. %! 0.2079018331396460
  827. %! 0.0507753178978075
  828. %! -0.0617245915143180
  829. %! -0.0535575358002337
  830. %! -0.0281579212691008
  831. %! 0.0581639884202646
  832. %! 0.0415131831103279];
  833. %! assert(remez(15,[0,0.3,0.4,1],[1,1,0,0]),b,1e-14);
  834. */