// create a resamp2 object // _m : filter semi-length (effective length: 4*_m+1) // _fc : center frequency of half-band filter // _As : stop-band attenuation [dB], _As > 0 RESAMP2() RESAMP2(_create)(unsigned int _m, float _fc, float _As) { // validate input if (_m < 2) { fprintf(stderr,"error: resamp2_%s_create(), filter semi-length must be at least 2\n", EXTENSION_FULL); exit(1); } RESAMP2() q = (RESAMP2()) malloc(sizeof(struct RESAMP2(_s))); q->m = _m; q->fc = _fc; q->As = _As; if ( q->fc < -0.5f || q->fc > 0.5f ) { fprintf(stderr,"error: resamp2_%s_create(), fc (%12.4e) must be in (-1,1)\n", EXTENSION_FULL, q->fc); exit(1); } // change filter length as necessary q->h_len = 4*(q->m) + 1; q->h = (TC *) malloc((q->h_len)*sizeof(TC)); q->h1_len = 2*(q->m); q->h1 = (TC *) malloc((q->h1_len)*sizeof(TC)); // design filter prototype unsigned int i; float t, h1, h2; TC h3; float beta = kaiser_beta_As(q->As); for (i=0; i<q->h_len; i++) { t = (float)i - (float)(q->h_len-1)/2.0f; h1 = sincf(t/2.0f); h2 = kaiser(i,q->h_len,beta,0); #if TC_COMPLEX == 1 h3 = cosf(2.0f*M_PI*t*q->fc) + _Complex_I*sinf(2.0f*M_PI*t*q->fc); #else h3 = cosf(2.0f*M_PI*t*q->fc); #endif q->h[i] = h1*h2*h3; } // resample, alternate sign, [reverse direction] unsigned int j=0; for (i=1; i<q->h_len; i+=2) q->h1[j++] = q->h[q->h_len - i - 1]; // create dotprod object q->dp = DOTPROD(_create)(q->h1, 2*q->m); // create window buffers q->w0 = WINDOW(_create)(2*(q->m)); q->w1 = WINDOW(_create)(2*(q->m)); RESAMP2(_clear)(q); return q; }
// 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 window buffers q->w0 = WINDOW(_create)(2*(q->m)); q->w1 = WINDOW(_create)(2*(q->m)); RESAMP2(_clear)(q); return q; } // re-create a resamp2 object with new properties // _q : original resamp2 object // _m : filter semi-length (effective length: 4*_m+1) // _fc : center frequency of half-band filter // _As : stop-band attenuation [dB], _As > 0 RESAMP2() RESAMP2(_recreate)(RESAMP2() _q, unsigned int _m, float _fc, float _As) { // only re-design filter if necessary if (_m != _q->m) { // destroy resampler and re-create from scratch RESAMP2(_destroy)(_q); _q = RESAMP2(_create)(_m, _fc, _As); } else { // re-design filter prototype unsigned int i; float t, h1, h2; TC h3;
// create dds object // _num_stages : number of halfband stages // _fc : input carrier // _bw : input signal bandwidth // _As : stop-band attenuation DDS() DDS(_create)(unsigned int _num_stages, float _fc, float _bw, float _As) { // create object DDS() q = (DDS()) malloc(sizeof(struct DDS(_s))); q->num_stages = _num_stages; q->rate = 1<<(q->num_stages); q->fc0 = _fc; q->bw0 = _bw; q->As0 = _As; // error checking if (q->fc0 > 0.5f || q->fc0 < -0.5f) { fprintf(stderr,"error: dds_xxxf_create(), frequency %12.4e is out of range [-0.5,0.5]\n", q->fc0); exit(1); } // allocate memory for filter properties q->fc = (float*) malloc((q->num_stages)*sizeof(float)); q->ft = (float*) malloc((q->num_stages)*sizeof(float)); q->As = (float*) malloc((q->num_stages)*sizeof(float)); q->h_len = (unsigned int*) malloc((q->num_stages)*sizeof(unsigned int)); unsigned int i; float fc, bw; fc = 0.5*(1<<q->num_stages)*q->fc0; // filter center frequency bw = q->bw0; // signal bandwidth // TODO : compute/set filter bandwidths, lengths appropriately for (i=0; i<q->num_stages; i++) { q->fc[i] = fc; while (q->fc[i] > 0.5f) q->fc[i] -= 1.0f; while (q->fc[i] < -0.5f) q->fc[i] += 1.0f; // compute transition bandwidth q->ft[i] = 0.5f*(1.0f - bw); if (q->ft[i] > 0.45) q->ft[i] = 0.45f; // set maximum bandwidth q->As[i] = q->As0; // compute (estimate) required filter length //q->h_len[i] = i==0 ? 37 : q->h_len[i-1]*0.7; q->h_len[i] = estimate_req_filter_len(q->ft[i], q->As[i]); if ((q->h_len[i] % 2) == 0) q->h_len[i]++; // ensure h_len[i] is of form 4*m+1 unsigned int m = (q->h_len[i]-1)/4; if (m < 1) m = 1; q->h_len[i] = 4*m+1; // update carrier, bandwidth parameters fc *= 0.5f; bw *= 0.5f; } // allocate memory for buffering q->buffer_len = q->rate; q->buffer0 = (T*) malloc((q->buffer_len)*sizeof(T)); q->buffer1 = (T*) malloc((q->buffer_len)*sizeof(T)); // allocate memory for resampler pointers and create objects q->halfband_resamp = (RESAMP2()*) malloc((q->num_stages)*sizeof(RESAMP()*)); for (i=0; i<q->num_stages; i++) { q->halfband_resamp[i] = RESAMP2(_create)(q->h_len[i], q->fc[i], q->As[i]); } // set down-converter scaling factor q->zeta = 1.0f / ((float)(q->rate)); // create NCO and set frequency q->ncox = NCO(_create)(LIQUID_VCO); // TODO : ensure range is in [-pi,pi] NCO(_set_frequency)(q->ncox, 2*M_PI*(q->rate)*(q->fc0)); return q; }