// create arbitrary resampler // _rate : resampling rate // _m : prototype filter semi-length // _fc : prototype filter cutoff frequency, fc in (0, 0.5) // _As : prototype filter stop-band attenuation [dB] (e.g. 60) // _npfb : number of filters in polyphase filterbank RESAMP() RESAMP(_create)(float _rate, unsigned int _m, float _fc, float _As, unsigned int _npfb) { // validate input if (_rate <= 0) { fprintf(stderr,"error: resamp_%s_create(), resampling rate must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr,"error: resamp_%s_create(), filter semi-length must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_fc <= 0.0f || _fc >= 0.5f) { fprintf(stderr,"error: resamp_%s_create(), filter cutoff must be in (0,0.5)\n", EXTENSION_FULL); exit(1); } else if (_As <= 0.0f) { fprintf(stderr,"error: resamp_%s_create(), filter stop-band suppression must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_npfb == 0) { fprintf(stderr,"error: resamp_%s_create(), number of filter banks must be greater than zero\n", EXTENSION_FULL); exit(1); } // allocate memory for resampler RESAMP() q = (RESAMP()) malloc(sizeof(struct RESAMP(_s))); // set rate using formal method (specifies output stride // value 'del') RESAMP(_set_rate)(q, _rate); // set properties q->m = _m; // prototype filter semi-length q->fc = _fc; // prototype filter cutoff frequency q->As = _As; // prototype filter stop-band attenuation q->npfb = _npfb; // number of filters in bank // design filter unsigned int n = 2*q->m*q->npfb+1; float hf[n]; TC h[n]; liquid_firdes_kaiser(n,q->fc/((float)(q->npfb)),q->As,0.0f,hf); // normalize filter coefficients by DC gain unsigned int i; float gain=0.0f; for (i=0; i<n; i++) gain += hf[i]; gain = (q->npfb)/(gain); // copy to type-specific array, applying gain for (i=0; i<n; i++) h[i] = hf[i]*gain; q->f = FIRPFB(_create)(q->npfb,h,n-1); // reset object and return RESAMP(_reset)(q); return q; }
// create arbitrary resampler object with a specified input // resampling rate and default parameters // m (filter semi-length) = 7 // fc (filter cutoff frequency) = 0.25 // As (filter stop-band attenuation) = 60 dB // npfb (number of filters in the bank) = 64 RESAMP() RESAMP(_create_default)(float _rate) { // validate input if (_rate <= 0) { fprintf(stderr,"error: resamp_%s_create_default(), resampling rate must be greater than zero\n", EXTENSION_FULL); exit(1); } // det default parameters unsigned int m = 7; float fc = 0.5f*_rate > 0.49f ? 0.49f : 0.5f*_rate; float As = 60.0f; unsigned int npfb = 64; // create and return resamp object return RESAMP(_create)(_rate, m, fc, As, npfb); }
#include <stdlib.h> #include <string.h> #include <math.h> // defined: // TO output data type // TC coefficient data type // TI input data type // RESAMP() name-mangling macro // FIRPFB() firpfb macro // enable run-time debug printing of resampler #define DEBUG_RESAMP_PRINT 0 // internal: update timing void RESAMP(_update_timing_state)(RESAMP() _q); struct RESAMP(_s) { // filter design parameters unsigned int m; // filter semi-length, h_len = 2*m + 1 float As; // filter stop-band attenuation float fc; // filter cutoff frequency // resampling properties/states float rate; // resampling rate (ouput/input) float del; // fractional delay step // floating-point phase float tau; // accumulated timing phase, 0 <= tau < 1 float bf; // soft filterbank index, bf = tau*npfb = b + mu int b; // base filterbank index, 0 <= b < npfb
RESAMP() RESAMP(_create)(float _r, unsigned int _h_len, float _fc, float _As, unsigned int _npfb) { // validate input if (_r <= 0) { fprintf(stderr,"error: resamp_%s_create(), resampling rate must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_h_len == 0) { fprintf(stderr,"error: resamp_%s_create(), filter length must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_npfb == 0) { fprintf(stderr,"error: resamp_%s_create(), number of filter banks must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_fc <= 0.0f || _fc >= 0.5f) { fprintf(stderr,"error: resamp_%s_create(), filter cutoff must be in (0,0.5)\n", EXTENSION_FULL); exit(1); } else if (_As <= 0.0f) { fprintf(stderr,"error: resamp_%s_create(), filter stop-band suppression must be greater than zero\n", EXTENSION_FULL); exit(1); } RESAMP() q = (RESAMP()) malloc(sizeof(struct RESAMP(_s))); q->r = _r; q->As = _As; q->fc = _fc; q->h_len = _h_len; q->b = 0; q->del = 1.0f / q->r; #if RESAMP_USE_FIXED_POINT_PHASE q->num_bits_npfb = liquid_nextpow2(_npfb); q->npfb = 1<<q->num_bits_npfb; q->num_bits_phase = 20; q->max_phase = 1 << q->num_bits_phase; q->num_shift_bits = q->num_bits_phase - q->num_bits_npfb; q->theta = 0; q->d_theta = (unsigned int)( q->max_phase * q->del ); #else q->npfb = _npfb; q->tau = 0.0f; q->bf = 0.0f; #endif // design filter unsigned int n = 2*_h_len*q->npfb+1; float hf[n]; TC h[n]; liquid_firdes_kaiser(n,q->fc/((float)(q->npfb)),q->As,0.0f,hf); // normalize filter coefficients by DC gain unsigned int i; float gain=0.0f; for (i=0; i<n; i++) gain += hf[i]; gain = (q->npfb)/(gain); // copy to type-specific array for (i=0; i<n; i++) h[i] = hf[i]*gain; q->f = FIRPFB(_create)(q->npfb,h,n-1); //for (i=0; i<n; i++) // PRINTVAL_TC(h[i],%12.8f); //exit(0); return q; }
gain += hf[i]; gain = (q->npfb)/(gain); // copy to type-specific array for (i=0; i<n; i++) h[i] = hf[i]*gain; q->f = FIRPFB(_create)(q->npfb,h,n-1); //for (i=0; i<n; i++) // PRINTVAL_TC(h[i],%12.8f); //exit(0); return q; } void RESAMP(_destroy)(RESAMP() _q) { FIRPFB(_destroy)(_q->f); free(_q); } void RESAMP(_print)(RESAMP() _q) { printf("resampler [rate: %f]\n", _q->r); FIRPFB(_print)(_q->f); } void RESAMP(_reset)(RESAMP() _q) { FIRPFB(_clear)(_q->f); _q->b = 0;
// create msresamp object // TODO: add signal bandwidth parameter? // TODO: add center frequency parameter; facilitates DDS object synthesis // _r : resampling rate [output/input] // _As : stop-band attenuation MSRESAMP() MSRESAMP(_create)(float _r, float _As) { // validate input if (_r <= 0.0f) { fprintf(stderr,"error: msresamp_%s_create(), resampling rate must be greater than zero\n", EXTENSION_FULL); exit(1); } // create object MSRESAMP() q = (MSRESAMP()) malloc(sizeof(struct MSRESAMP(_s))); // set internal properties q->rate = _r; // composite rate q->As = _As; // stop-band suppression // decimation or interpolation? q->type = (q->rate > 1.0f) ? LIQUID_RESAMP_INTERP : LIQUID_RESAMP_DECIM; // compute derived values q->rate_arbitrary = q->rate; q->rate_halfband = 1.0f; q->num_halfband_stages = 0; switch(q->type) { case LIQUID_RESAMP_INTERP: while (q->rate_arbitrary > 2.0f) { q->num_halfband_stages++; q->rate_halfband *= 2.0f; q->rate_arbitrary *= 0.5f; } break; case LIQUID_RESAMP_DECIM: while (q->rate_arbitrary < 0.5f) { q->num_halfband_stages++; q->rate_halfband *= 0.5f; q->rate_arbitrary *= 2.0f; } break; default:; } // allocate memory for buffer q->buffer_len = 4 + (1 << q->num_halfband_stages); q->buffer = (T*) malloc( q->buffer_len*sizeof(T) ); // create single multi-stage half-band resampler object // TODO: compute appropriate cut-off frequency q->halfband_resamp = MSRESAMP2(_create)(q->type, q->num_halfband_stages, 0.4f, 0.0f, q->As); // create arbitrary resampler object // TODO: compute appropriate parameters q->arbitrary_resamp = RESAMP(_create)(q->rate_arbitrary, 7, 0.4f, q->As, 64); // reset object MSRESAMP(_reset)(q); // return main object return q; }