// // Test DC gain control // void autotest_agc_crcf_dc_gain_control() { // set paramaters float gamma = 0.1f; // nominal signal level float bt = 0.1f; // bandwidth-time product float tol = 0.001f; // error tolerance // create AGC object and initialize agc_crcf q = agc_crcf_create(); agc_crcf_set_bandwidth(q, bt); unsigned int i; float complex x = gamma; // input sample float complex y; // output sample for (i=0; i<256; i++) agc_crcf_execute(q, x, &y); // Check results CONTEND_DELTA( crealf(y), 1.0f, tol ); CONTEND_DELTA( cimagf(y), 0.0f, tol ); CONTEND_DELTA( agc_crcf_get_gain(q), 1.0f/gamma, tol ); // destroy AGC object agc_crcf_destroy(q); }
// _p : polynomial, [size: _order+1 x 1] // _r : roots (sorted), [size: _order x 1] // _ordre : polynomial order void polyf_findroots_testbench(float * _p, float complex * _r, unsigned int _order) { float tol=1e-6f; float complex roots[_order]; polyf_findroots(_p,_order+1,roots); unsigned int i; if (liquid_autotest_verbose) { printf("poly:\n"); for (i=0; i<=_order; i++) printf(" p[%3u] = %12.8f\n", i, _p[i]); printf("roots:\n"); for (i=0; i<_order; i++) { float e = cabsf(roots[i] - _r[i]); printf(" r[%3u] = %12.8f + %12.8fj (%12.8f + %12.8fj) %12.4e%s\n", i, crealf(roots[i]), cimagf(roots[i]), crealf( _r[i]), cimagf( _r[i]), e, e < tol ? "" : " *"); } } // check to see if roots match within relative tolerance for (i=0; i<_order; i++) { CONTEND_DELTA(crealf(roots[i]), crealf(_r[i]), tol); CONTEND_DELTA(cimagf(roots[i]), cimagf(_r[i]), tol); } }
// // AUTOTEST: inverse // void autotest_matrixcf_inv() { float tol = 1e-3f; float complex x[9] = { 0.054076+ 0.263160*_I, 0.570850+ -0.208230*_I, 0.551480+ -0.189100*_I, -0.223700+ 0.298170*_I, 0.416250+ 1.152200*_I, -0.299920+ 0.469310*_I, -1.485400+ -0.192370*_I, -0.679430+ 0.528100*_I, -0.827860+ -0.345740*_I }; float complex x_inv[9]; float complex x_inv_test[9] = { -0.277900+ -0.717820*_I, 0.559370+ 0.305450*_I, -0.691300+ 0.080448*_I, -0.026647+ -0.650270*_I, 0.702820+ -0.990530*_I, 0.237160+ 0.231150*_I, 1.319100+ 1.318300*_I, -0.539880+ 0.808700*_I, -0.255610+ 0.084624*_I }; memmove(x_inv, x, sizeof(x)); matrixcf_inv(x_inv,3,3); unsigned int i; for (i=0; i<9; i++) { CONTEND_DELTA(crealf(x_inv[i]), crealf(x_inv_test[i]), tol); CONTEND_DELTA(cimagf(x_inv[i]), cimagf(x_inv_test[i]), tol); } }
// autotest helper function // _b : filter coefficients (numerator) // _a : filter coefficients (denominator) // _h_len : filter coefficients length // _x : input array // _x_len : input array length // _y : output array // _y_len : output array length void iirfilt_crcf_test(float * _b, float * _a, unsigned int _h_len, float complex * _x, unsigned int _x_len, float complex * _y, unsigned int _y_len) { float tol = 0.001f; // load filter coefficients externally iirfilt_crcf q = iirfilt_crcf_create(_b, _h_len, _a, _h_len); // allocate memory for output float complex y_test[_y_len]; unsigned int i; // compute output for (i=0; i<_x_len; i++) { iirfilt_crcf_execute(q, _x[i], &y_test[i]); CONTEND_DELTA( crealf(y_test[i]), crealf(_y[i]), tol ); CONTEND_DELTA( cimagf(y_test[i]), cimagf(_y[i]), tol ); } // destroy filter object iirfilt_crcf_destroy(q); }
// helper function (compare structured object to ordinal computation) void runtest_dotprod_cccf(unsigned int _n) { float tol = 1e-3; float complex h[_n]; float complex x[_n]; // generate random coefficients unsigned int i; for (i=0; i<_n; i++) { h[i] = randnf() + randnf() * _Complex_I; x[i] = randnf() + randnf() * _Complex_I; } // compute expected value (ordinal computation) float complex y_test; dotprod_cccf_run(h, x, _n, &y_test); // create and run dot product object float complex y; dotprod_cccf dp; dp = dotprod_cccf_create(h,_n); dotprod_cccf_execute(dp, x, &y); dotprod_cccf_destroy(dp); // print results if (liquid_autotest_verbose) { printf(" dotprod-cccf-%-4u : %12.8f + j%12.8f (expected %12.8f + j%12.8f)\n", _n, crealf(y), cimagf(y), crealf(y_test), cimagf(y_test)); } // validate result CONTEND_DELTA(crealf(y), crealf(y_test), tol); CONTEND_DELTA(cimagf(y), cimagf(y_test), tol); }
// test sparse floating-point vector multiplication void autotest_smatrixf_vmul() { float tol = 1e-6f; // A = [ // 0 0 0 0 4 // 0 0 0 0 0 // 0 0 0 3 0 // 2 0 0 0 1 // create sparse matrix and set values smatrixf A = smatrixf_create(4, 5); smatrixf_set(A, 0,4, 4); smatrixf_set(A, 2,3, 3); smatrixf_set(A, 3,0, 2); smatrixf_set(A, 3,4, 0); smatrixf_set(A, 3,4, 1); // initialize input vector float x[5] = {7, 1, 5, 2, 2}; float y_test[4] = {8, 0, 6, 16}; float y[4]; // multiply and run test smatrixf_vmul(A,x,y); // check values CONTEND_DELTA( y[0], y_test[0], tol ); CONTEND_DELTA( y[1], y_test[1], tol ); CONTEND_DELTA( y[2], y_test[2], tol ); CONTEND_DELTA( y[3], y_test[3], tol ); smatrixf_destroy(A); }
void autotest_nco_crcf_mix_block_up() { // options unsigned int buf_len = 4096; float phase = 0.7123f; float freq = 0; //0.1324f; float tol = 1e-2f; // create object nco_crcf nco = nco_crcf_create(LIQUID_NCO); nco_crcf_set_phase (nco, phase); nco_crcf_set_frequency(nco, freq); // generate signal float complex buf_0[buf_len]; float complex buf_1[buf_len]; unsigned int i; for (i=0; i<buf_len; i++) buf_0[i] = cexpf(_Complex_I*2*M_PI*randf()); // mix signal nco_crcf_mix_block_up(nco, buf_0, buf_1, buf_len); // compare result to expected float phi = phase; for (i=0; i<buf_len; i++) { float complex v = buf_0[i] * cexpf(_Complex_I*phi); CONTEND_DELTA( crealf(buf_1[i]), crealf(v), tol); CONTEND_DELTA( cimagf(buf_1[i]), cimagf(v), tol); phi += freq; } // destroy object nco_crcf_destroy(nco); }
// // test nco block mixing // void autotest_nco_block_mixing() { // frequency, phase float f = 0.1f; float phi = M_PI; // error tolerance (high for NCO) float tol = 0.05f; unsigned int i; // number of samples unsigned int num_samples = 1024; // store samples float complex * x = (float complex*)malloc(num_samples*sizeof(float complex)); float complex * y = (float complex*)malloc(num_samples*sizeof(float complex)); // generate complex sin/cos for (i=0; i<num_samples; i++) x[i] = cexpf(_Complex_I*(f*i + phi)); // initialize nco object nco_crcf p = nco_crcf_create(LIQUID_NCO); nco_crcf_set_frequency(p, f); nco_crcf_set_phase(p, phi); // mix signal back to zero phase (in pieces) unsigned int num_remaining = num_samples; i = 0; while (num_remaining > 0) { unsigned int n = 7 < num_remaining ? 7 : num_remaining; nco_crcf_mix_block_down(p, &x[i], &y[i], n); i += n; num_remaining -= n; } // assert mixer output is correct for (i=0; i<num_samples; i++) { CONTEND_DELTA( crealf(y[i]), 1.0f, tol ); CONTEND_DELTA( cimagf(y[i]), 0.0f, tol ); } // free those buffers free(x); free(y); // destroy NCO object nco_crcf_destroy(p); }
// // test phase-locked loop // _type : NCO type (e.g. LIQUID_NCO) // _phase_offset : initial phase offset // _freq_offset : initial frequency offset // _pll_bandwidth : bandwidth of phase-locked loop // _num_iterations : number of iterations to run // _tol : error tolerance void nco_crcf_pll_test(int _type, float _phase_offset, float _freq_offset, float _pll_bandwidth, unsigned int _num_iterations, float _tol) { // objects nco_crcf nco_tx = nco_crcf_create(_type); nco_crcf nco_rx = nco_crcf_create(_type); // initialize objects nco_crcf_set_phase(nco_tx, _phase_offset); nco_crcf_set_frequency(nco_tx, _freq_offset); nco_crcf_pll_set_bandwidth(nco_rx, _pll_bandwidth); // run loop unsigned int i; float phase_error; float complex r, v; for (i=0; i<_num_iterations; i++) { // received complex signal nco_crcf_cexpf(nco_tx,&r); nco_crcf_cexpf(nco_rx,&v); // error estimation phase_error = cargf(r*conjf(v)); // update pll nco_crcf_pll_step(nco_rx, phase_error); // update nco objects nco_crcf_step(nco_tx); nco_crcf_step(nco_rx); } // ensure phase of oscillators is locked float nco_tx_phase = nco_crcf_get_phase(nco_tx); float nco_rx_phase = nco_crcf_get_phase(nco_rx); CONTEND_DELTA(nco_tx_phase, nco_rx_phase, _tol); // ensure frequency of oscillators is locked float nco_tx_freq = nco_crcf_get_frequency(nco_tx); float nco_rx_freq = nco_crcf_get_frequency(nco_rx); CONTEND_DELTA(nco_tx_freq, nco_rx_freq, _tol); // clean it up nco_crcf_destroy(nco_tx); nco_crcf_destroy(nco_rx); }
// // Test AC gain control // void autotest_agc_crcf_ac_gain_control() { // set paramaters float gamma = 0.1f; // nominal signal level float bt = 0.1f; // bandwidth-time product float tol = 0.001f; // error tolerance float dphi = 0.1f; // NCO frequency // create AGC object and initialize agc_crcf q = agc_crcf_create(); agc_crcf_set_bandwidth(q, bt); unsigned int i; float complex x; float complex y; for (i=0; i<256; i++) { x = gamma * cexpf(_Complex_I*i*dphi); agc_crcf_execute(q, x, &y); } if (liquid_autotest_verbose) printf("gamma : %12.8f, rssi : %12.8f\n", gamma, agc_crcf_get_signal_level(q)); // Check results CONTEND_DELTA( agc_crcf_get_gain(q), 1.0f/gamma, tol); // destroy AGC object agc_crcf_destroy(q); }
// // AUTOTEST: regular phase-unwrapping // void autotest_nco_unwrap_phase() { unsigned int n=32; // number of steps float tol = 1e-6f; // error tolerance // initialize data arrays float phi[n]; // original array float theta[n]; // wrapped array float phi_hat[n]; // unwrapped array float phi0 = 3.0f; // initial phase float dphi = 0.1f; // phase step unsigned int i; for (i=0; i<n; i++) { // phase input phi[i] = phi0 + i*dphi; // wrapped array theta[i] = phi[i]; while (theta[i] > M_PI) theta[i] -= 2*M_PI; while (theta[i] < -M_PI) theta[i] += 2*M_PI; // initialize output phi_hat[i] = theta[i]; } // unwrap phase liquid_unwrap_phase(phi_hat, n); // compare input to output for (i=0; i<n; i++) CONTEND_DELTA( phi[i], phi_hat[i], tol ); }
// autotest helper function void fft_r2r_test(float * _x, float * _test, unsigned int _n, unsigned int _kind) { int _flags = 0; float tol=1e-4f; unsigned int i; float y[_n]; // compute real even/odd FFT fftplan q = fft_create_plan_r2r_1d(_n, _x, y, _kind, _flags); fft_execute(q); // print results if (liquid_autotest_verbose) { printf("%12s %12s\n", "expected", "actual"); for (i=0; i<_n; i++) printf("%12.8f %12.8f\n", _test[i], y[i]); } // validate results for (i=0; i<_n; i++) CONTEND_DELTA( y[i], _test[i], tol); // destroy plans fft_destroy_plan(q); }
// // AUTOTEST: Q function // void autotest_Q() { float tol = 1e-6f; CONTEND_DELTA(liquid_Qf(-4.0f), 0.999968329f, tol); CONTEND_DELTA(liquid_Qf(-3.0f), 0.998650102f, tol); CONTEND_DELTA(liquid_Qf(-2.0f), 0.977249868f, tol); CONTEND_DELTA(liquid_Qf(-1.0f), 0.841344746f, tol); CONTEND_DELTA(liquid_Qf( 0.0f), 0.5f, tol); CONTEND_DELTA(liquid_Qf( 1.0f), 0.158655254f, tol); CONTEND_DELTA(liquid_Qf( 2.0f), 0.022750132f, tol); CONTEND_DELTA(liquid_Qf( 3.0f), 0.001349898f, tol); CONTEND_DELTA(liquid_Qf( 4.0f), 0.000031671f, tol); }
// test sparse floating-point matrix multiplication void autotest_smatrixf_mul() { float tol = 1e-6f; // intialize matrices smatrixf a = smatrixf_create(4, 5); smatrixf b = smatrixf_create(5, 3); smatrixf c = smatrixf_create(4, 3); // initialize 'a' // 0 0 0 0 4 // 0 0 0 0 0 // 0 0 0 3 0 // 2 0 0 0 1 smatrixf_set(a, 0,4, 4); smatrixf_set(a, 2,3, 3); smatrixf_set(a, 3,0, 2); smatrixf_set(a, 3,4, 0); smatrixf_set(a, 3,4, 1); // initialize 'b' // 7 6 0 // 0 0 0 // 0 0 0 // 0 5 0 // 2 0 0 smatrixf_set(b, 0,0, 7); smatrixf_set(b, 0,1, 6); smatrixf_set(b, 3,1, 5); smatrixf_set(b, 4,0, 2); // compute 'c' // 8 0 0 // 0 0 0 // 0 15 0 // 16 12 0 smatrixf_mul(a,b,c); float c_test[12] = { 8, 0, 0, 0, 0, 0, 0, 15, 0, 16, 12, 0}; // check values unsigned int i; unsigned int j; for (i=0; i<4; i++) { for (j=0; j<3; j++) { CONTEND_DELTA(smatrixf_get(c,i,j), matrixf_access(c_test,4,3,i,j), tol); } } smatrixf_destroy(a); smatrixf_destroy(b); smatrixf_destroy(c); }
void autotest_iirdes_cplxpair_n6() { float tol = 1e-8f; // float complex r[6] = { 0.980066577841242 + 0.198669330795061 * _Complex_I, 5.000000000000000 + 0.000000000000000 * _Complex_I, -0.416146836547142 + 0.909297426825682 * _Complex_I, 0.980066577841242 - 0.198669330795061 * _Complex_I, 0.300000000000000 + 0.000000000000000 * _Complex_I, -0.416146836547142 - 0.909297426825682 * _Complex_I }; float complex p[6]; float complex ptest[6] = { -0.416146836547142 - 0.909297426825682 * _Complex_I, -0.416146836547142 + 0.909297426825682 * _Complex_I, 0.980066577841242 - 0.198669330795061 * _Complex_I, 0.980066577841242 + 0.198669330795061 * _Complex_I, 0.300000000000000 + 0.000000000000000 * _Complex_I, 5.000000000000000 + 0.000000000000000 * _Complex_I }; // compute complex pairs liquid_cplxpair(r,6,1e-6f,p); unsigned int i; if (liquid_autotest_verbose) { printf("complex set:\n"); for (i=0; i<6; i++) printf(" r[%3u] : %12.8f + j*%12.8f\n", i, crealf(r[i]), cimagf(r[i])); printf("complex pairs:\n"); for (i=0; i<6; i++) printf(" p[%3u] : %12.8f + j*%12.8f\n", i, crealf(p[i]), cimagf(p[i])); } // run test for (i=0; i<6; i++) { CONTEND_DELTA( crealf(p[i]), crealf(ptest[i]), tol ); CONTEND_DELTA( cimagf(p[i]), cimagf(ptest[i]), tol ); } }
// // AUTOTEST: // void autotest_firinterp_rrrf_generic() { float h[9] = { -0.2762293319046737, 1.4757679031218007, 0.1432569489572376, -0.2142368750177835, 1.3471241294836864, 0.1166010284926269, 0.0536534505390281, 0.1412672462812405, -0.0991854372394269}; unsigned int M = 4; // firinterp factor firinterp_rrrf q = firinterp_rrrf_create(M,h,9); float x[] = {1.0, -1.0, 1.0, 1.0}; float y[16]; float test[16] = { -0.2762293319046737, 1.4757679031218007, 0.1432569489572376, -0.2142368750177835, 1.6233534613883602, -1.3591668746291738, -0.0896034984182095, 0.3555041212990241, -1.7225388986277870, 1.3591668746291738, 0.0896034984182095, -0.3555041212990241, 1.1700802348184398, 1.5923689316144276, 0.1969103994962658, -0.0729696287365430}; float tol = 1e-6; unsigned int i; for (i=0; i<4; i++) firinterp_rrrf_execute(q, x[i], &y[i*M]); for (i=0; i<16; i++) { CONTEND_DELTA(y[i], test[i], tol); if (liquid_autotest_verbose) printf(" y(%u) = %8.4f;\n", i+1, y[i]); } if (liquid_autotest_verbose) firinterp_rrrf_print(q); // destroy interpolator object firinterp_rrrf_destroy(q); }
// // AUTOTEST: polycf_findroots (random roots) // void xautotest_polycf_findroots_rand() { unsigned int n=5; float tol=1e-4f; float complex p[n]; float complex roots[n-1]; float complex p_hat[n]; unsigned int i; for (i=0; i<n; i++) p[i] = i == n-1 ? 1 : 3.0f * randnf(); polycf_findroots(p,n,roots); float complex roots_hat[n-1]; // convert form... for (i=0; i<n-1; i++) roots_hat[i] = -roots[i]; polycf_expandroots(roots_hat,n-1,p_hat); if (liquid_autotest_verbose) { printf("poly:\n"); for (i=0; i<n; i++) printf(" p[%3u] = %12.8f + j*%12.8f\n", i, crealf(p[i]), cimagf(p[i])); printf("roots:\n"); for (i=0; i<n-1; i++) printf(" r[%3u] = %12.8f + j*%12.8f\n", i, crealf(roots[i]), cimagf(roots[i])); printf("poly (expanded roots):\n"); for (i=0; i<n; i++) printf(" p[%3u] = %12.8f + j*%12.8f\n", i, crealf(p_hat[i]), cimagf(p_hat[i])); } for (i=0; i<n; i++) { CONTEND_DELTA(crealf(p[i]), crealf(p_hat[i]), tol); CONTEND_DELTA(cimagf(p[i]), cimagf(p_hat[i]), tol); } }
// // AUTOTEST : design 2nd-order butterworth filter (design comes // from [Ziemer:1998] Example 9-7, pp. 440--442) // void autotest_iirdes_butter_2() { // initialize variables unsigned int order = 2; // filter order float fc = 0.25f; // normalized cutoff frequency float f0 = 0.0f; // center frequency (ignored for low-pass filter) float Ap = 1.0f; // pass-band ripple (ignored for Butterworth) float As = 40.0f; // stop-band attenuation (ignored for Butterworth) float tol = 1e-6f; // error tolerance // initialize pre-determined coefficient array // for 2^nd-order low-pass Butterworth filter // with cutoff frequency 0.25 float a_test[3] = { 1.0f, 0.0f, 0.171572875253810f}; float b_test[3] = { 0.292893218813452f, 0.585786437626905f, 0.292893218813452f}; // output coefficients float a[3]; float b[3]; // design butterworth filter liquid_iirdes(LIQUID_IIRDES_BUTTER, LIQUID_IIRDES_LOWPASS, LIQUID_IIRDES_TF, order, fc, f0, Ap, As, b, a); // Ensure data are equal to within tolerance unsigned int i; for (i=0; i<3; i++) { CONTEND_DELTA( b[i], b_test[i], tol ); CONTEND_DELTA( a[i], a_test[i], tol ); } }
// Help function to keep code base small // _kf : modulation factor // _type : demodulation type {LIQUID_FREQDEM_DELAYCONJ, LIQUID_FREQDEM_PLL} void freqmodem_test(float _kf, liquid_freqdem_type _type) { // options unsigned int num_samples = 1024; //float tol = 1e-2f; unsigned int i; // create mod/demod objects freqmod mod = freqmod_create(_kf); // modulator freqdem dem = freqdem_create(_kf,_type); // demodulator // allocate arrays float m[num_samples]; // message signal float complex r[num_samples]; // received signal (complex baseband) float y[num_samples]; // demodulator output // generate message signal (single-frequency sine) for (i=0; i<num_samples; i++) m[i] = 0.7f*cosf(2*M_PI*0.013f*i + 0.0f); // modulate/demodulate signal for (i=0; i<num_samples; i++) { // modulate freqmod_modulate(mod, m[i], &r[i]); // demodulate freqdem_demodulate(dem, r[i], &y[i]); } // delete modem objects freqmod_destroy(mod); freqdem_destroy(dem); #if 0 // compute power spectral densities and compare float complex mcf[num_samples]; float complex ycf[num_samples]; float complex M[num_samples]; float complex Y[num_samples]; for (i=0; i<num_samples; i++) { mcf[i] = m[i] * hamming(i,num_samples); ycf[i] = y[i] * hamming(i,num_samples); } fft_run(num_samples, mcf, M, LIQUID_FFT_FORWARD, 0); fft_run(num_samples, ycf, Y, LIQUID_FFT_FORWARD, 0); // run test: compare spectral magnitude for (i=0; i<num_samples; i++) CONTEND_DELTA( cabsf(Y[i]), cabsf(M[i]), tol ); #endif }
// // test Cholesky decomposition // void autotest_matrixcf_chol() { float tol = 1e-3f; // error tolerance // lower triangular matrix with positive values on diagonal float complex L[16]= { 1.01, 0, 0, 0, -1.42 + _Complex_I*0.25, 0.50, 0, 0, 0.32 - _Complex_I*1.23, 2.01 + _Complex_I*0.78, 0.30, 0, -1.02 + _Complex_I*1.02, -0.32 - _Complex_I*0.03, -1.65 + _Complex_I*2.01, 1.07}; float complex A[16]; // A = L * L^T float complex Lp[16]; // output Cholesky decomposition unsigned int i; // compute A matrixcf_mul_transpose(L,4,4,A); // force A to be positive definite for (i=0; i<4; i++) matrix_access(A,4,4,i,i) = creal(matrix_access(A,4,4,i,i)); // run decomposition matrixcf_chol(A,4,Lp); if (liquid_autotest_verbose) { printf("L :\n"); matrixcf_print(L,4,4); printf("A :\n"); matrixcf_print(A,4,4); printf("Lp:\n"); matrixcf_print(Lp,4,4); } for (i=0; i<16; i++) { CONTEND_DELTA( crealf(L[i]), crealf(Lp[i]), tol ); CONTEND_DELTA( cimagf(L[i]), cimagf(Lp[i]), tol ); } }
// // AUTOTEST : iir group delay (second-order sections), n=8 // void autotest_iir_groupdelay_sos_n8() { // create coefficients arrays (7th-order Butterworth) float B[12] = { 0.00484212, 0.00968423, 0.00484212, 1.00000000, 2.00000000, 1.00000000, 1.00000000, 2.00000000, 1.00000000, 1.00000000, 1.00000000, 0.00000000}; float A[12] = { 1.00000000, -0.33283597, 0.07707999, 1.00000000, -0.38797498, 0.25551325, 1.00000000, -0.51008475, 0.65066898, 1.00000000, -0.15838444, 0.00000000}; float tol = 1e-3f; unsigned int i; // create testing vectors float fc[7] = { 0.00000, 0.06250, 0.12500, 0.18750, 0.25000, 0.31250, 0.37500}; float g0[7] = { 3.09280801068444, 3.30599360247944, 4.18341028373046, 7.71934054380586, 4.34330109915390, 2.60203085226210, 1.97868452107144}; // // test with iir filter (second-order sections) // // create filter iirfilt_rrrf filter = iirfilt_rrrf_create_sos(B,A,4); // run tests float g; for (i=0; i<7; i++) { g = iirfilt_rrrf_groupdelay(filter, fc[i]); CONTEND_DELTA( g, g0[i], tol ); } // destroy filter iirfilt_rrrf_destroy(filter); }
// // AUTOTEST : iir group delay, n=3 // void autotest_iir_groupdelay_n3() { // create coefficients array float b[3] = {0.20657210, 0.41314420, 0.20657210}; float a[3] = {1.00000000, -0.36952737, 0.19581573}; float tol = 1e-3f; unsigned int i; // create testing vectors float fc[4] = { 0.000, 0.125, 0.250, 0.375}; float g0[4] = { 0.973248939389634, 1.366481121240365, 1.227756735863196, 0.651058521306726}; // run tests float g; for (i=0; i<4; i++) { g = iir_group_delay(b, 3, a, 3, fc[i]); CONTEND_DELTA( g, g0[i], tol ); } // create filter iirfilt_rrrf filter = iirfilt_rrrf_create(b,3,a,3); // run tests again for (i=0; i<4; i++) { g = iirfilt_rrrf_groupdelay(filter, fc[i]); CONTEND_DELTA( g, g0[i], tol ); } // destroy filter iirfilt_rrrf_destroy(filter); }
// // AUTOTEST : fir group delay, n=3 // void autotest_fir_groupdelay_n3() { // create coefficients array float h[3] = {0.1, 0.2, 0.4}; float tol = 1e-3f; unsigned int i; // create testing vectors float fc[4] = { 0.000, 0.125, 0.250, 0.375}; float g0[4] = { 1.42857142857143, 1.54756605839643, 2.15384615384615, 2.56861651421767}; // run tests float g; for (i=0; i<4; i++) { g = fir_group_delay(h, 3, fc[i]); CONTEND_DELTA( g, g0[i], tol ); } // create filter firfilt_rrrf filter = firfilt_rrrf_create(h,3); // run tests again for (i=0; i<4; i++) { g = firfilt_rrrf_groupdelay(filter, fc[i]); CONTEND_DELTA( g, g0[i], tol ); } // destroy filter firfilt_rrrf_destroy(filter); }
// // AUTOTEST: bsync_crcf/simple correlation with phase // offset // void xautotest_bsync_crcf_phase_15() { // generate sequence (15-bit msequence) float h[15] = { 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0 }; float tol = 1e-3f; float theta = 0.3f; // generate synchronizer bsync_crcf fs = bsync_crcf_create(15,h); // // run tests // unsigned int i; float complex rxy; // fill buffer with sequence for (i=0; i<15; i++) bsync_crcf_correlate(fs,h[i]*cexpf(_Complex_I*theta),&rxy); // correlation should be 1.0 CONTEND_DELTA( crealf(rxy), 1.0f*cosf(theta), tol ); CONTEND_DELTA( cimagf(rxy), 1.0f*sinf(theta), tol ); // all other cross-correlations should be exactly -1/15 for (i=0; i<14; i++) { bsync_crcf_correlate(fs,h[i]*cexpf(_Complex_I*theta),&rxy); CONTEND_DELTA( crealf(rxy), -1.0f/15.0f*cosf(theta), tol ); CONTEND_DELTA( cimagf(rxy), -1.0f/15.0f*sinf(theta), tol ); } // clean it up bsync_crcf_destroy(fs); }
// // AUTOTEST: Factorial // void autotest_factorial() { float tol = 1e-3f; CONTEND_DELTA(liquid_factorialf(0), 1, tol); CONTEND_DELTA(liquid_factorialf(1), 1, tol); CONTEND_DELTA(liquid_factorialf(2), 2, tol); CONTEND_DELTA(liquid_factorialf(3), 6, tol); CONTEND_DELTA(liquid_factorialf(4), 24, tol); CONTEND_DELTA(liquid_factorialf(5), 120, tol); CONTEND_DELTA(liquid_factorialf(6), 720, tol); }
// autotest helper function // _theta : input phase // _cos : expected output: cos(_theta) // _sin : expected output: sin(_theta) // _type : NCO type (e.g. LIQUID_NCO) // _tol : error tolerance void nco_crcf_phase_test(float _theta, float _cos, float _sin, int _type, float _tol) { // create object nco_crcf nco = nco_crcf_create(_type); // set phase nco_crcf_set_phase(nco, _theta); // compute cosine and sine outputs float c = nco_crcf_cos(nco); float s = nco_crcf_sin(nco); // run tests CONTEND_DELTA( c, _cos, _tol ); CONTEND_DELTA( s, _sin, _tol ); // destroy object nco_crcf_destroy(nco); }
// // test nco mixing // void autotest_nco_mixing() { // frequency, phase float f = 0.1f; float phi = M_PI; // error tolerance (high for NCO) float tol = 0.05f; // initialize nco object nco_crcf p = nco_crcf_create(LIQUID_NCO); nco_crcf_set_frequency(p, f); nco_crcf_set_phase(p, phi); unsigned int i; float nco_i, nco_q; for (i=0; i<64; i++) { // generate sin/cos nco_crcf_sincos(p, &nco_q, &nco_i); // mix back to zero phase complex float nco_cplx_in = nco_i + _Complex_I*nco_q; complex float nco_cplx_out; nco_crcf_mix_down(p, nco_cplx_in, &nco_cplx_out); // assert mixer output is correct CONTEND_DELTA(crealf(nco_cplx_out), 1.0f, tol); CONTEND_DELTA(cimagf(nco_cplx_out), 0.0f, tol); //printf("%3u : %12.8f + j*%12.8f\n", i, crealf(nco_cplx_out), cimagf(nco_cplx_out)); // step nco nco_crcf_step(p); } // destroy NCO object nco_crcf_destroy(p); }
// // AUTOTEST: bsync_rrrf/simple correlation // void autotest_bsync_rrrf_15() { // generate sequence (15-bit msequence) float h[15] = { 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0 }; float tol = 1e-3f; // generate synchronizer bsync_rrrf fs = bsync_rrrf_create(15,h); // // run tests // unsigned int i; float rxy; // fill buffer with sequence for (i=0; i<15; i++) bsync_rrrf_correlate(fs,h[i],&rxy); // correlation should be 1.0 CONTEND_DELTA( rxy, 1.0f, tol ); // all other cross-correlations should be exactly -1/15 for (i=0; i<14; i++) { bsync_rrrf_correlate(fs,h[i],&rxy); CONTEND_DELTA( rxy, -1.0f/15.0f, tol ); } // clean it up bsync_rrrf_destroy(fs); }
// autotest helper function // _x : fft input array // _test : expected fft output // _n : fft size void fft_test(float complex * _x, float complex * _test, unsigned int _n) { int _method = 0; float tol=2e-4f; unsigned int i; float complex y[_n], z[_n]; // compute FFT fftplan pf = fft_create_plan(_n, _x, y, LIQUID_FFT_FORWARD, _method); fft_execute(pf); // compute IFFT fftplan pr = fft_create_plan(_n, y, z, LIQUID_FFT_BACKWARD, _method); fft_execute(pr); // normalize inverse for (i=0; i<_n; i++) z[i] /= (float) _n; // validate results float fft_error, ifft_error; for (i=0; i<_n; i++) { fft_error = cabsf( y[i] - _test[i] ); ifft_error = cabsf( _x[i] - z[i] ); CONTEND_DELTA( fft_error, 0, tol); CONTEND_DELTA( ifft_error, 0, tol); } // destroy plans fft_destroy_plan(pf); fft_destroy_plan(pr); }
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); }