/* * Copyright (c) 1983-2023 Trevor Wishart and Composers Desktop Project Ltd * http://www.trevorwishart.co.uk * http://www.composersdesktop.com * This file is part of the CDP System. The CDP System is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The CDP System is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the CDP System; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* floatsams version*/ #include #include #include #include #include #include #include #include #include #include #include /*RWD*/ #include //#ifdef unix #define round(x) lround((x)) //#endif #define MINUS96DB (0.000016) static void filtering(int n,int chans,float *buf, double *a,double *b,double *y,double *z,double *d,double *e,double *ampl,dataptr dz); static double check_float_limits(double sum, dataptr dz); static int newvalue(int valno,int valincrno, int sampcntno, dataptr dz); static int newfval(int *fsams,dataptr dz); static int do_filters(dataptr dz); static int do_qvary_filters(dataptr dz); static int do_fvary_filters(dataptr dz); static void print_filter_frqs(dataptr dz); static int do_varifilter(dataptr dz); static int do_sweep_filter(dataptr dz); static double getfrq(double lfrq,double hfrq,double sfrq,dataptr dz); static int do_allpass_filter(dataptr dz); static int allpass(float *buf,int chans,double prescale,dataptr dz); static int varidelay_allpass(float *buf,int chans,double prescale,dataptr dz); static int do_eq_filter(dataptr dz); static float multifilter(double *dll,double *dbb,double *dnn,double *dhh,double *dpp, double qfac,double coeff,float input,dataptr dz); static int do_lphp_filter(dataptr dz); static int my_modulus(int x,int y); static void lphp_filt_chan(double *e1,double *e2,double *s1,double *s2, double *den1,double *den2,double *cn,dataptr dz,int chan); static int do_fvary2_filters(dataptr dz); /****************************** FILTER_PROCESS *************************/ int filter_process(dataptr dz) { int exit_status = FINISHED; int filter_tail = 0, tail_extend = 0, was_tail_extend = 0, bufspace; // NEW MAY 2012 int do_norm = 0, chans = dz->infile->channels, sndendset = 0; double inmaxsamp = 0.0, outmaxsamp = 0.0, maxsamp = 0.0; float *buf = dz->sampbuf[0]; int n, m, k, sndend = 0; int framend, framestart, framesize = F_SECSIZE, framecnt = dz->buflen/framesize; switch(dz->process) { case(FLTBANKV): if(dz->vflag[2]) do_norm = 1; break; case(FLTBANKV2): if(dz->vflag[1]) do_norm = 1; break; case(FLTBANKN): do_norm = 1; break; } // MAY 2012 TO HERE if(dz->process==FLTBANKC) { print_filter_frqs(dz); return(FINISHED); } display_virtual_time(0,dz); // NEW MAY 2012 if(do_norm) { fprintf(stdout,"INFO: Assessing input level.\n"); fflush(stdout); while(dz->samps_left > 0) { if((exit_status = read_samps(buf,dz))<0) return(exit_status); for(n = 0;n < dz->ssampsread;n++) inmaxsamp = max(inmaxsamp,fabs(buf[n])); } if(inmaxsamp <= 0.0) { sprintf(errstr,"No level found in input signal\n"); return DATA_ERROR; } sndseekEx(dz->ifd[0],0,0); reset_filedata_counters(dz); if(dz->process==FLTBANKV) { if((exit_status = newfval(&(dz->iparam[FLT_FSAMS]),dz))<0) return(exit_status); } else if(dz->process==FLTBANKV2) { dz->iparam[FLT_FSAMS] = dz->iparam[FLT_BLOKSIZE]; dz->param[FLT_TIMESTEP] = (double)dz->iparam[FLT_BLOKSIZE]/(double)dz->infile->srate; dz->param[FLT_TOTALTIME] = 0.0; if((exit_status = newfval2(dz->parray[FLT_FBRK],dz->parray[FLT_HBRK],dz))<0) return(exit_status); } else if(dz->process==FLTBANKN) { if(dz->brksize[FLT_Q]) exit_status = do_qvary_filters(dz); else exit_status = do_filters(dz); } fprintf(stdout,"INFO: Assessing output level.\n"); fflush(stdout); while(dz->samps_left > 0 || filter_tail > 0) { memset((char *)dz->sampbuf[0],0,(size_t) (dz->buflen * sizeof(float))); if(filter_tail || tail_extend) { dz->ssampsread = 0; } else { if((exit_status = read_samps(dz->sampbuf[0],dz))<0) return(exit_status); if(dz->samps_left <= 0) { if(dz->process==FLTBANKV || dz->process==FLTBANKV2) filter_tail = round(dz->param[FILT_TAILV] * (double)dz->infile->srate) * dz->infile->channels; else filter_tail = (int)round((dz->param[FILT_TAIL] * (double)dz->infile->srate) * dz->infile->channels); if(filter_tail == 0) { was_tail_extend = 1; tail_extend = 1; } } } if(filter_tail) { bufspace = dz->buflen - dz->ssampsread; if(bufspace >= filter_tail) { dz->ssampsread += filter_tail; filter_tail = 0; } else { dz->ssampsread = dz->buflen; filter_tail -= bufspace; } } else if(tail_extend) { bufspace = dz->buflen; dz->ssampsread = dz->buflen; } switch(dz->process) { case(FLTBANKV): exit_status = do_fvary_filters(dz); break; case(FLTBANKV2):exit_status = do_fvary2_filters(dz); break; case(FLTBANKN): if(dz->brksize[FLT_Q]) exit_status = do_qvary_filters(dz); else exit_status = do_filters(dz); break; } if(exit_status <0) return(exit_status); if(tail_extend) { sndend = dz->buflen; framend = dz->buflen; for(k = framecnt; k > 0; k--) { // Search backwards thro buffer, frame by frame framestart = framend - framesize; maxsamp = 0.0; for(n = framend-chans;n >= framestart;n-=chans) { for(m=0;m maxsamp) { if(!sndendset) { // If samples cease to be zero sndend = n + chans; // Mark start of end-zeros in buffer sndendset = 1; // and flag that snd end has been found } maxsamp = fabs(buf[n+m]); } } if(maxsamp < MINUS96DB) { // If max level in frame falls below -96dB if(sndendset) { // If we found a place in buffer after which samples were all zero dz->ssampsread = sndend; // Mark this as end of output, and quit the main filtering loop tail_extend = 0; // by setting tail_extend to zero dz->samps_left = 0; // SAFETY break; } else // If we didn't find place .... sndend = framestart; // Then all samples in the frame are zero. } // So move snd end to start of current frame. } // .. and search backwards thro previous frame if(tail_extend == 0) break; framend = framestart; } } if(tail_extend) tail_extend++; if(dz->ssampsread > 0) { for(n = 0;n < dz->ssampsread;n++) outmaxsamp = max(outmaxsamp,(double)fabs(buf[n])); } } if(outmaxsamp <= 0.0) { sprintf(errstr,"No level found in output signal.\n"); return DATA_ERROR; } dz->param[FLT_GAIN] *= (inmaxsamp/outmaxsamp); sndseekEx(dz->ifd[0],0,0); reset_filedata_counters(dz); if(dz->process==FLTBANKV || dz->process==FLTBANKV2) { for(n = 0;niparam[FLT_CNT];n++) { dz->parray[FLT_FRQ][n] = dz->parray[FLT_INFRQ][n]; dz->parray[FLT_AMP][n] = dz->parray[FLT_INAMP][n]; dz->parray[FLT_LASTFVAL][n] = dz->parray[FLT_FRQ][n]; dz->parray[FLT_LASTAVAL][n] = dz->parray[FLT_AMP][n]; } dz->iparam[FLT_FRQ_INDEX] = dz->iparam[FLT_CNT]; dz->iparam[FLT_TIMES_CNT] = 1; } // dz->iparam[FLT_FRQ_INDEX] = dz->iparam[FLT_CNT]; // RWD June 2025 moved up; only for varybanks. // dz->iparam[FLT_TIMES_CNT] = 1; filter_tail = 0; tail_extend = 0; sndendset = 0; sndend = 0; tail_extend = 0; was_tail_extend = 0; fprintf(stdout,"INFO: Running filter.\n"); fflush(stdout); } // MAY 2012, TO HERE if(dz->process==FLTBANKV) { if((exit_status = newfval(&(dz->iparam[FLT_FSAMS]),dz))<0) return(exit_status); } else if(dz->process==FLTBANKV2) { dz->iparam[FLT_FSAMS] = dz->iparam[FLT_BLOKSIZE]; dz->param[FLT_TIMESTEP] = (double)dz->iparam[FLT_BLOKSIZE]/(double)dz->infile->srate; dz->param[FLT_TOTALTIME] = 0.0; if((exit_status = newfval2(dz->parray[FLT_FBRK],dz->parray[FLT_HBRK],dz))<0) return(exit_status); } while(dz->samps_left > 0 || filter_tail > 0 || tail_extend) { memset((char *)dz->sampbuf[0],0,(size_t) (dz->buflen * sizeof(float))); if(filter_tail > 0 || tail_extend) { dz->ssampsread = 0; } else { if((exit_status = read_samps(dz->sampbuf[0],dz))<0) return(exit_status); if(dz->samps_left <= 0) { if(dz->process==FLTBANKV || dz->process==FLTBANKV2) filter_tail = round(dz->param[FILT_TAILV] * (double)dz->infile->srate) * dz->infile->channels; else filter_tail = (int)round((dz->param[FILT_TAIL] * (double)dz->infile->srate) * dz->infile->channels); if(filter_tail == 0) { was_tail_extend = 1; tail_extend = 1; fprintf(stdout,"INFO: Writing Filter tail.\n"); fflush(stdout); } } } if(filter_tail) { bufspace = dz->buflen - dz->ssampsread; if(bufspace >= filter_tail) { dz->ssampsread += filter_tail; filter_tail = 0; } else { dz->ssampsread = dz->buflen; filter_tail -= bufspace; } } else if(tail_extend) { bufspace = dz->buflen; dz->ssampsread = dz->buflen; } switch(dz->process) { case(FLTBANKN): case(FLTBANKU): if(dz->brksize[FLT_Q]) exit_status = do_qvary_filters(dz); else exit_status = do_filters(dz); break; case(FLTBANKV): exit_status = do_fvary_filters(dz); break; case(FLTBANKV2):exit_status = do_fvary2_filters(dz); break; case(FLTSWEEP): exit_status = do_sweep_filter(dz); break; case(FSTATVAR): exit_status = do_varifilter(dz); break; case(ALLPASS): exit_status = do_allpass_filter(dz); break; case(EQ): exit_status = do_eq_filter(dz); break; case(LPHP): exit_status = do_lphp_filter(dz); break; } if(exit_status <0) return(exit_status); if(tail_extend) { sndend = dz->buflen; framend = dz->buflen; for(k = framecnt; k > 0; k--) { // Search backwards thro buffer, frame by frame framestart = framend - framesize; maxsamp = 0.0; for(n = framend-chans;n >= framestart;n-=chans) { for(m=0;m maxsamp) { if(!sndendset) { // If samples cease to be zero sndend = n + chans; // Mark start of end-zeros in buffer sndendset = 1; // and flag that snd end has been found } maxsamp = fabs(buf[n+m]); } } if(maxsamp < MINUS96DB) { // If max level in frame falls below -96dB if(sndendset) { // If we found a place in buffer after which samples were all zero dz->ssampsread = sndend; // Mark this as end of output, and quit the main filtering loop tail_extend = 0; // by setting tail_extend to zero dz->samps_left = 0; // SAFETY break; } else // If we didn't find place .... sndend = framestart; // Then all samples in the frame are zero. } // So move snd end to start of current frame. } // .. and search backwards thro previous frame if(tail_extend == 0) break; framend = framestart; } if((maxsamp < MINUS96DB) && !sndendset) { // Entire buffer is "zero" tail_extend = 0; // Force exit by seting tail_extend to zero dz->samps_left = 0; // SAFETY // DO NOT set samps_read to 0, as there may be input samples still to write } } if(tail_extend) tail_extend++; if(dz->ssampsread > 0) { if(sloom && was_tail_extend) { // Force Loom progress bar to respond to tail-write if(!tail_extend) dz->total_samps_written = dz->insams[0]; else dz->total_samps_written = (long)round((double)dz->insams[0] * ((double)(tail_extend % 8)/8.0)); dz->total_samps_written -= dz->ssampsread; } if((exit_status = write_samps(dz->sampbuf[0],dz->ssampsread,dz))<0) return(exit_status); } } if(dz->iparam[FLT_OVFLW] > 0) { if(!sloom && !sloombatch) fprintf(stdout,"Number of overflows: %d\n",dz->iparam[FLT_OVFLW]); else fprintf(stdout,"INFO: Number of overflows: %d\n",dz->iparam[FLT_OVFLW]); fflush(stdout); } return(FINISHED); } /*************************** DO_FVARY_FILTERS *****************************/ int do_fvary_filters(dataptr dz) { int exit_status; int n, m, fno, chans = dz->infile->channels; float *buf = dz->sampbuf[0]; double *fincr = dz->parray[FLT_FINCR]; double *aincr = dz->parray[FLT_AINCR]; double *ampl = dz->parray[FLT_AMPL]; double *a = dz->parray[FLT_A]; double *b = dz->parray[FLT_B]; double *y = dz->parray[FLT_Y]; double *z = dz->parray[FLT_Z]; double *d = dz->parray[FLT_D]; double *e = dz->parray[FLT_E]; int fsams = dz->iparam[FLT_FSAMS]; if (dz->vflag[DROP_OUT_AT_OVFLOW]) { for (n = 0; n < dz->ssampsread; n += chans) { if(fsams <= 0) { if((exit_status = newfval(&fsams,dz))<0) return(exit_status); } if(dz->brksize[FLT_Q]) { if((dz->iparam[FLT_SAMS] -= chans) <= 0) { if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) { sprintf(errstr,"Ran out of Q values: do_fvary_filters()\n"); return(PROGRAM_ERROR); } dz->iparam[FLT_SAMS] *= chans; } } if((dz->iparam[FLT_BLOKCNT] -= chans) <= 0) { for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) { get_coeffs1(fno,dz); get_coeffs2(fno,dz); } if(dz->brksize[FLT_Q]) dz->param[FLT_Q] *= dz->param[FLT_Q_INCR]; for(m=0;miparam[FLT_CNT];m++) { dz->parray[FLT_FRQ][m] *= fincr[m]; dz->parray[FLT_AMP][m] *= aincr[m]; } dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE] * chans; } filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz); if(dz->iparam[FLT_OVFLW] > 0) { sprintf(errstr,"Filter overflowed\n"); return(GOAL_FAILED); } fsams--; } } else { for (n = 0; n < dz->ssampsread; n += chans) { if(fsams <= 0) { if((exit_status = newfval(&fsams,dz))<0) return(exit_status); } if(dz->brksize[FLT_Q]) { if((dz->iparam[FLT_SAMS] -= chans) <= 0) { if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) { sprintf(errstr,"Ran out of Q values: do_fvary_filters()\n"); return(PROGRAM_ERROR); } dz->iparam[FLT_SAMS] *= chans; } } if((dz->iparam[FLT_BLOKCNT] -= chans) <= 0) { for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) { get_coeffs1(fno,dz); get_coeffs2(fno,dz); } if(dz->brksize[FLT_Q]) dz->param[FLT_Q] *= dz->param[FLT_Q_INCR]; for(m=0;miparam[FLT_CNT];m++) { dz->parray[FLT_FRQ][m] *= fincr[m]; dz->parray[FLT_AMP][m] *= aincr[m]; } dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE] * chans; } filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz); fsams--; } } dz->iparam[FLT_FSAMS] = fsams; return(CONTINUE); } /*************************** DO_FILTERS *******************************/ int do_filters(dataptr dz) { int n; int chans = dz->infile->channels; float *buf = dz->sampbuf[0]; double *ampl = dz->parray[FLT_AMPL]; double *a = dz->parray[FLT_A]; double *b = dz->parray[FLT_B]; double *y = dz->parray[FLT_Y]; double *z = dz->parray[FLT_Z]; double *d = dz->parray[FLT_D]; double *e = dz->parray[FLT_E]; for (n = 0; n < dz->ssampsread; n += chans) filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz); return(CONTINUE); } /*************************** DO_QVARY_FILTERS *****************************/ int do_qvary_filters(dataptr dz) { int n; int fno, chans = dz->infile->channels; float *buf = dz->sampbuf[0]; double *ampl = dz->parray[FLT_AMPL]; double *a = dz->parray[FLT_A]; double *b = dz->parray[FLT_B]; double *y = dz->parray[FLT_Y]; double *z = dz->parray[FLT_Z]; double *d = dz->parray[FLT_D]; double *e = dz->parray[FLT_E]; for (n = 0; n < dz->ssampsread; n += chans) { if((dz->iparam[FLT_SAMS] -= chans) <= 0) { if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) { sprintf(errstr,"Ran out of Q values: do_qvary_filters()\n"); return(PROGRAM_ERROR); } dz->iparam[FLT_SAMS] *= chans; } if((dz->iparam[FLT_BLOKCNT] -= chans) <= 0) { for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) get_coeffs2(fno,dz); dz->param[FLT_Q] *= dz->param[FLT_Q_INCR]; dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE] * chans; } filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz); } return(CONTINUE); } /******************************* NEWVALUE *************************** * * VAL is the base value from which we calculate. * VALINCR is the value increment per block of samples. * SAMPCNT is the number of samples from 1 brkpnt val to next. */ int newvalue(int valno,int valincrno, int sampcntno, dataptr dz) { double *p; double ratio, one_over_steps; double thistime; double thisval; int linear_flag = FALSE; if(dz->process==ALLPASS && valno==FLT_DELAY) linear_flag = dz->vflag[FLT_LINDELAY]; p = dz->brkptr[valno]; if(p - dz->brk[valno] >= dz->brksize[valno] * 2) return(FALSE); thistime = (double)round((*p++) * dz->infile->srate); thisval = *p++; dz->iparam[sampcntno] = round(thistime - dz->lastind[valno]); /* steps = no_of_samples/sampsize_of_blok: therefore.. */ one_over_steps = (double)dz->iparam[FLT_BLOKSIZE]/(double)dz->iparam[sampcntno]; if(linear_flag) dz->param[valincrno] = (thisval - dz->lastval[valno]) * one_over_steps; else { ratio = (thisval/dz->lastval[valno]); dz->param[valincrno] = pow(ratio,(one_over_steps)); } dz->param[valno] = dz->lastval[valno]; dz->lastval[valno] = thisval; dz->lastind[valno] = thistime; dz->brkptr[valno] = p; return(TRUE); } /******************************* NEWFVAL *************************** * * VAL is the base value from which we calculate. * VALINCR is the value increment per block of samples. * FSAMS is the number of samples (per channel) from 1 brkpnt val to next. * brk is the particular table we're accessing. */ int newfval(int *fsams,dataptr dz) { int thistime, lasttime; double rratio, one_over_steps; int n,m,k; double thisval; double *lastfval = dz->parray[FLT_LASTFVAL]; double *lastaval = dz->parray[FLT_LASTAVAL]; double *aincr = dz->parray[FLT_AINCR]; double *fincr = dz->parray[FLT_FINCR]; int total_frqcnt = dz->iparam[FLT_CNT] * dz->iparam[FLT_TIMESLOTS]; if(dz->iparam[FLT_TIMES_CNT]>dz->iparam[FLT_TIMESLOTS]) { sprintf(errstr,"Ran off end of filter data: newfval()\n"); return(PROGRAM_ERROR); } k = dz->iparam[FLT_TIMES_CNT]; lasttime = dz->lparray[FLT_SAMPTIME][k-1]; thistime = dz->lparray[FLT_SAMPTIME][k]; *fsams = thistime - lasttime; /* steps = fsams/FLT_BLOKSIZE: therefore ... */ one_over_steps = (double)dz->iparam[FLT_BLOKSIZE]/(double)(*fsams); if(dz->iparam[FLT_FRQ_INDEX] >= total_frqcnt) return(FINISHED); for(n=0, m= dz->iparam[FLT_FRQ_INDEX];niparam[FLT_CNT];n++,m++) { /* FREQUENCY */ thisval = dz->parray[FLT_INFRQ][m]; if(flteq(lastfval[n],thisval)) fincr[n] = 1.0; else { rratio = (thisval/lastfval[n]); fincr[n] = pow(rratio,one_over_steps); } dz->parray[FLT_FRQ][n] = lastfval[n]; lastfval[n] = thisval; /* AMPLITUDE */ thisval = dz->parray[FLT_INAMP][m]; if(flteq(thisval,lastaval[n])) aincr[n] = 1.0; else { rratio = (thisval/lastaval[n]); aincr[n] = pow(rratio,one_over_steps); } dz->parray[FLT_AMP][n] = lastaval[n]; lastaval[n] = thisval; } dz->iparam[FLT_FRQ_INDEX] += dz->iparam[FLT_CNT]; dz->iparam[FLT_TIMES_CNT]++; return(FINISHED); } /************************** FILTERING ****************************/ void filtering(int n,int chans,float *buf,double *a,double *b,double *y,double *z, double *d,double *e,double *ampl,dataptr dz) { double input, sum, xx; int chno, this_samp, fno, i; for(chno = 0; chno < chans; chno++) { this_samp = n + chno; input = (double)buf[this_samp]; sum = 0.0; for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) { i = (fno * chans) + chno; xx = input + (a[fno] * y[i]) + (b[fno] * z[i]); z[i] = y[i]; y[i] = xx; if(dz->vflag[FLT_DBLFILT]) { xx += (a[fno] * d[i]) + (b[fno] * e[i]); e[i] = d[i]; d[i] = xx; } sum += (xx * ampl[fno]); } sum *= dz->param[FLT_GAIN]; sum = check_float_limits(sum,dz); buf[this_samp] = (float) sum; } } /************************** IO_FILTERING ****************************/ void io_filtering (float *buf1,float *buf2,int chans,int n, double *a,double *b,double *y,double *z,double *d,double *z1,double *ampl,dataptr dz) { double input, sum, xx; int chno, this_samp, fno, i; for(chno = 0; chno < chans; chno++) { this_samp = n + chno; input = (double)buf1[this_samp]; sum = 0.0; for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) { i = (fno * chans) + chno; xx = input + (a[fno] * y[i]) + (b[fno] * z[i]); z[i] = y[i]; y[i] = xx; if(dz->vflag[FLT_DBLFILT]) { xx += (a[fno] * d[i]) + (b[fno] * z1[i]); z1[i] = d[i]; d[i] = xx; } sum += (xx * ampl[fno]); } sum *= dz->param[FLT_GAIN]; sum = check_float_limits(sum,dz); buf2[this_samp] = (float) sum; } } /************************ CHECK_FLOAT_LIMITS **************************/ //TODO: if shorts o/p - do clipping; if floatsams, report but don't change! double check_float_limits(double sum,dataptr dz) { double peak = fabs(sum); #ifdef NOTDEF //do this when 'modify loudness' can handle floatsams! if(dz->true_outfile_stype== SAMP_FLOAT){ if(peak > 1.0){ dz->iparam[FLT_OVFLW]++; dz->peak_fval = max(dz->peak_fval,peak); } } else { #endif if (sum > 1.0) { //TW SUGGEST KEEP THIS; prevents FILTER BLOWING UP: see notes dz->param[FLT_GAIN] *= 0.9999; dz->iparam[FLT_OVFLW]++; dz->peak_fval = max(dz->peak_fval,peak); //return(1.0); if(dz->clip_floatsams) sum = 1.0; } if (sum < -1.0) { //TW SUGGEST KEEP THIS; prevents FILTER BLOWING UP: see notes dz->param[FLT_GAIN] *= 0.9999; dz->iparam[FLT_OVFLW]++; dz->peak_fval = max(dz->peak_fval,peak); //return(-1.0); if(dz->clip_floatsams) sum = -1.0; } #ifdef NOTDEF } #endif return sum; } /************************ PRINT_FILTER_FRQS *******************************/ void print_filter_frqs(dataptr dz) { int n; double *frq = dz->parray[FLT_FRQ]; for(n=0;niparam[FLT_CNT];n++) fprintf(dz->fp,"%lf\n",frq[n]); } /******************************* DO_VARIFILTER ******************************/ int do_varifilter(dataptr dz) { double *dls = dz->parray[FLT_DLS]; double *dbs = dz->parray[FLT_DBS]; double *dhs = dz->parray[FLT_DHS]; double *dns = dz->parray[FLT_DNS]; double *dops[2]; double coeff = 0.0; float *buf = dz->sampbuf[0]; int n; int k, chans = dz->infile->channels; int is_fbrk = FALSE, is_qbrk = FALSE; if(dz->brksize[FLT_ONEFRQ]) is_fbrk = TRUE; if(dz->brksize[FLT_Q]) is_qbrk = TRUE; for(n=0;nmode){ case(FSW_HIGH): dops[n] = &(dz->parray[FLT_DHS][n]); break; case(FSW_LOW): dops[n] = &(dz->parray[FLT_DLS][n]); break; case(FSW_BAND): dops[n] = &(dz->parray[FLT_DBS][n]); break; case(FSW_NOTCH): dops[n] = &(dz->parray[FLT_DNS][n]); break; } } for (n = 0 ; n < dz->ssampsread; n += chans) { if(is_fbrk && (--dz->iparam[FLT_FSAMS] <= 0)) { if(!newvalue(FLT_ONEFRQ,FLT_F_INCR,FLT_FSAMS,dz)) { sprintf(errstr,"Ran out of sweepfrq values: do_varifilter()\n"); return(PROGRAM_ERROR); } } if(is_qbrk && (--dz->iparam[FLT_SAMS] <= 0)) { if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) { sprintf(errstr,"Ran out of Q values: do_sweep_filter()\n"); return(PROGRAM_ERROR); } } if(--dz->iparam[FLT_BLOKCNT] <= 0){ coeff = (2.0 * PI * dz->param[FLT_ONEFRQ]) * dz->param[FLT_INV_SR]; if(is_fbrk) dz->param[FLT_ONEFRQ] *= dz->param[FLT_F_INCR]; if(is_qbrk) { dz->param[FLT_QFAC] = 1.0/(1.0 + dz->param[FLT_Q]); dz->param[FLT_Q] *= dz->param[FLT_Q_INCR]; } dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE]; } for(k=0;kparam[FLT_Q],coeff,buf[n+k],dz); } return(CONTINUE); } /******************************* DO_SWEEP_FILTER ******************************/ int do_sweep_filter(dataptr dz) { double *dls = dz->parray[FLT_DLS]; double *dbs = dz->parray[FLT_DBS]; double *dhs = dz->parray[FLT_DHS]; double *dns = dz->parray[FLT_DNS]; double *dops[2]; double coeff = 0.0, frq; float *buf = dz->sampbuf[0]; int n; int k, chans = dz->infile->channels; int is_lbrk = FALSE, is_hbrk = FALSE, is_sbrk = FALSE, is_qbrk = FALSE; if(dz->brksize[FLT_LOFRQ]) is_lbrk = TRUE; if(dz->brksize[FLT_HIFRQ]) is_hbrk = TRUE; if(dz->brksize[FLT_SWPFRQ]) is_sbrk = TRUE; if(dz->brksize[FLT_Q]) is_qbrk = TRUE; for(n=0;nmode){ case(FSW_HIGH): dops[n] = &(dz->parray[FLT_DHS][n]); break; case(FSW_LOW): dops[n] = &(dz->parray[FLT_DLS][n]); break; case(FSW_BAND): dops[n] = &(dz->parray[FLT_DBS][n]); break; case(FSW_NOTCH): dops[n] = &(dz->parray[FLT_DNS][n]); break; } } for (n = 0 ; n < dz->ssampsread; n += chans) { if(is_lbrk && (--dz->iparam[FLT_LOSAMS] <= 0)) { if(!newvalue(FLT_LOFRQ,FLT_LOINCR,FLT_LOSAMS,dz)) { sprintf(errstr,"Ran out of lofrq values: do_sweep_filter()\n"); return(PROGRAM_ERROR); } } if(is_hbrk && (--dz->iparam[FLT_HISAMS] <= 0)) { if(!newvalue(FLT_HIFRQ,FLT_HIINCR,FLT_HISAMS,dz)) { sprintf(errstr,"Ran out of hifrq values: do_sweep_filter()\n"); return(PROGRAM_ERROR); } } if(is_sbrk && (--dz->iparam[FLT_SWSAMS] <= 0)) { if(!newvalue(FLT_SWPFRQ,FLT_SWINCR,FLT_SWSAMS,dz)) { sprintf(errstr,"Ran out of sweepfrq values: do_sweep_filter()\n"); return(PROGRAM_ERROR); } } if(is_qbrk && (--dz->iparam[FLT_SAMS] <= 0)) { if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) { sprintf(errstr,"Ran out of Q values: do_sweep_filter()\n"); return(PROGRAM_ERROR); } } if(--dz->iparam[FLT_BLOKCNT] <= 0){ frq = getfrq(dz->param[FLT_LOFRQ],dz->param[FLT_HIFRQ],dz->param[FLT_SWPFRQ],dz); coeff = (2.0 * PI * frq) * dz->param[FLT_INV_SR]; if(is_lbrk) dz->param[FLT_LOFRQ] *= dz->param[FLT_LOINCR]; if(is_hbrk) dz->param[FLT_HIFRQ] *= dz->param[FLT_HIINCR]; if(is_sbrk) dz->param[FLT_SWPFRQ] *= dz->param[FLT_SWINCR]; if(is_qbrk) { dz->param[FLT_QFAC] = 1.0/(1.0 + dz->param[FLT_Q]); dz->param[FLT_Q] *= dz->param[FLT_Q_INCR]; } dz->iparam[FLT_BLOKCNT] = dz->iparam[FLT_BLOKSIZE]; } for(k=0;kparam[FLT_Q],coeff,buf[n+k],dz); } return(CONTINUE); } /*************************** GETFRQ **************************** * * NB sfrq is already adjusted to advance over a whole flt_blok. */ double getfrq(double lfrq,double hfrq,double sfrq,dataptr dz) { double thispos; double range = hfrq - lfrq; thispos = (cos(dz->param[FLT_CYCPOS]) + 1.0) * 0.5; dz->param[FLT_CYCPOS] = fmod(dz->param[FLT_CYCPOS] + sfrq,TWOPI); return((thispos * range) + lfrq); } /******************************* DO_ALLPASS_FILTER ******************************/ int do_allpass_filter(dataptr dz) { int exit_status; int chans = dz->infile->channels; float *buf = dz->sampbuf[0]; double prescale = dz->param[FLT_PRESCALE]; if(dz->brksize[FLT_DELAY]) exit_status = varidelay_allpass(buf,chans,prescale,dz); else exit_status = allpass(buf,chans,prescale,dz); return(exit_status); } /******************************* VARIDELAY_ALLPASS ******************************/ int varidelay_allpass(float *buf,int chans,double prescale,dataptr dz) { int n, thisdelbfpos1, thisdelbfpos2, sampno; int delay, channo; double frac, ip, op, delval1,delval2, delval; double *delbuf1 = dz->parray[FLT_DELBUF1]; double *delbuf2 = dz->parray[FLT_DELBUF2]; int maxdelsamps = dz->iparam[FLT_MAXDELSAMPS] * chans; int delbufpos = dz->iparam[FLT_DELBUFPOS]; switch(dz->mode) { case(FLT_PHASESHIFT): for(n=0;nssampsread;n+= chans){ if(--dz->iparam[FLT_SAMS] <= 0) { if(!newvalue(FLT_DELAY,FLT_D_INCR,FLT_SAMS,dz)) { sprintf(errstr,"Ran out of Delay vals: varidelay_allpass()\n"); return(PROGRAM_ERROR); } } delay = (int)dz->param[FLT_DELAY]; frac = dz->param[FLT_DELAY] - (double)delay; for(channo = 0;channo < chans; channo++) { sampno = n + channo; thisdelbfpos1 = my_modulus((delbufpos - (delay*chans)),maxdelsamps); thisdelbfpos2 = my_modulus((thisdelbfpos1 + chans) ,maxdelsamps); ip = (double)buf[sampno] * prescale; op = (-dz->param[FLT_GAIN]) * ip; delval1 = delbuf1[thisdelbfpos1]; delval2 = delbuf1[thisdelbfpos2]; delval = delval1 + ((delval2 - delval1) * frac); op += delval; delval1 = delbuf2[thisdelbfpos1]; delval2 = delbuf2[thisdelbfpos2]; delval = delval1 + ((delval2 - delval1) * frac); op += dz->param[FLT_GAIN] * delval; delbuf1[delbufpos] = ip; delbuf2[delbufpos] = op; if(++delbufpos >= maxdelsamps) // delbufpos = 0; delbufpos -= maxdelsamps; /*RWD 9:2001 */ //TW ?????? maxdelsamps is a mutiple of channels, delbufpos is incremented by 1 each time // so (delbufpos -= maxdelsamps) = 0 buf[sampno] = (float) (op); } if(dz->vflag[FLT_LINDELAY]) dz->param[FLT_DELAY] += dz->param[FLT_D_INCR]; else dz->param[FLT_DELAY] *= dz->param[FLT_D_INCR]; } break; case(FLT_PHASER): for(n=0;nssampsread;n+= chans){ if(--dz->iparam[FLT_SAMS] <= 0) { if(!newvalue(FLT_DELAY,FLT_D_INCR,FLT_SAMS,dz)) { sprintf(errstr,"Ran out of Delay vals: varidelay_allpass()\n"); return(PROGRAM_ERROR); } } delay = (int)dz->param[FLT_DELAY]; frac = dz->param[FLT_DELAY] - (double)delay; for(channo = 0;channo < chans; channo++) { sampno = n + channo; thisdelbfpos1 = my_modulus((delbufpos - (delay*chans)),maxdelsamps); thisdelbfpos2 = my_modulus((thisdelbfpos1 + chans) ,maxdelsamps); ip = (double)buf[sampno] * prescale; op = (-dz->param[FLT_GAIN]) * ip; delval1 = delbuf1[thisdelbfpos1]; delval2 = delbuf1[thisdelbfpos2]; delval = delval1 + ((delval2 - delval1) * frac); op += delval; delval1 = delbuf2[thisdelbfpos1]; delval2 = delbuf2[thisdelbfpos2]; delval = delval1 + ((delval2 - delval1) * frac); op += dz->param[FLT_GAIN] * delval; delbuf1[delbufpos] = ip; delbuf2[delbufpos] = op; if(++delbufpos >= maxdelsamps) //delbufpos = 0; delbufpos -= maxdelsamps; /*RWD 9:2001 (see e_tmp/cdpfloat ) */ //TW ?????? maxdelsamps is a mutiple of channels, delbufpos is incremented by 1 each time // so (delbufpos -= maxdelsamps) = 0 buf[sampno] = (float) ((op + (double)buf[sampno]) * 0.5); } if(dz->vflag[FLT_LINDELAY]) dz->param[FLT_DELAY] += dz->param[FLT_D_INCR]; else dz->param[FLT_DELAY] *= dz->param[FLT_D_INCR]; } break; default: sprintf(errstr,"Unknown case:varidelay_allpass()\n"); return(PROGRAM_ERROR); } dz->iparam[FLT_DELBUFPOS] = delbufpos; return(FINISHED); } /******************************* ALLPASS ******************************/ int allpass(float *buf,int chans,double prescale,dataptr dz) { int n, sampno; int channo; double *delbuf1 = dz->parray[FLT_DELBUF1]; double *delbuf2 = dz->parray[FLT_DELBUF2]; int maxdelsamps = dz->iparam[FLT_MAXDELSAMPS] * chans; int delbufpos = dz->iparam[FLT_DELBUFPOS]; double ip, op; switch(dz->mode) { case(FLT_PHASESHIFT): for(n=0;nssampsread;n+=chans){ for(channo = 0;channo < chans; channo++) { sampno = n + channo; ip = (double)buf[sampno] * prescale; op = (-dz->param[FLT_GAIN]) * ip; op += delbuf1[delbufpos]; op += dz->param[FLT_GAIN] * delbuf2[delbufpos]; delbuf1[delbufpos] = ip; delbuf2[delbufpos] = op; if(++delbufpos >= maxdelsamps) /*delbufpos = 0;*/ delbufpos -= maxdelsamps; /*RWD */ //TW ?????? maxdelsamps is a mutiple of channels, delbufpos is incremented by 1 each time // so (delbufpos -= maxdelsamps) = 0 buf[sampno] = (float)(op); } } break; case(FLT_PHASER): for(n=0;nssampsread;n+=chans){ for(channo = 0;channo < chans; channo++) { sampno = n + channo; ip = (double)buf[sampno] * prescale; op = (-dz->param[FLT_GAIN]) * ip; op += delbuf1[delbufpos]; op += dz->param[FLT_GAIN] * delbuf2[delbufpos]; delbuf1[delbufpos] = ip; delbuf2[delbufpos] = op; if(++delbufpos >= maxdelsamps) /*delbufpos = 0;*/ delbufpos -= maxdelsamps; /*RWD */ //TW ?????? maxdelsamps is a mutiple of channels, delbufpos is incremented by 1 each time // so (delbufpos -= maxdelsamps) = 0 buf[sampno] = (float)((op + (double)buf[sampno]) * 0.5); } } break; default: sprintf(errstr,"Unknown case: allpass()\n"); return(PROGRAM_ERROR); } dz->iparam[FLT_DELBUFPOS] = delbufpos; return(FINISHED); } /******************************* DO_EQ_FILTER ******************************/ int do_eq_filter(dataptr dz) { double ip, op; int n, sampno; float *buf = dz->sampbuf[0]; int chans = dz->infile->channels, chno; double *xx1 = dz->parray[FLT_XX1]; double *xx2 = dz->parray[FLT_XX2]; double *yy1 = dz->parray[FLT_YY1]; double *yy2 = dz->parray[FLT_YY2]; double a0 = dz->param[FLT_A0]; double a1 = dz->param[FLT_A1]; double a2 = dz->param[FLT_A2]; double b1 = dz->param[FLT_B1]; double b2 = dz->param[FLT_B2]; double prescale = dz->param[FLT_PRESCALE]; //double inv_of_maxsamp = 1.0/(double)F_MAXSAMP; for(n = 0;n < dz->ssampsread; n+= chans){ for(chno = 0;chno < chans; chno++) { sampno = n+chno; ip = (double)buf[sampno] /* * inv_of_maxsamp*/; ip *= prescale; op = (a0 * ip) + (a1 * xx1[chno]) + (a2 * xx2[chno]) - (b1 * yy1[chno]) - (b2 * yy2[chno]); xx2[chno] = xx1[chno]; xx1[chno] = ip; yy2[chno] = yy1[chno]; yy1[chno] = op; buf[sampno] = (float)(op); } } return(FINISHED); } /************************** MULTIFILTER **************************/ float multifilter(double *dll,double *dbb,double *dnn,double *dhh,double *dpp, double qfac,double coeff,float input,dataptr dz) { double dya, dsa; dya = (double)input; *dhh = (qfac * *dbb) - *dll - dya; *dbb = *dbb - (coeff * *dhh); *dll = *dll - (coeff * *dbb); *dnn = *dll + *dhh; dsa = (*dpp) * dz->param[FLT_GAIN]; /* dpp points to dhh,dbb,dll,dnn */ #ifdef NOTDEF if (fabs(dsa) > F_MAXSAMP) { dz->iparam[FLT_OVFLW]++; dz->param[FLT_GAIN] *= .9999; if (dsa > 0.0) dsa = (double)F_MAXSAMP; else dsa = (double)F_MINSAMP; } return((float)dsa); /* TRUNCATE */ #else return (float) check_float_limits(dsa,dz); #endif } /***************************** FILTER *************************************/ /* RWD TODO: add fix for nchans */ //int do_lphp_filter(dataptr dz) //{ // double *e1s,*e2s,*s1s,*s2s; // double *e1 = dz->parray[FLT_E1]; // double *e2 = dz->parray[FLT_E2]; // double *s1 = dz->parray[FLT_S1]; // double *s2 = dz->parray[FLT_S2]; // double *den1 = dz->parray[FLT_DEN1]; // double *den2 = dz->parray[FLT_DEN2]; // double *cn = dz->parray[FLT_CN]; // switch(dz->infile->channels) { // case(STEREO): // e1s = dz->parray[FLT_E1S]; // e2s = dz->parray[FLT_E2S]; // s1s = dz->parray[FLT_S1S]; // s2s = dz->parray[FLT_S2S]; // lphp_filt_stereo(e1,e2,s1,s2,e1s,e2s,s1s,s2s,den1,den2,cn,dz); // break; // case(MONO): // lphp_filt(e1,e2,s1,s2,den1,den2,cn,dz); // break; // } // return(FINISHED); //} // // TW MULTICHAN 2010 int do_lphp_filter(dataptr dz) { int i; int index; double *e1,*e2,*s1,*s2; double *den1 = dz->parray[FLT_DEN1]; double *den2 = dz->parray[FLT_DEN2]; double *cn = dz->parray[FLT_CN]; for(i=0; i < dz->infile->channels; i++) { index = i * FLT_LPHP_ARRAYS_PER_FILTER; e1 = dz->parray[FLT_E1_BASE + index]; e2 = dz->parray[FLT_E2_BASE + index]; s1 = dz->parray[FLT_S1_BASE + index]; s2 = dz->parray[FLT_S2_BASE + index]; lphp_filt_chan(e1,e2,s1,s2,den1,den2,cn,dz,i); } return(FINISHED); } /***************************** LPHP_FILT *************************************/ void lphp_filt(double *e1,double *e2,double *s1,double *s2, double *den1,double *den2,double *cn,dataptr dz) { int i; int k; float *buf = dz->sampbuf[0]; double ip, op = 0.0, b1; for (i = 0 ; i < dz->ssampsread; i++) { ip = (double) buf[i]; for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) { b1 = dz->param[FLT_MUL] * cn[k]; op = (cn[k] * ip) + (den1[k] * s1[k]) + (den2[k] * s2[k]) + (b1 * e1[k]) + (cn[k] * e2[k]); s2[k] = s1[k]; s1[k] = op; e2[k] = e1[k]; e1[k] = ip; } op *= dz->param[FLT_PRESCALE]; //RWD NB gain modification... #ifdef NOTDEF if (fabs(op) > 1.0) { dz->iparam[FLT_OVFLW]++; //TW SUGGEST KEEP THIS: PREVENTS FILTER BLOWING UP dz->param[FLT_PRESCALE] *= .9999; if (op > 0.0) op = 1.0; else op = -1.0; } buf[i] = (float)op; #else buf[i] = (float) check_float_limits(op,dz); #endif } } /*RWD 4:2000 */ void lphp_filt_chan(double *e1,double *e2,double *s1,double *s2, double *den1,double *den2,double *cn,dataptr dz,int chan) { int i; int k; float *buf = dz->sampbuf[0]; double ip, op = 0.0, b1; for (i = chan ; i < dz->ssampsread; i+= dz->infile->channels) { ip = (double) buf[i]; for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) { b1 = dz->param[FLT_MUL] * cn[k]; op = (cn[k] * ip) + (den1[k] * s1[k]) + (den2[k] * s2[k]) + (b1 * e1[k]) + (cn[k] * e2[k]); s2[k] = s1[k]; s1[k] = op; e2[k] = e1[k]; e1[k] = ip; } op *= dz->param[FLT_PRESCALE]; //RWD NB gain modification... #ifdef NOTDEF if (fabs(op) > 1.0) { dz->iparam[FLT_OVFLW]++; //TW SUGGEST KEEP THIS: PREVENTS FILTER BLOWING UP dz->param[FLT_PRESCALE] *= .9999; if (op > 0.0) op = 1.0; else op = -1.0; } buf[i] = (float)op; #else buf[i] = (float) check_float_limits(op,dz); #endif } } /***************************** LPHP_FILT_STEREO *************************************/ void lphp_filt_stereo(double *e1,double *e2,double *s1,double *s2,double *e1s,double *e2s,double *s1s,double *s2s, double *den1,double *den2,double *cn,dataptr dz) { int i, j; int k; float *buf = dz->sampbuf[0]; double ip, op = 0.0, b1; for (i = 0 ; i < dz->ssampsread; i+=2) { ip = (double)buf[i]; for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) { b1 = dz->param[FLT_MUL] * cn[k]; op = (cn[k] * ip) + (den1[k] * s1[k]) + (den2[k] * s2[k]) + (b1 * e1[k]) + (cn[k] * e2[k]); s2[k] = s1[k]; s1[k] = op; e2[k] = e1[k]; e1[k] = ip; } op *= dz->param[FLT_PRESCALE]; #ifdef NOTDEF if (fabs(op) > F_MAXSAMP) { dz->iparam[FLT_OVFLW]++; dz->param[FLT_PRESCALE] *= .9999; if (op > 0.0) op = (double)F_MAXSAMP; else op = (double)F_MINSAMP; } buf[i] = (float)op; #else buf[i] = (float) check_float_limits(op,dz); #endif j = i+1; ip = (double)buf[j]; for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) { b1 = dz->param[FLT_MUL] * cn[k]; op = (den1[k] * s1s[k]) + (den2[k] * s2s[k]) + (cn[k] * ip) + (b1 * e1s[k]) + (cn[k] * e2s[k]); s2s[k] = s1s[k]; s1s[k] = op; e2s[k] = e1s[k]; e1s[k] = ip; } op *= dz->param[FLT_PRESCALE]; #ifdef NOTDEF if (fabs(op) > F_MAXSAMP) { dz->iparam[FLT_OVFLW]++; dz->param[FLT_PRESCALE] *= .9999; if (op > 0.0) op = (double)F_MAXSAMP; else op = (double)F_MINSAMP; } buf[j] = (float)op; #else buf[j] = (float) check_float_limits(op,dz); #endif } } /***************************** MY_MODULUS *************************************/ int my_modulus(int x,int y) { if(x>=0) return(x%y); while(x < 0) x += y; return(x); } /**************************** NEWFVAL2 *******************************/ int newfval2(double *fbrk,double *hbrk,dataptr dz) { int n, m, k, timepoint, nextrow; int entrycnt = dz->iparam[FLT_ENTRYCNT]; int wordcnt = dz->iparam[FLT_WORDCNT]; int hentrycnt = dz->iparam[HRM_ENTRYCNT]; int hwordcnt = dz->iparam[HRM_WORDCNT]; //long srate = dz->infile->srate; double lotime, hitime, timefrac, valdiff; double thistime = dz->param[FLT_TOTALTIME]; memset((char *)dz->parray[FLT_INFRQ],0,dz->iparam[FLT_CNT] * sizeof(double)); memset((char *)dz->parray[FLT_INAMP],0,dz->iparam[FLT_CNT] * sizeof(double)); timepoint = 0; while(thistime >= fbrk[timepoint]) { /* search times in frq array */ timepoint += entrycnt; if(timepoint >= wordcnt) break; } timepoint -= entrycnt; lotime = fbrk[timepoint]; nextrow = timepoint + entrycnt; for(n = timepoint+1,k = 0; n < nextrow;n+=2,k += dz->iparam[FLT_HARMCNT]) { dz->parray[FLT_INFRQ][k] = fbrk[n]; /* Get frqs of fundamentals into array, leaving space for harmonics */ dz->parray[FLT_INAMP][k] = fbrk[n+1]; /* Get amps of fundamentals into array, leaving space for harmonics */ } if(nextrow != wordcnt) { /* if not at end of table, do interpolation */ nextrow += entrycnt; timepoint += entrycnt; hitime = fbrk[timepoint]; timefrac = (thistime - lotime)/(hitime - lotime); k = 0; for(n = timepoint+1,k=0; n < nextrow;n+=2,k += dz->iparam[FLT_HARMCNT]) { /* FRQ */ valdiff = fbrk[n] - dz->parray[FLT_INFRQ][k]; valdiff *= timefrac; dz->parray[FLT_INFRQ][k] = dz->parray[FLT_INFRQ][k] + valdiff; /* AMP */ valdiff = fbrk[n+1] - dz->parray[FLT_INAMP][k]; valdiff *= timefrac; dz->parray[FLT_INAMP][k] = dz->parray[FLT_INAMP][k] + valdiff; } } timepoint = 0; while(thistime >= hbrk[timepoint]) { /* search times in frq array */ timepoint += hentrycnt; if(timepoint >= hwordcnt) { break; } } timepoint -= hentrycnt; lotime = hbrk[timepoint]; nextrow = timepoint + hentrycnt; k = 0; for(n = timepoint+1,k=0; n < nextrow;n+=2,k++) { dz->parray[HARM_FRQ_CALC][k] = hbrk[n]; dz->parray[HARM_AMP_CALC][k] = hbrk[n+1]; } if(nextrow != hwordcnt) { /* if not at end of table, do interpolation */ nextrow += hentrycnt; timepoint += hentrycnt; hitime = hbrk[timepoint]; timefrac = (thistime - lotime)/(hitime - lotime); k = 0; for(n = timepoint+1,k=0; n < nextrow;n+=2,k++) { /* PARTIAL MULTIPLIER */ valdiff = hbrk[n] - dz->parray[HARM_FRQ_CALC][k]; valdiff *= timefrac; dz->parray[HARM_FRQ_CALC][k] = dz->parray[HARM_FRQ_CALC][k] + valdiff; /* PARTIAL AMP */ valdiff = hbrk[n+1] - dz->parray[HARM_AMP_CALC][k]; valdiff *= timefrac; dz->parray[HARM_AMP_CALC][k] = dz->parray[HARM_AMP_CALC][k] + valdiff; } } for(k=0;kiparam[FLT_CNT];k+=dz->iparam[FLT_HARMCNT]) { for(m=0; m < dz->iparam[FLT_HARMCNT];m++) { /* calc vals for partials from basefrq vals */ dz->parray[FLT_INFRQ][k+m] = dz->parray[FLT_INFRQ][k] * dz->parray[HARM_FRQ_CALC][m]; dz->parray[FLT_INAMP][k+m] = dz->parray[FLT_INAMP][k] * dz->parray[HARM_AMP_CALC][m]; dz->parray[FLT_FRQ][k+m] = dz->parray[FLT_INFRQ][k+m]; dz->parray[FLT_AMP][k+m] = dz->parray[FLT_INAMP][k+m]; } } dz->param[FLT_TOTALTIME] += dz->param[FLT_TIMESTEP]; return(FINISHED); } /*************************** DO_FVARY2_FILTERS *****************************/ int do_fvary2_filters(dataptr dz) { int exit_status; int n, fno, chans = dz->infile->channels; float *buf = dz->sampbuf[0]; //double *fincr = dz->parray[FLT_FINCR]; //double *aincr = dz->parray[FLT_AINCR]; double *ampl = dz->parray[FLT_AMPL]; double *a = dz->parray[FLT_A]; double *b = dz->parray[FLT_B]; double *y = dz->parray[FLT_Y]; double *z = dz->parray[FLT_Z]; double *d = dz->parray[FLT_D]; double *e = dz->parray[FLT_E]; int fsams = dz->iparam[FLT_FSAMS]; for (n = 0; n < dz->ssampsread; n += chans) { if(dz->brksize[FLT_Q]) { if((dz->iparam[FLT_SAMS] -= chans) <= 0) { if(!newvalue(FLT_Q,FLT_Q_INCR,FLT_SAMS,dz)) { sprintf(errstr,"Ran out of Q values: do_fvary2_filters()\n"); return(PROGRAM_ERROR); } dz->iparam[FLT_SAMS] *= chans; } } if(fsams <= 0) { if((exit_status = newfval2(dz->parray[FLT_FBRK],dz->parray[FLT_HBRK],dz))<0) return(exit_status); fsams = dz->iparam[FLT_FSAMS]; for (fno = 0; fno < dz->iparam[FLT_CNT]; fno++) { get_coeffs1(fno,dz); get_coeffs2(fno,dz); } if(dz->brksize[FLT_Q]) dz->param[FLT_Q] *= dz->param[FLT_Q_INCR]; } filtering(n,chans,buf,a,b,y,z,d,e,ampl,dz); fsams--; } return(CONTINUE); }