// create multi-stage half-band resampler // _type : resampler type (e.g. LIQUID_RESAMP_DECIM) // _num_stages : number of resampling stages // _fc : filter cut-off frequency 0 < _fc < 0.5 // _f0 : filter center frequency // _As : stop-band attenuation [dB] MSRESAMP2() MSRESAMP2(_create)(int _type, unsigned int _num_stages, float _fc, float _f0, float _As) { // validate input if (_num_stages > 10) { fprintf(stderr,"error: msresamp2_%s_create(), number of stages should not exceed 10\n", EXTENSION_FULL); exit(1); } // ensure cut-off frequency is valid if ( _fc <= 0.0f || _fc >= 0.5f ) { fprintf(stderr,"error: msresamp2_%s_create(), cut-off frequency must be in (0,0.5)\n", EXTENSION_FULL); exit(1); } else if ( _fc > 0.45f ) { fprintf(stderr,"warning: msresamp2_%s_create(), cut-off frequency greater than 0.45\n", EXTENSION_FULL); fprintf(stderr," >> truncating to 0.45\n"); _fc = 0.45f; } // check center frequency if ( _f0 != 0. ) { fprintf(stderr,"warning: msresamp2_%s_create(), non-zero center frequency not yet supported\n", EXTENSION_FULL); _f0 = 0.; } unsigned int i; // create object MSRESAMP2() q = (MSRESAMP2()) malloc(sizeof(struct MSRESAMP2(_s))); // set internal properties q->type = _type == LIQUID_RESAMP_INTERP ? LIQUID_RESAMP_INTERP : LIQUID_RESAMP_DECIM; q->num_stages = _num_stages; q->fc = _fc; q->f0 = _f0; q->As = _As; // derived values q->M = 1 << q->num_stages; q->zeta = 1.0f / (float)(q->M); // allocate memory for buffers q->buffer0 = (T*) malloc( q->M * sizeof(T) ); q->buffer1 = (T*) malloc( q->M * sizeof(T) ); // allocate arrays for half-band resampler parameters q->fc_stage = (float*) malloc(q->num_stages*sizeof(float) ); q->f0_stage = (float*) malloc(q->num_stages*sizeof(float) ); q->As_stage = (float*) malloc(q->num_stages*sizeof(float) ); q->m_stage = (unsigned int*) malloc(q->num_stages*sizeof(unsigned int)); // determine half-band resampler parameters float fc = q->fc; float f0 = q->f0; for (i=0; i<q->num_stages; i++) { // compute parameters based on filter requirements; f0 = 0.5f*f0; // update center frequency fc = 0.5f*fc; // update cutoff frequency // estiamte required filter length float ft = (0.5f - fc)/2.0f; unsigned int h_len = estimate_req_filter_len(ft, q->As); unsigned int m = ceilf( (float)(h_len-1) / 4.0f ); q->fc_stage[i] = fc; // filter cut-of q->f0_stage[i] = f0; // filter center frequency q->As_stage[i] = q->As; // filter stop-band attenuation q->m_stage[i] = m < 3 ? 3 : m; // minimum 2 } // create half-band resampler objects q->resamp2 = (RESAMP2()*) malloc(q->num_stages*sizeof(RESAMP2())); for (i=0; i<q->num_stages; i++) { // create half-band resampler q->resamp2[i] = RESAMP2(_create)(q->m_stage[i], q->f0_stage[i], q->As_stage[i]); } // reset object MSRESAMP2(_reset)(q); // return main object return q; }
// 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; }
float * fc_stage; // cut-off frequency for each stage float * f0_stage; // center frequency for each stage float * As_stage; // stop-band attenuation for each stage unsigned int * m_stage; // filter semi-length for each stage RESAMP2() * resamp2; // array of half-band resamplers T * buffer0; // buffer[0] T * buffer1; // buffer[1] unsigned int buffer_index; // index of buffer float zeta; // scaling factor }; // execute multi-stage resampler as interpolator // _q : msresamp object // _x : input sample // _y : output sample array [size:2^_num_stages x 1] void MSRESAMP2(_interp_execute)(MSRESAMP2() _q, TI _x, TO * _y); // execute multi-stage resampler as decimator // _q : msresamp object // _x : input sample array [size: 2^_num_stages x 1] // _y : output sample pointer void MSRESAMP2(_decim_execute)(MSRESAMP2() _q, TI * _x, TO * _y); // create multi-stage half-band resampler // _type : resampler type (e.g. LIQUID_RESAMP_DECIM) // _num_stages : number of resampling stages // _fc : filter cut-off frequency 0 < _fc < 0.5