/* ----------------------------------------------------------------------- */ float *downsample(float *input, int samsin, int state_idx, double freq, int *samsout, int decimate, int first_time, int last_time) { static float b[2048]; static float *foutput = NULL; float beta = 0.0f; static int ncoeff = 127, ncoefft = 0; int init; if(input && (samsin > 0) && (decimate > 0) && *samsout) { if(decimate == 1) { return(input); } if(first_time){ int nbuff = (samsin/decimate) + (2*ncoeff); ncoeff = ((int)(freq * .005)) | 1; beta = .5f/decimate; foutput = (float *) realloc((void *) foutput, sizeof(float) * nbuff); for( ; nbuff > 0 ;) foutput[--nbuff] = 0.0; if( !lc_lin_fir(beta,&ncoeff,b)) { fprintf(stderr,"\nProblems computing interpolation filter\n"); free((void *) foutput); return(NULL); } ncoefft = (ncoeff/2) + 1; } /* endif new coefficients need to be computed */ if(first_time) init = 1; else if (last_time) init = 2; else init = 0; if(downsamp(input,foutput,samsin,samsout,state_idx,decimate,ncoefft,b,init)) { return(foutput); } else Fprintf(stderr,"Problems in downsamp() in downsample()\n"); } return(NULL); }
/* ----------------------------------------------------------------------- */ void FdFilter::FdFilterInitialize(float inFreq, float cFreq, int doHp, float fDur, int convertF, char *specShape, float *specArray, int nMagnitudes) { float beta = 0.0, *b = NULL; float ratio_t, ratio, freq1=inFreq; int pow2, i; insert = 1; decimate = 1; state = 1; arrayLeftover = 0; arrayIndex = 0; arraySamplesUsed = 0; trueOutputFreq = inFreq; if(specShape || (specArray && (nMagnitudes > 1))) { doHp = -1; /* flag that this is an equalization filtering */ } else { if(convertF) { freq1 = inFreq; } else { /* it is just a symmetric FIR */ if(cFreq >= (freq1 = inFreq)/2.0) { fprintf(stderr,"Unreasonable corner frequency specified to filter() (%f)\n",cFreq); } } } if(specShape) { FILE *specStream = fopen(specShape, "r"); if(specStream) { int nSpect, ind; char line[500]; float fs; if(fgets(line,500, specStream)) { int nItems = sscanf(line,"%d %d %f", &pow2, &nSpect, &fs); if((nItems == 3) && (fs != inFreq)) { // This should be a fatal error fprintf(stderr,"Filter spec (%f) does not match input frequency (%f)\n",fs,inFreq); fprintf(stderr,"The filtering results will probably not be what you want!\n"); } b = new float [nSpect]; nCoeff = (nSpect - 1); /* represents actual filter-kernel length, instead of half filter length when using externsl filter. */ for(i=0; i < nSpect; i++) { if((! fgets(line,500,specStream)) || (sscanf(line,"%d %f", &ind, &(b[i])) != 2)) { fprintf(stderr, "Parsing error in spect ratio file %s\n",specShape); } } } else { fprintf(stderr,"Bad format in spectrum file %s\n", specShape); } fclose(specStream); } else { fprintf(stderr,"Can't open %s as a spectrum file\n",specShape); } } else if( specArray && (nMagnitudes > 1)) { // Note: nMagnitudes MUST be ((2^k)+1) for k > 1. nCoeff = nMagnitudes - 1; int nft = nCoeff * 2; pow2 = 1; while( (1 << pow2) < nft) { pow2++; } b = specArray; // Note: b must not be deleted in this case! } else { /* it is not an eq filter */ if(convertF) { /* get a ratio of integers close to desired freq. ratio. */ ratio = cFreq/freq1; ratprx(ratio,&insert,&decimate,FD_MAX_DECIMATE); ratio_t = ((float)insert)/((float)decimate); if(fabs(1.0-ratio_t) < .01) { fprintf(stderr,"Input and output frequencies are essentially equal!\n"); } trueOutputFreq = ratio_t * freq1; // if(cFreq != trueOutputFreq) { // fprintf(stderr, // "Warning: The output frequency obtained (%f) is not the frequency requested (%f)\n", // trueOutputFreq, cFreq); // } cFreq = trueOutputFreq; nCoeff = ((int)(freq1 * insert * fDur)) | 1; if(cFreq < freq1) beta = (.5 * cFreq)/(insert * freq1); else beta = .5/insert; } else { beta = cFreq/freq1; nCoeff = ((int)(freq1 * fDur)) | 1; } /* Generate the symmetric FIR filter coefficients. */ b = new float [1 + nCoeff/2]; lc_lin_fir(beta,&nCoeff,b); if(insert > 1) { /* scale up filter coeffs. to maintain precision in output */ float fact = (float)insert; for(i=nCoeff/2; i>=0; i--) b[i] *= fact; } } /* end else it is not an eq filter */ nCoeffBy2 = nCoeff/2; if(doHp >= 0) { /* Is it a simple high- or low-pass filter? */ mirror_filter(b,doHp); int nf2 = nCoeff << 1; nFFT = 128; pow2 = 7; while(nf2 > nFFT) { nFFT *= 2; pow2++; } } else { /* it is a filter with the magnitude response specified in b. */ nFFT = nCoeff * 2; pow2 = 2; while((1 << pow2) < nFFT) pow2++; } nFFTBy2 = nFFT/2; x = new float [nFFT]; y = new float [nFFT]; xf = new float [nFFT]; yf = new float [nFFT]; leftovers = new short [nFFT]; maxInput = FD_FBUF_SIZE/insert; outputDelayed = new float [FD_FBUF_SIZE+nCoeff+nFFT]; float ftscale = 1.0/(float)nFFT; ft = new FFT(pow2); if(doHp >= 0) { /* position the filter kernel to be symmetric about time=0 */ /* Note that this assumes an odd number of symmetric filter coefficients. */ for(i=0; i <= nCoeffBy2; i++) { xf[i] = ftscale * fCoeff[i+nCoeffBy2]; yf[i] = 0.0; } for( ; i < nCoeff; i++) { xf[nFFT - nCoeff + i] = ftscale * fCoeff[i-nCoeffBy2-1]; yf[nFFT - nCoeff + i] = 0.0; } for(i=nCoeffBy2 ;i < (nFFT-nCoeffBy2);i++) xf[i] = yf[i] = 0.0; ft->fft(xf,yf); } else { /* Install the magnitude response symmetrically. */ for(i=0; i <= nCoeff; i++) { xf[i] = ftscale * b[i]; yf[i] = 0.0; } for( ; i < nFFT; i++) { xf[i] = xf[nFFT - i]; yf[i] = 0.0; } } /* The filter, regardless of origin, is now in the frequency domain. */ if(specShape && !( specArray && (nMagnitudes > 1))) delete b; b = NULL; filterMode = doHp; }