// create from square-root Nyquist prototype // _type : filter type (e.g. LIQUID_RNYQUIST_RRC) // _k : nominal samples/symbol, _k > 1 // _m : filter delay [symbols], _m > 0 // _beta : rolloff factor, 0 < beta <= 1 // _mu : fractional sample offset,-0.5 < _mu < 0.5 FIRFILT() FIRFILT(_create_rnyquist)(int _type, unsigned int _k, unsigned int _m, float _beta, float _mu) { // validate input if (_k < 2) { fprintf(stderr,"error: firfilt_%s_create_rnyquist(), filter samples/symbol must be greater than 1\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr,"error: firfilt_%s_create_rnyquist(), filter delay must be greater than 0\n", EXTENSION_FULL); exit(1); } else if (_beta < 0.0f || _beta > 1.0f) { fprintf(stderr,"error: firfilt_%s_create_rnyquist(), filter excess bandwidth factor must be in [0,1]\n", EXTENSION_FULL); exit(1); } // generate square-root Nyquist filter unsigned int h_len = 2*_k*_m + 1; float hf[h_len]; liquid_firdes_rnyquist(_type,_k,_m,_beta,_mu,hf); // copy coefficients to type-specific array (e.g. float complex) unsigned int i; TC hc[h_len]; for (i=0; i<h_len; i++) hc[i] = hf[i]; // return filterbank object return FIRFILT(_create)(hc, h_len); }
// create firfilt object // _h : coefficients (filter taps) [size: _n x 1] // _n : filter length FIRFILT() FIRFILT(_create)(TC * _h, unsigned int _n) { // validate input if (_n == 0) { fprintf(stderr,"error: firfilt_%s_create(), filter length must be greater than zero\n", EXTENSION_FULL); exit(1); } // create filter object and initialize FIRFILT() q = (FIRFILT()) malloc(sizeof(struct FIRFILT(_s))); q->h_len = _n; q->h = (TC *) malloc((q->h_len)*sizeof(TC)); #if LIQUID_FIRFILT_USE_WINDOW // create window (internal buffer) q->w = WINDOW(_create)(q->h_len); #else // initialize array for buffering q->w_len = 1<<liquid_msb_index(q->h_len); // effectively 2^{floor(log2(len))+1} q->w_mask = q->w_len - 1; q->w = (TI *) malloc((q->w_len + q->h_len + 1)*sizeof(TI)); q->w_index = 0; #endif // load filter in reverse order unsigned int i; for (i=_n; i>0; i--) q->h[i-1] = _h[_n-i]; // create dot product object q->dp = DOTPROD(_create)(q->h, q->h_len); // set default scaling q->scale = 1; // reset filter state (clear buffer) FIRFILT(_reset)(q); return q; }
// create rectangular filter prototype FIRFILT() FIRFILT(_create_rect)(unsigned int _n) { // validate input if (_n == 0 || _n > 1024) { fprintf(stderr,"error: firfilt_%s_create_rect(), filter length must be in [1,1024]\n", EXTENSION_FULL); exit(1); } // create float array coefficients float hf[_n]; unsigned int i; for (i=0; i<_n; i++) hf[i] = 1.0f; // copy coefficients to type-specific array TC h[_n]; for (i=0; i<_n; i++) h[i] = (TC) hf[i]; // return filter object and return return FIRFILT(_create)(h, _n); }
// create filter using Kaiser-Bessel windowed sinc method // _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 FIRFILT() FIRFILT(_create_kaiser)(unsigned int _n, float _fc, float _As, float _mu) { // validate input if (_n == 0) { fprintf(stderr,"error: firfilt_%s_create_kaiser(), filter length must be greater than zero\n", EXTENSION_FULL); exit(1); } // compute temporary array for holding coefficients float hf[_n]; liquid_firdes_kaiser(_n, _fc, _As, _mu, hf); // copy coefficients to type-specific array TC h[_n]; unsigned int i; for (i=0; i<_n; i++) h[i] = (TC) hf[i]; // return FIRFILT(_create)(h, _n); }
// copy coefficients to type-specific array (e.g. float complex) unsigned int i; TC hc[h_len]; for (i=0; i<h_len; i++) hc[i] = hf[i]; // return filterbank object return FIRFILT(_create)(hc, h_len); } // re-create firfilt object // _q : original firfilt object // _h : new coefficients [size: _n x 1] // _n : new filter length FIRFILT() FIRFILT(_recreate)(FIRFILT() _q, TC * _h, unsigned int _n) { unsigned int i; // reallocate memory array if filter length has changed if (_n != _q->h_len) { // reallocate memory _q->h_len = _n; _q->h = (TC*) realloc(_q->h, (_q->h_len)*sizeof(TC)); #if LIQUID_FIRFILT_USE_WINDOW // recreate window object, preserving internal state _q->w = WINDOW(_recreate)(_q->w, _q->h_len); #else