X-Git-Url: http://git.johnwright.org/?p=fmit.git;a=blobdiff_plain;f=libs%2FMusic%2FFilter.cpp;fp=libs%2FMusic%2FFilter.cpp;h=21b60e23f363d994e7e99de60ad61cd525b0e453;hp=3a5434dc11236afef63247fcc1c4198c3b289fe2;hb=49947d1cd4506f5574b3be62ee90e9f00227d9fd;hpb=82c9faab9421b3d87a0faa84a73f55aaccbbb689 diff --git a/libs/Music/Filter.cpp b/libs/Music/Filter.cpp index 3a5434d..21b60e2 100644 --- a/libs/Music/Filter.cpp +++ b/libs/Music/Filter.cpp @@ -24,6 +24,11 @@ using namespace std; using namespace Math; #include "Music.h" +#include +#include +#include + +// DOESN'T WORK // b = fir1(32,[0.00001 0.23]); vector Music::fir1_lowpass(int n, double cutoff) { @@ -37,6 +42,7 @@ vector Music::fir1_lowpass(int n, double cutoff) return b; } +// DOESN'T WORK vector Music::fir1_highpass(int n, double cutoff) { vector b(n); @@ -57,17 +63,55 @@ vector Music::fir1_highpass(int n, double cutoff) return b; } +// cutoff in ]0;0.5[ where 0.5 is the Nyquist frequency vector Music::fir1_bandpass(int n, double low_cutoff, double high_cutoff) { - vector b(n, 0.0); - - if(low_cutoff>high_cutoff) - return b; - - vector lowf = fir1_lowpass(n, low_cutoff); - vector highf = fir1_highpass(n, high_cutoff); - - return conv(lowf, highf); + double *weights, *desired, *bands; + double *h; + int i; + + bands = (double *)malloc(6 * sizeof(double)); + weights = (double *)malloc(3 * sizeof(double)); + desired = (double *)malloc(3 * sizeof(double)); + h = (double *)malloc(1000 * sizeof(double)); + + desired[0] = 1; + desired[1] = 1; + desired[2] = 0; + + weights[0] = 10; + weights[1] = 1; + weights[2] = 10; + + bands[0] = 0; + bands[1] = 0.1; + bands[2] = 0.2; + bands[3] = 0.3; + bands[4] = 0.35; + bands[5] = 0.5; +// bands[0] = 0; +// bands[1] = low_cutoff/2; +// bands[2] = low_cutoff; +// bands[3] = high_cutoff; +// bands[4] = 0.5*(high_cutoff+0.5); +// bands[5] = 0.5; + + remez(h, n, 3, bands, desired, weights, BANDPASS); + + vector hv(n); + + for (i=0; i& imp_res) @@ -86,7 +130,7 @@ double Music::FIRRTFilter::operator()(double v) if(m_to_filter.size()>=m_imp_res.size()) { - // convolve + // convolve for(size_t i=0; i bands[0])) + bands[0] = delf; + + j=0; + for (band=0; band < numband; band++) + { + Grid[j] = bands[2*band]; + lowf = bands[2*band]; + highf = bands[2*band + 1]; + k = (int)((highf - lowf)/delf + 0.5); /* .5 for rounding */ + for (i=0; i (0.5 - delf)) && + (numtaps % 2)) + { + Grid[*gridsize-1] = 0.5-delf; + } +} + + +/******************** + * InitialGuess + *============== + * Places Extremal Frequencies evenly throughout the dense grid. + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * int gridsize - Number of elements in the dense frequency grid + * + * OUTPUT: + * ------- + * int Ext[] - Extremal indexes to dense frequency grid [r+1] + ********************/ + +void InitialGuess(int r, int Ext[], int gridsize) +{ + int i; + + for (i=0; i<=r; i++) + Ext[i] = i * (gridsize-1) / r; +} + + +/*********************** + * CalcParms + *=========== + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * int Ext[] - Extremal indexes to dense frequency grid [r+1] + * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize] + * double D[] - Desired response on the dense grid [gridsize] + * double W[] - Weight function on the dense grid [gridsize] + * + * OUTPUT: + * ------- + * double ad[] - 'b' in Oppenheim & Schafer [r+1] + * double x[] - [r+1] + * double y[] - 'C' in Oppenheim & Schafer [r+1] + ***********************/ + +void CalcParms(int r, int Ext[], double Grid[], double D[], double W[], + double ad[], double x[], double y[]) +{ + int i, j, k, ld; + double sign, xi, delta, denom, numer; + +/* + * Find x[] + */ + for (i=0; i<=r; i++) + x[i] = cos(Pi2 * Grid[Ext[i]]); + +/* + * Calculate ad[] - Oppenheim & Schafer eq 7.132 + */ + ld = (r-1)/15 + 1; /* Skips around to avoid round errors */ + for (i=0; i<=r; i++) + { + denom = 1.0; + xi = x[i]; + for (j=0; j0.0) && (E[0]>E[1])) || + ((E[0]<0.0) && (E[0]=E[i-1]) && (E[i]>E[i+1]) && (E[i]>0.0)) || + ((E[i]<=E[i-1]) && (E[i]0.0) && (E[j]>E[j-1])) || + ((E[j]<0.0) && (E[j] 0) + { + if (E[foundExt[0]] > 0.0) + up = 1; /* first one is a maxima */ + else + up = 0; /* first one is a minima */ + + l=0; + alt = 1; + for (j=1; j 0.0)) + up = 1; /* switch to a maxima */ + else + { + alt = 0; + break; /* Ooops, found two non-alternating */ + } /* extrema. Delete smallest of them */ + } /* if the loop finishes, all extrema are alternating */ + +/* + * If there's only one extremal and all are alternating, + * delete the smallest of the first/last extremals. + */ + if ((alt) && (extra == 1)) + { + if (fabs(E[foundExt[k-1]]) < fabs(E[foundExt[0]])) + l = foundExt[k-1]; /* Delete last extremal */ + else + l = foundExt[0]; /* Delete first extremal */ + } + + for (j=l; j max) + max = current; + } + if (((max-min)/max) < 0.0001) + return 1; + return 0; +} + +/******************** + * remez + *======= + * Calculates the optimal (in the Chebyshev/minimax sense) + * FIR filter impulse response given a set of band edges, + * the desired reponse on those bands, and the weight given to + * the error in those bands. + * + * INPUT: + * ------ + * int numtaps - Number of filter coefficients + * int numband - Number of bands in filter specification + * double bands[] - User-specified band edges [2 * numband] + * double des[] - User-specified band responses [numband] + * double weight[] - User-specified error weights [numband] + * int type - Type of filter + * + * OUTPUT: + * ------- + * double h[] - Impulse response of final filter [numtaps] + ********************/ + +void Music::remez(double h[], int numtaps, + int numband, double bands[], double des[], double weight[], + int type) +{ + double *Grid, *W, *D, *E; + int i, iter, gridsize, r, *Ext; + double *taps, c; + double *x, *y, *ad; + int symmetry; + + if (type == BANDPASS) + symmetry = POSITIVE; + else + symmetry = NEGATIVE; + + r = numtaps/2; /* number of extrema */ + if ((numtaps%2) && (symmetry == POSITIVE)) + r++; + +/* + * Predict dense grid size in advance for memory allocation + * .5 is so we round up, not truncate + */ + gridsize = 0; + for (i=0; i 0.0001) + W[i] = W[i]/Grid[i]; + } + } + +/* + * For odd or Negative symmetry filters, alter the + * D[] and W[] according to Parks McClellan + */ + if (symmetry == POSITIVE) + { + if (numtaps % 2 == 0) + { + for (i=0; i