?? iir-lib.c
字號:
}/* ....................... End of cascade_iir_init() ....................... *//* ============================================================================ void cascade_free (CASCADE_IIR *iir_ptr); ~~~~~~~~~~~~~~~~~ Description: ~~~~~~~~~~~~ Deallocate memory, which was allocated by an earlier call to one of the initilization routines. `CASCADE_IIR *iir_prt' must not be NULL. Parameters: ~~~~~~~~~~~ CASCADE_IIR *iir_ptr: ... pointer to struct CASCADE_IIR previously initialized by a call to one of the initialization routines. Return value: ~~~~~~~~~~~~~ Nothing. Author: <simao@ctd.comsat.com> ~~~~~~~ History: ~~~~~~~~ 30.Oct.94 v1.0 Release of 1st version <simao@ctd.comsat.com> ============================================================================*/void cascade_iir_free(iir_ptr) CASCADE_IIR *iir_ptr;{ free(iir_ptr->T); /* free state variables */ free(iir_ptr); /* free allocated struct */}/* ....................... End of cascade_iir_free() ....................... *//* *********************************************************************** *//* ============================================================================ void direct_reset (DIRECT_IIR *iir_ptr); ~~~~~~~~~~~~~~~~~ Description: ~~~~~~~~~~~~ Clear state variables in DIRECT_IIR structure, what has been initialized by a previous call to one of the init functions. Parameters: ~~~~~~~~~~~ DIRECT_IIR *iir_ptr: ... pointer to struct DIRECT_IIR previously initialized by a call to one of the initialization routines. Return value: ~~~~~~~~~~~~~ Nothing. Author: <simao@ctd.comsat.com> ~~~~~~~ History: ~~~~~~~~ 31.Jul.95 v1.0 Release of 1st version <simao@ctd.comsat.com> ============================================================================*/void direct_reset(iir_ptr) DIRECT_IIR *iir_ptr;{ long n; register float (*T_ptr)[2]; long nblocks = (iir_ptr->poleno > iir_ptr->zerono) ? iir_ptr->poleno : iir_ptr->zerono; T_ptr = iir_ptr->T; for (n = 0; n < nblocks; n++) { T_ptr[n][0] = 0.0; T_ptr[n][1] = 0.0; } iir_ptr->k0 = iir_ptr->idown; /* modulo counter for down-sampling */}/* ....................... End of direct_reset() ....................... *//* ============================================================================ long direct_iir_kernel (long lseg, float *x_ptr, DIRECT_IIR *iir_ptr, ~~~~~~~~~~~~~~~~~~~~~~~ float *y_ptr); Description: ~~~~~~~~~~~~ Basic direct-form IIR filtering routine, for both up- and down-sampling. Parameters: ~~~~~~~~~~~ lseg: ...... number of input samples x_ptr: ..... array with input samples iir_ptr: ... pointer to IIR-struct (DIRECT_IIR *) y_ptr: ..... output samples Return value: ~~~~~~~~~~~~~ Returns the number of output samples. Author: <simao@ctd.comsat.com> ~~~~~~~ History: ~~~~~~~~ 31.Jul.95 v1.0 Release of 1st version <simao@ctd.comsat.com> ============================================================================*/long direct_iir_kernel(lseg, x_ptr, iir_ptr, y_ptr) long lseg; float *x_ptr; DIRECT_IIR *iir_ptr; float *y_ptr;{ if (iir_ptr->hswitch == 'U') return direct_form_iir_up_kernel( /* returns number of output samples */ lseg, /* In : input signal leng. */ x_ptr, /* In : input sample array */ y_ptr, /* Out: outp. sample array */ iir_ptr->idown, /* In : dwnsmpl.factor */ iir_ptr->zerono, /*In: no.IIR-zeroes */ iir_ptr->poleno, /*In: no.IIR-poles */ iir_ptr->gain, /* In : gain factor*/ iir_ptr->a, /* In : num.coeffs */ iir_ptr->b, /* In : denom.coeffs */ iir_ptr->T /* I/O: state vars */ ); else return direct_form_iir_down_kernel(/* returns number of output samples */ lseg, /* In : input signal leng. */ x_ptr, /* In : input sample array */ y_ptr, /* Out: outp. sample array */ &(iir_ptr->k0), /*I/O: start idx,x-array */ iir_ptr->idown, /*In : dwnsmpl.factor */ iir_ptr->zerono, /*In: no.IIR-zeroes */ iir_ptr->poleno, /*In: no.IIR-poles */ iir_ptr->gain, /* In : gain factor */ iir_ptr->a, /* In : numerator coeffs */ iir_ptr->b, /* In : denom.coeffs */ iir_ptr->T /* I/O: state vars */ );}/* .................... End of direct_iir_kernel() ....................... *//* ============================================================================ long direct_form_iir_down_kernel(long lenx, float *x, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ float *y, long *k0, long idown, long zerono, long poleno, double gain, float *a, float *b, float (*T)[2]); Description: ~~~~~~~~~~~~ Function for filtering a sequence of input samples by a direct-form IIR-filter with down-sampling. Parameters: ~~~~~~~~~~~ lenx: ........ (In) length of input array x[] x: ........... (In) array with input samples y: ........... (Out) array with output samples k0: .......... (In/Out) pointer to modulo counter idown: ....... (In) down-sampling factor zerono: ...... (In) number of zeroes poleno: ...... (In) number of poles gain: ........ (In) gain factor b: ........... (In) numerator coefficients c: ........... (In) denominator coefficients T: ........... (In/Out) past sample memory: T[][0] store past numerator (x) samples and T[][1] stores past denominator (y) samples. T[0][0],T[0][1] are the most recent samples, T[zerono-1][0],T[poleno-1][1] are the oldest. Return value: ~~~~~~~~~~~~~ Returns the number of samples filtered. Author: <simao@ctd.comsat.com> ~~~~~~~ History: ~~~~~~~~ 31.Jul.95 v1.0 Release of 1st version <simao@ctd.comsat.com> ============================================================================*/static long direct_form_iir_down_kernel(lenx, x, y, k0, idown, zerono, poleno, gain, a, b, T) long lenx; float *x, *y; long *k0, idown, zerono, poleno; double gain; float *a, *b, (*T)[2];{ long kx, ky, n; double yj; ky = 0; /* starting index in output array (y) */ for (kx = 0; kx < lenx; kx++) /* loop over all input samples */ { T[0][0] = x[kx]; /* Filter samples through numerator (zero) part */ for (yj=0, n = 0; n < zerono; n++) yj += a[n] * T[n][0]; /* Filter samples through denominator (pole) part */ for (n = 1; n < poleno; n++) yj -= b[n] * T[n-1][1]; /* Shift samples in memory (to the right) for next step */ for (n = zerono-1; n >0; n--) T[n][0] = T[n-1][0]; for (n = poleno-1; n >0; n--) T[n][1] = T[n-1][1]; T[0][1] = yj; /* Save to output only every "idown" samples */ if (*k0 % idown == 0) { /* Apply gain and update y-samples' counter */ y[ky] = yj * gain; ky++; } (*k0)++; } *k0 %= idown; /* avoid overflow by (*k0)++ */ return ky;}/* .............. End of direct_form_iir_down_kernel() .............. *//* ============================================================================ long direct_form_iir_up_kernel(long lenx, float *x, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ float *y, long *k0, long idown, long zerono, long poleno, double gain, float *a, float *b, float (*T)[2]); Description: ~~~~~~~~~~~~ Function for filtering a sequence of input samples by a direct-form IIR-filter with up-sampling. Samples are taken from the input vector x only once-in-idown times; in the other times, the input sample is zero (interpolation process). Parameters: ~~~~~~~~~~~ lenx: ........ (In) length of input array x[] x: ........... (In) array with input samples y: ........... (Out) array with output samples iup: ......... (In) up-sampling factor zerono: ...... (In) number of zeroes poleno: ...... (In) number of poles gain: ........ (In) gain factor b: ........... (In) numerator coefficients c: ........... (In) denominator coefficients T: ........... (In/Out) past sample memory: T[][0] store past numerator (x) samples and T[][1] stores past denominator (y) samples. T[0][0],T[0][1] are the most recent samples, T[zerono-1][0],T[poleno-1][1] are the oldest. Return value: ~~~~~~~~~~~~~ Returns the number of samples filtered. Author: <simao@ctd.comsat.com> ~~~~~~~ History: ~~~~~~~~ 31.Jul.95 v1.0 Release of 1st version <simao@ctd.comsat.com> ============================================================================*/static long direct_form_iir_up_kernel(lenx, x, y, iup, zerono, poleno, gain, a, b, T) long lenx; float *x, *y; long iup, zerono, poleno; double gain; float *a, *b, (*T)[2];{ long kx, ky, n; register double yj; kx = 0; /* starting index in input array (x) */ for (ky = 0; ky < iup * lenx; ky++) /* loop over all input samples */ { /* Compute output only every "iup" compute output only every "iup" * samples by taking one input sample direct path OR by using a * zero-valued sample; already save on memory array */ T[0][0] = (ky % iup == 0) ? x[kx] : 0; /* Filter samples through numerator (zero) part */ for (yj=0, n = 0; n < zerono; n++) yj += a[n] * T[n][0]; /* Filter samples through denominator (pole) part */ for (n = 1; n < poleno; n++) yj -= b[n] * T[n-1][1]; /* Shift samples in memory (to the right) for next step */ for (n = zerono-1; n >0; n--) T[n][0] = T[n-1][0]; for (n = poleno-1; n >0; n--) T[n][1] = T[n-1][1]; T[0][1] = yj; /* Apply the gain and update x counter if needed */ y[ky] = yj * gain; if (ky % iup == 0) kx++; } return ky;}/* ............... End of direct_form_iir_up_kernel() ............... *//* ============================================================================ DIRECT_IIR *direct_iir_init (long nblocks, float *a, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ float *b, double gain, long idwnup, char hswitch); Description: ~~~~~~~~~~~~ Allocate & initialize struct for down/up-sampling procedures. Parameters: ~~~~~~~~~~~ long zerono: ........ number of zeroes long poleno: ........ number of poles float *a: ........... pointer to numerator coeffic. float *b: ........... pointer to denominator coeffic. double gain: ........ gain factor for filter long idown: ......... Down-sampling factor char hswitch: ....... to up-/downsampling routine Return value: ~~~~~~~~~~~~~ Returns a pointer to struct DIRECT_IIR; Author: <simao@ctd.comsat.com> ~~~~~~~ History: ~~~~~~~~ 31.Jul.95 v1.0 Release of 1st version <simao@ctd.comsat.com> ============================================================================*/DIRECT_IIR *direct_iir_init(zerono, poleno, a, b, gain, idown, hswitch) long zerono, poleno; float *a, *b; double gain; long idown; char hswitch;{ static DIRECT_IIR *ptrIIR; /* pointer to the new struct */ float fak; float (*T_ptr)[2]; long n; long nblocks; /* Get greater of zero and pole */ nblocks = zerono > poleno? zerono: poleno; /* Allocate memory for a new struct */ ptrIIR = (DIRECT_IIR *) malloc((long) sizeof(DIRECT_IIR)); if (ptrIIR == (DIRECT_IIR *) 0L) { return 0; } /* Allocate memory for state variables */ if ((ptrIIR->T = (float (*)[2]) malloc((nblocks * 2) * sizeof(fak))) == (float (*)[2]) 0) { free(ptrIIR); return 0; } /* fill coefficient sets */ ptrIIR->poleno = poleno; /* store number of poles */ ptrIIR->zerono = zerono; /* store number of zeroes */ ptrIIR->a = a; ptrIIR->b = b; /* store down-sampling factor/gain/direct-path coefficient */ ptrIIR->idown = idown; ptrIIR->gain = gain; /* Store switch to IIR-kernel procedure */ ptrIIR->hswitch = hswitch; /* Clear state variables */ T_ptr = ptrIIR->T; for (n = 0; n < nblocks; n++) { T_ptr[n][0] = 0.0; /* Numerator memory */ T_ptr[n][1] = 0.0; /* Denominator memory */ } ptrIIR->k0 = idown; /* modulo counter for down-sampling */ /* Exit returning pointer to struct */ return (ptrIIR);}/* ....................... End of direct_iir_init() ....................... *//* ============================================================================ void direct_free (DIRECT_IIR *iir_ptr); ~~~~~~~~~~~~~~~~~ Description: ~~~~~~~~~~~~ Deallocate memory, which was allocated by an earlier call to one of the initilization routines. `DIRECT_IIR *iir_prt' must not be NULL. Parameters: ~~~~~~~~~~~ DIRECT_IIR *iir_ptr: ... pointer to struct DIRECT_IIR previously initialized by a call to one of the initialization routines. Return value: ~~~~~~~~~~~~~ Nothing. Author: <simao@ctd.comsat.com> ~~~~~~~ History: ~~~~~~~~ 31.Jul.95 v1.0 Release of 1st version <simao@ctd.comsat.com> ============================================================================*/void direct_iir_free(iir_ptr) DIRECT_IIR *iir_ptr;{ free(iir_ptr->T); /* free state variables */ free(iir_ptr); /* free allocated struct */}/* ....................... End of direct_iir_free() ....................... *//* **************************** END OF IIR-LIB.C ************************ */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -