void autotest_iirfiltsos_impulse_n2() { // initialize filter with 2nd-order low-pass butterworth filter float a[3] = { 1.000000000000000, -0.942809041582063, 0.333333333333333}; float b[3] = { 0.0976310729378175, 0.1952621458756350, 0.0976310729378175}; iirfiltsos_rrrf f = iirfiltsos_rrrf_create(b,a); // initialize oracle; expected output (generated with octave) float test[15] = { 9.76310729378175e-02, 2.87309604180767e-01, 3.35965474513536e-01, 2.20981418970514e-01, 9.63547883225231e-02, 1.71836926400291e-02, -1.59173219853878e-02, -2.07348926322729e-02, -1.42432702548109e-02, -6.51705310050832e-03, -1.39657983602602e-03, 8.55642936806248e-04, 1.27223450919543e-03, 9.14259886013424e-04, 4.37894317157432e-04}; unsigned int i; float v, y; float tol=1e-4f; // hit filter with impulse, compare output for (i=0; i<15; i++) { v = (i==0) ? 1.0f : 0.0f; iirfiltsos_rrrf_execute(f, v, &y); CONTEND_DELTA(test[i], y, tol); } iirfiltsos_rrrf_destroy(f); }
void autotest_iirfiltsos_step_n2() { // initialize filter with 2nd-order low-pass butterworth filter float a[3] = { 1.000000000000000, -0.942809041582063, 0.333333333333333}; float b[3] = { 0.0976310729378175, 0.1952621458756350, 0.0976310729378175}; iirfiltsos_rrrf f = iirfiltsos_rrrf_create(b,a); float test[15] = { 0.0976310729378175, 0.3849406771185847, 0.7209061516321208, 0.9418875706026352, 1.0382423589251584, 1.0554260515651877, 1.0395087295798000, 1.0187738369475272, 1.0045305666927162, 0.9980135135922078, 0.9966169337561817, 0.9974725766929878, 0.9987448112021832, 0.9996590710881966, 1.0000969654053542}; unsigned int i; float y; float tol=1e-4f; // hit filter with step, compare output for (i=0; i<15; i++) { iirfiltsos_rrrf_execute(f, 1.0f, &y); CONTEND_DELTA(test[i], y, tol ); } iirfiltsos_rrrf_destroy(f); }
// create synchronizer object from external coefficients // _k : samples per symbol // _M : number of filters in the bank // _h : matched filter coefficients // _h_len : length of matched filter SYMSYNC() SYMSYNC(_create)(unsigned int _k, unsigned int _M, TC * _h, unsigned int _h_len) { // validate input if (_k < 2) { fprintf(stderr,"error: symsync_%s_create(), input sample rate must be at least 2\n", EXTENSION_FULL); exit(1); } else if (_h_len == 0) { fprintf(stderr,"error: symsync_%s_create(), filter length must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_M == 0) { fprintf(stderr,"error: symsync_%s_create(), number of filter banks must be greater than zero\n", EXTENSION_FULL); exit(1); } SYMSYNC() q = (SYMSYNC()) malloc(sizeof(struct SYMSYNC(_s))); q->k = _k; q->M = _M; q->tau = 0.0f; q->bf = 0.0f; q->b = 0; // set output rate (nominally 1, full decimation) SYMSYNC(_set_output_rate)(q, 1); // TODO: validate length q->h_len = (_h_len-1)/q->M; // compute derivative filter TC dh[_h_len]; float hdh_max = 0.0f; unsigned int i; for (i=0; i<_h_len; i++) { if (i==0) { dh[i] = _h[i+1] - _h[_h_len-1]; } else if (i==_h_len-1) { dh[i] = _h[0] - _h[i-1]; } else { dh[i] = _h[i+1] - _h[i-1]; } // find maximum of h*dh if ( fabsf(_h[i]*dh[i]) > hdh_max || i==0 ) hdh_max = fabsf(_h[i]*dh[i]); } // apply scaling factor for normalized response // TODO: scale to 1.0 for consistency for (i=0; i<_h_len; i++) dh[i] *= 0.06f / hdh_max; q->mf = FIRPFB(_create)(q->M, _h, _h_len); q->dmf = FIRPFB(_create)(q->M, dh, _h_len); // reset state and initialize loop filter q->A[0] = 1.0f; q->B[0] = 0.0f; q->A[1] = 0.0f; q->B[1] = 0.0f; q->A[2] = 0.0f; q->B[2] = 0.0f; q->pll = iirfiltsos_rrrf_create(q->B, q->A); SYMSYNC(_reset)(q); SYMSYNC(_set_lf_bw)(q, 0.01f); // set output rate nominally at 1 sample/symbol (full decimation) SYMSYNC(_set_output_rate)(q, 1); // unlock loop control SYMSYNC(_unlock)(q); #if DEBUG_SYMSYNC q->debug_del = windowf_create(DEBUG_BUFFER_LEN); q->debug_tau = windowf_create(DEBUG_BUFFER_LEN); q->debug_bsoft = windowf_create(DEBUG_BUFFER_LEN); q->debug_b = windowf_create(DEBUG_BUFFER_LEN); q->debug_q_hat = windowf_create(DEBUG_BUFFER_LEN); #endif // return main object return q; }