// 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; }
// Design FIR using kaiser window // _n : filter length, _n > 0 // _fc : cutoff frequency, 0 < _fc < 0.5 // _As : stop-band attenuation [dB], _As > 0 // _mu : fractional sample offset, -0.5 < _mu < 0.5 // _h : output coefficient buffer, [size: _n x 1] void liquid_firdes_kaiser(unsigned int _n, float _fc, float _As, float _mu, float *_h) { // validate inputs if (_mu < -0.5f || _mu > 0.5f) { fprintf(stderr,"error: liquid_firdes_kaiser(), _mu (%12.4e) out of range [-0.5,0.5]\n", _mu); exit(1); } else if (_fc < 0.0f || _fc > 0.5f) { fprintf(stderr,"error: liquid_firdes_kaiser(), cutoff frequency (%12.4e) out of range (0, 0.5)\n", _fc); exit(1); } else if (_n == 0) { fprintf(stderr,"error: liquid_firdes_kaiser(), filter length must be greater than zero\n"); exit(1); } // choose kaiser beta parameter (approximate) float beta = kaiser_beta_As(_As); float t, h1, h2; unsigned int i; for (i=0; i<_n; i++) { t = (float)i - (float)(_n-1)/2 + _mu; // sinc prototype h1 = sincf(2.0f*_fc*t); // kaiser window h2 = kaiser(i,_n,beta,_mu); //printf("t = %f, h1 = %f, h2 = %f\n", t, h1, h2); // composite _h[i] = h1*h2; } }
// Design frequency-shifted root-Nyquist filter based on // the Kaiser-windowed sinc using approximation for rho. // // _k : filter over-sampling rate (samples/symbol) // _m : filter delay (symbols) // _beta : filter excess bandwidth factor (0,1) // _dt : filter fractional sample delay // _h : resulting filter [size: 2*_k*_m+1] void liquid_firdes_arkaiser(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h) { // validate input if (_k < 2) { fprintf(stderr,"error: liquid_firdes_arkaiser(), k must be at least 2\n"); exit(1); } else if (_m < 1) { fprintf(stderr,"error: liquid_firdes_arkaiser(), m must be at least 1\n"); exit(1); } else if (_beta <= 0.0f || _beta >= 1.0f) { fprintf(stderr,"error: liquid_firdes_arkaiser(), beta must be in (0,1)\n"); exit(1); } else if (_dt < -1.0f || _dt > 1.0f) { fprintf(stderr,"error: liquid_firdes_arkaiser(), dt must be in [-1,1]\n"); exit(1); } #if 0 // compute bandwidth adjustment estimate float rho_hat = rkaiser_approximate_rho(_m,_beta); // bandwidth correction factor #else // rho ~ c0 + c1*log(_beta) + c2*log^2(_beta) // c0 ~ 0.762886 + 0.067663*log(m) // c1 ~ 0.065515 // c2 ~ log( 1 - 0.088*m^-1.6 ) float c0 = 0.762886 + 0.067663*logf(_m); float c1 = 0.065515; float c2 = logf( 1 - 0.088*powf(_m,-1.6 ) ); float log_beta = logf(_beta); float rho_hat = c0 + c1*log_beta + c2*log_beta*log_beta; // ensure range is valid if (rho_hat <= 0.0f || rho_hat >= 1.0f) rho_hat = rkaiser_approximate_rho(_m,_beta); #endif unsigned int n=2*_k*_m+1; // filter length float kf = (float)_k; // samples/symbol (float) float del = _beta*rho_hat / kf; // transition bandwidth float As = estimate_req_filter_As(del, n); // stop-band suppression float fc = 0.5f*(1 + _beta*(1.0f-rho_hat))/kf; // filter cutoff #if DEBUG_RKAISER printf("rho-hat : %12.8f (compare to %12.8f)\n", rho_hat, rkaiser_approximate_rho(_m,_beta)); printf("fc : %12.8f\n", fc); printf("delta-f : %12.8f\n", del); printf("As : %12.8f dB\n", As); printf("alpha : %12.8f\n", kaiser_beta_As(As)); #endif // compute filter coefficients liquid_firdes_kaiser(n,fc,As,_dt,_h); // normalize coefficients float e2 = 0.0f; unsigned int i; for (i=0; i<n; i++) e2 += _h[i]*_h[i]; for (i=0; i<n; i++) _h[i] *= sqrtf(_k/e2); }