void ModemFMStereo::disposeKit(ModemKit *kit) { ModemKitFMStereo *fmkit = (ModemKitFMStereo *)kit; msresamp_rrrf_destroy(fmkit->audioResampler); msresamp_rrrf_destroy(fmkit->stereoResampler); firfilt_rrrf_destroy(fmkit->firStereoLeft); firfilt_rrrf_destroy(fmkit->firStereoRight); firhilbf_destroy(fmkit->firStereoR2C); firhilbf_destroy(fmkit->firStereoC2R); nco_crcf_destroy(fmkit->stereoPilot); if (fmkit->iirDemphR) { iirfilt_rrrf_destroy(fmkit->iirDemphR); } if (fmkit->iirDemphL) { iirfilt_rrrf_destroy(fmkit->iirDemphL); } }
// 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_rrrf_test(float * _b, float * _a, unsigned int _h_len, float * _x, unsigned int _x_len, float * _y, unsigned int _y_len) { float tol = 0.001f; // load filter coefficients externally iirfilt_rrrf q = iirfilt_rrrf_create(_b, _h_len, _a, _h_len); // allocate memory for output float y_test[_y_len]; unsigned int i; // compute output for (i=0; i<_x_len; i++) { iirfilt_rrrf_execute(q, _x[i], &y_test[i]); CONTEND_DELTA( y_test[i], _y[i], tol ); } // destroy filter object iirfilt_rrrf_destroy(q); }
// // 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); }
// destroy cpfskmod object void cpfskmod_destroy(cpfskmod _q) { // destroy pulse-shaping filter/interpolator free(_q->ht); free(_q->phase_interp); firinterp_rrrf_destroy(_q->interp); // destroy phase integrator iirfilt_rrrf_destroy(_q->integrator); // free main object memory free(_q); }
// // 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 : iir group delay, n=8 // void autotest_iir_groupdelay_n8() { // create coefficients arrays (7th-order Butterworth) float b[8]; b[ 0] = 0.00484212; b[ 1] = 0.03389481; b[ 2] = 0.10168444; b[ 3] = 0.16947407; b[ 4] = 0.16947407; b[ 5] = 0.10168444; b[ 6] = 0.03389481; b[ 7] = 0.00484212; float a[8]; a[ 0] = 1.00000000; a[ 1] = -1.38928008; a[ 2] = 1.67502367; a[ 3] = -1.05389738; a[ 4] = 0.50855154; a[ 5] = -0.14482945; a[ 6] = 0.02625222; a[ 7] = -0.00202968; 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}; // run tests float g; for (i=0; i<7; i++) { g = iir_group_delay(b, 8, a, 8, fc[i]); CONTEND_DELTA( g, g0[i], tol ); } // // test with iir filter (tf) // // create filter iirfilt_rrrf filter = iirfilt_rrrf_create(b,8,a,8); // run tests again 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); }
int main(int argc, char*argv[]) { srand( time(NULL) ); // options float phase_offset = M_PI / 4.0f; // phase offset float frequency_offset = 0.3f; // frequency offset float pll_bandwidth = 0.01f; // PLL bandwidth float zeta = 1/sqrtf(2.0f); // PLL damping factor float K = 1000.0f; // PLL loop gain unsigned int n=512; // number of iterations int dopt; while ((dopt = getopt(argc,argv,"uhb:z:K:n:p:f:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'b': pll_bandwidth = atof(optarg); break; case 'z': zeta = atof(optarg); break; case 'K': K = atof(optarg); break; case 'n': n = atoi(optarg); break; case 'p': phase_offset = atof(optarg); break; case 'f': frequency_offset= atof(optarg); break; default: exit(1); } } unsigned int d=n/32; // print every "d" lines // validate input if (pll_bandwidth <= 0.0f) { fprintf(stderr,"error: bandwidth must be greater than 0\n"); exit(1); } else if (zeta <= 0.0f) { fprintf(stderr,"error: damping factor must be greater than 0\n"); exit(1); } else if (K <= 0.0f) { fprintf(stderr,"error: loop gain must be greater than 0\n"); exit(1); } // data arrays float complex x[n]; // input complex sinusoid float complex y[n]; // output complex sinusoid float phase_error[n]; // output phase error // generate PLL filter float b[3]; float a[3]; iirdes_pll_active_lag(pll_bandwidth, zeta, K, b, a); iirfilt_rrrf pll = iirfilt_rrrf_create(b,3,a,3); iirfilt_rrrf_print(pll); unsigned int i; float phi; for (i=0; i<n; i++) { phi = phase_offset + i*frequency_offset; x[i] = cexpf(_Complex_I*phi); } // run loop float theta = 0.0f; y[0] = 1.0f; for (i=0; i<n; i++) { // generate complex sinusoid y[i] = cexpf(_Complex_I*theta); // compute phase error phase_error[i] = cargf(x[i]*conjf(y[i])); // update pll iirfilt_rrrf_execute(pll, phase_error[i], &theta); // print phase error if ((i)%d == 0 || i==n-1 || i==0) printf("%4u : phase error = %12.8f\n", i, phase_error[i]); } // destroy filter object iirfilt_rrrf_destroy(pll); // write output file FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"n = %u;\n", n); fprintf(fid,"x = zeros(1,n);\n"); fprintf(fid,"y = zeros(1,n);\n"); for (i=0; i<n; i++) { fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i])); fprintf(fid,"y(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i])); fprintf(fid,"e(%4u) = %12.4e;\n", i+1, phase_error[i]); } fprintf(fid,"t=0:(n-1);\n"); fprintf(fid,"figure;\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(t,real(x),t,real(y));\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('real');\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(t,imag(x),t,imag(y));\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('imag');\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(t,e);\n"); fprintf(fid,"xlabel('time');\n"); fprintf(fid,"ylabel('phase error');\n"); fprintf(fid,"grid on;\n"); fclose(fid); printf("results written to %s.\n",OUTPUT_FILENAME); printf("done.\n"); return 0; }
int main(int argc, char*argv[]) { // options float mod_index = 0.1f; // modulation index (bandwidth) float fc = 0.10f; // AM carrier liquid_ampmodem_type type = LIQUID_AMPMODEM_DSB; int suppressed_carrier = 0; // suppress the carrier? unsigned int num_samples = 201; // number of samples float SNRdB = 60.0f; // signal-to-noise ratio [dB] // derived values unsigned int nfft = 1024; // create mod/demod objects ampmodem mod = ampmodem_create(mod_index, fc, type, suppressed_carrier); ampmodem demod = ampmodem_create(mod_index, fc, type, suppressed_carrier); ampmodem_print(mod); unsigned int i; float x[num_samples]; float complex y[num_samples]; float z[num_samples]; #if 0 // generate input data: windowed sinusoid float f_audio = 0.04179f; // input sine frequency for (i=0; i<num_samples; i++) { x[i] = sinf(2*M_PI*i*f_audio) + 0.5f*sinf(2*M_PI*i*f_audio*1.8f); x[i] *= 0.7f*hamming(i,num_samples); } #else // generate un-modulated input signal (filtered noise) float fc_audio = 0.07f; float f0_audio = 0.10f; iirfilt_rrrf f = iirfilt_rrrf_create_prototype(LIQUID_IIRDES_BUTTER, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, 6, fc_audio, f0_audio, 1.0f, 1.0f); // push noise through filter for (i=0; i<100; i++) iirfilt_rrrf_execute(f, 1.5f*randnf(), &x[0]); // generate filtered/windowed output for (i=0; i<num_samples; i++) { iirfilt_rrrf_execute(f, 1.5f*randnf(), &x[i]); x[i] *= hamming(i,num_samples); } iirfilt_rrrf_destroy(f); #endif // modulate signal for (i=0; i<num_samples; i++) ampmodem_modulate(mod, x[i], &y[i]); // add noise float nstd = powf(10.0f,-SNRdB/20.0f); for (i=0; i<num_samples; i++) cawgn(&y[i], nstd); // demodulate signal for (i=0; i<num_samples; i++) ampmodem_demodulate(demod, y[i], &z[i]); // destroy objects ampmodem_destroy(mod); ampmodem_destroy(demod); // compute power spectral density float complex Y[nfft]; liquid_doc_psdwindow wtype = LIQUID_DOC_PSDWINDOW_HANN; int normalize = 1; liquid_doc_compute_psdcf(y, num_samples, Y, nfft, wtype, normalize); // // export output files // FILE * fid; // time-domain plot fid = fopen(OUTPUT_FILENAME_TIME,"w"); if (!fid) { fprintf(stderr,"error: %s, could not open '%s' for writing\n", argv[0], OUTPUT_FILENAME_TIME); exit(1); } fprintf(fid,"# %s: auto-generated file\n\n", OUTPUT_FILENAME_TIME); fprintf(fid,"reset\n"); fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n"); fprintf(fid,"set xrange [0:%u];\n",num_samples-1); fprintf(fid,"set yrange [-1.2:1.2]\n"); fprintf(fid,"set size ratio 0.3\n"); fprintf(fid,"set xlabel 'Sample Index'\n"); fprintf(fid,"set key top right nobox\n"); fprintf(fid,"set ytics -5,0.5,5\n"); fprintf(fid,"set grid xtics ytics\n"); fprintf(fid,"set pointsize 0.6\n"); fprintf(fid,"set grid linetype 1 linecolor rgb '%s' lw 1\n", LIQUID_DOC_COLOR_GRID); fprintf(fid,"set multiplot layout 2,1 scale 1.0,1.0\n"); fprintf(fid,"# input/demodulated signals\n"); fprintf(fid,"set ylabel 'input/output signal'\n"); fprintf(fid,"plot '-' using 1:2 with lines linetype 1 linewidth 2 linecolor rgb '%s' title 'input',\\\n",LIQUID_DOC_COLOR_RED); fprintf(fid," '-' using 1:2 with lines linetype 1 linecolor rgb '%s' title 'demodulated'\n",LIQUID_DOC_COLOR_GRAY); for (i=0; i<num_samples; i++) fprintf(fid,"%12u %12.4e\n", i, x[i]); fprintf(fid,"e\n"); for (i=0; i<num_samples; i++) fprintf(fid,"%12u %12.4e\n", i, z[i]); fprintf(fid,"e\n"); fprintf(fid,"# demodulated signals\n"); fprintf(fid,"set ylabel 'modulated signal'\n"); fprintf(fid,"plot '-' using 1:2 with lines linetype 1 linewidth 1 linecolor rgb '%s' title 'real',\\\n",LIQUID_DOC_COLOR_BLUE); fprintf(fid," '-' using 1:2 with lines linetype 1 linewidth 1 linecolor rgb '%s' title 'imag',\\\n",LIQUID_DOC_COLOR_GREEN); fprintf(fid," '-' using 1:2 with lines linetype 0 linewidth 2 linecolor rgb '#222222' notitle,\\\n"); fprintf(fid," '-' using 1:2 with lines linetype 0 linewidth 2 linecolor rgb '#222222' notitle\n"); for (i=0; i<num_samples; i++) fprintf(fid,"%12u %12.4e\n", i, crealf(y[i])); fprintf(fid,"e\n"); for (i=0; i<num_samples; i++) fprintf(fid,"%12u %12.4e\n", i, cimagf(y[i])); fprintf(fid,"e\n"); for (i=0; i<num_samples; i++) fprintf(fid,"%12u %12.4e\n", i, cabsf(y[i])); fprintf(fid,"e\n"); for (i=0; i<num_samples; i++) fprintf(fid,"%12u %12.4e\n", i, -cabsf(y[i])); fprintf(fid,"e\n"); fclose(fid); printf("results written to '%s\n", OUTPUT_FILENAME_TIME); // frequency-domain plot fid = fopen(OUTPUT_FILENAME_FREQ,"w"); if (!fid) { fprintf(stderr,"error: %s, could not open '%s' for writing\n", argv[0], OUTPUT_FILENAME_FREQ); exit(1); } fprintf(fid,"# %s: auto-generated file\n\n", OUTPUT_FILENAME_FREQ); fprintf(fid,"reset\n"); fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n"); fprintf(fid,"set xrange [-0.5:0.5];\n"); fprintf(fid,"set yrange [-100:10]\n"); fprintf(fid,"set size ratio 0.6\n"); fprintf(fid,"set xlabel 'Normalized Frequency'\n"); fprintf(fid,"set ylabel 'Power Spectral Density [dB]'\n"); fprintf(fid,"set nokey\n"); fprintf(fid,"set xtics -0.5,0.1,0.5\n"); fprintf(fid,"set ytics -200,20,200\n"); fprintf(fid,"set grid xtics ytics\n"); fprintf(fid,"set grid linetype 1 linecolor rgb '%s' lw 1\n", LIQUID_DOC_COLOR_GRID); fprintf(fid,"# spectrum\n"); fprintf(fid,"set style fill solid 0.1\n"); fprintf(fid,"plot '-' using 1:2 with filledcurves above y1=-200 linetype 1 linewidth 3 linecolor rgb '%s' title 'input'\n",LIQUID_DOC_COLOR_PURPLE); for (i=0; i<nfft; i++) fprintf(fid,"%12.8f %12.4e\n", (float)i/(float)nfft - 0.5f, 20*log10f(cabsf(Y[(i+nfft/2)%nfft]))); fprintf(fid,"e\n"); fclose(fid); printf("results written to '%s\n", OUTPUT_FILENAME_FREQ); return 0; }
int main(int argc, char*argv[]) { // options unsigned int k = 8; // filter samples/symbol unsigned int bps= 1; // number of bits/symbol float h = 0.5f; // modulation index (h=1/2 for MSK) unsigned int num_data_symbols = 20; // number of data symbols float SNRdB = 80.0f; // signal-to-noise ratio [dB] float cfo = 0.0f; // carrier frequency offset float cpo = 0.0f; // carrier phase offset float tau = 0.0f; // fractional symbol offset enum { TXFILT_SQUARE=0, TXFILT_RCOS_FULL, TXFILT_RCOS_HALF, TXFILT_GMSK, } tx_filter_type = TXFILT_SQUARE; float gmsk_bt = 0.35f; // GMSK bandwidth-time factor int dopt; while ((dopt = getopt(argc,argv,"ht:k:b:H:B:n:s:F:P:T:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 't': if (strcmp(optarg,"square")==0) { tx_filter_type = TXFILT_SQUARE; } else if (strcmp(optarg,"rcos-full")==0) { tx_filter_type = TXFILT_RCOS_FULL; } else if (strcmp(optarg,"rcos-half")==0) { tx_filter_type = TXFILT_RCOS_HALF; } else if (strcmp(optarg,"gmsk")==0) { tx_filter_type = TXFILT_GMSK; } else { fprintf(stderr,"error: %s, unknown filter type '%s'\n", argv[0], optarg); exit(1); } break; case 'k': k = atoi(optarg); break; case 'b': bps = atoi(optarg); break; case 'H': h = atof(optarg); break; case 'B': gmsk_bt = atof(optarg); break; case 'n': num_data_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'F': cfo = atof(optarg); break; case 'P': cpo = atof(optarg); break; case 'T': tau = atof(optarg); break; default: exit(1); } } unsigned int i; // derived values unsigned int num_symbols = num_data_symbols; unsigned int num_samples = k*num_symbols; unsigned int M = 1 << bps; // constellation size float nstd = powf(10.0f, -SNRdB/20.0f); // arrays unsigned char sym_in[num_symbols]; // input symbols float phi[num_samples]; // transmitted phase float complex x[num_samples]; // transmitted signal float complex y[num_samples]; // received signal float complex z[num_samples]; // output... //unsigned char sym_out[num_symbols]; // output symbols unsigned int ht_len = 0; unsigned int tx_delay = 0; float * ht = NULL; switch (tx_filter_type) { case TXFILT_SQUARE: // regular MSK ht_len = k; tx_delay = 1; ht = (float*) malloc(ht_len *sizeof(float)); for (i=0; i<ht_len; i++) ht[i] = h * M_PI / (float)k; break; case TXFILT_RCOS_FULL: // full-response raised-cosine pulse ht_len = k; tx_delay = 1; ht = (float*) malloc(ht_len *sizeof(float)); for (i=0; i<ht_len; i++) ht[i] = h * M_PI / (float)k * (1.0f - cosf(2.0f*M_PI*i/(float)ht_len)); break; case TXFILT_RCOS_HALF: // partial-response raised-cosine pulse ht_len = 3*k; tx_delay = 2; ht = (float*) malloc(ht_len *sizeof(float)); for (i=0; i<ht_len; i++) ht[i] = 0.0f; for (i=0; i<2*k; i++) ht[i+k/2] = h * 0.5f * M_PI / (float)k * (1.0f - cosf(2.0f*M_PI*i/(float)(2*k))); break; case TXFILT_GMSK: ht_len = 2*k*3+1+k; tx_delay = 4; ht = (float*) malloc(ht_len *sizeof(float)); for (i=0; i<ht_len; i++) ht[i] = 0.0f; liquid_firdes_gmsktx(k,3,gmsk_bt,0.0f,&ht[k/2]); for (i=0; i<ht_len; i++) ht[i] *= h * 2.0f / (float)k; break; default: fprintf(stderr,"error: %s, invalid tx filter type\n", argv[0]); exit(1); } for (i=0; i<ht_len; i++) printf("ht(%3u) = %12.8f;\n", i+1, ht[i]); firinterp_rrrf interp_tx = firinterp_rrrf_create(k, ht, ht_len); // generate symbols and interpolate // phase-accumulating filter (trapezoidal integrator) float b[2] = {0.5f, 0.5f}; if (tx_filter_type == TXFILT_SQUARE) { // square filter: rectangular integration with one sample of delay b[0] = 0.0f; b[1] = 1.0f; } float a[2] = {1.0f, -1.0f}; iirfilt_rrrf integrator = iirfilt_rrrf_create(b,2,a,2); float theta = 0.0f; for (i=0; i<num_symbols; i++) { sym_in[i] = rand() % M; float v = 2.0f*sym_in[i] - (float)(M-1); // +/-1, +/-3, ... +/-(M-1) firinterp_rrrf_execute(interp_tx, v, &phi[k*i]); // accumulate phase unsigned int j; for (j=0; j<k; j++) { iirfilt_rrrf_execute(integrator, phi[i*k+j], &theta); x[i*k+j] = cexpf(_Complex_I*theta); } } iirfilt_rrrf_destroy(integrator); // push through channel for (i=0; i<num_samples; i++) { // add carrier frequency/phase offset y[i] = x[i]*cexpf(_Complex_I*(cfo*i + cpo)); // add noise y[i] += nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2; } // create decimator unsigned int m = 3; float bw = 0.0f; float beta = 0.0f; firfilt_crcf decim_rx = NULL; switch (tx_filter_type) { case TXFILT_SQUARE: //bw = 0.9f / (float)k; bw = 0.4f; decim_rx = firfilt_crcf_create_kaiser(2*k*m+1, bw, 60.0f, 0.0f); firfilt_crcf_set_scale(decim_rx, 2.0f * bw); break; case TXFILT_RCOS_FULL: if (M==2) { decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k,m,0.5f,0); firfilt_crcf_set_scale(decim_rx, 1.33f / (float)k); } else { decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k/2,2*m,0.9f,0); firfilt_crcf_set_scale(decim_rx, 3.25f / (float)k); } break; case TXFILT_RCOS_HALF: if (M==2) { decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k,m,0.3f,0); firfilt_crcf_set_scale(decim_rx, 1.10f / (float)k); } else { decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k/2,2*m,0.27f,0); firfilt_crcf_set_scale(decim_rx, 2.90f / (float)k); } break; case TXFILT_GMSK: bw = 0.5f / (float)k; // TODO: figure out beta value here beta = (M == 2) ? 0.8*gmsk_bt : 1.0*gmsk_bt; decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k,m,beta,0); firfilt_crcf_set_scale(decim_rx, 2.0f * bw); break; default: fprintf(stderr,"error: %s, invalid tx filter type\n", argv[0]); exit(1); } printf("bw = %f\n", bw); // run receiver unsigned int n=0; unsigned int num_errors = 0; unsigned int num_symbols_checked = 0; float complex z_prime = 0.0f; for (i=0; i<num_samples; i++) { // push through filter firfilt_crcf_push(decim_rx, y[i]); firfilt_crcf_execute(decim_rx, &z[i]); // decimate output if ( (i%k)==0 ) { // compute instantaneous frequency scaled by modulation index float phi_hat = cargf(conjf(z_prime) * z[i]) / (h * M_PI); // estimate transmitted symbol float v = (phi_hat + (M-1.0))*0.5f; unsigned int sym_out = ((int) roundf(v)) % M; // save current point z_prime = z[i]; // print result to screen printf("%3u : %12.8f + j%12.8f, <f=%8.4f : %8.4f> (%1u)", n, crealf(z[i]), cimagf(z[i]), phi_hat, v, sym_out); if (n >= m+tx_delay) { num_errors += (sym_out == sym_in[n-m-tx_delay]) ? 0 : 1; num_symbols_checked++; printf(" (%1u)\n", sym_in[n-m-tx_delay]); } else { printf("\n"); } n++; } } // print number of errors printf("errors : %3u / %3u\n", num_errors, num_symbols_checked); // destroy objects firinterp_rrrf_destroy(interp_tx); firfilt_crcf_destroy(decim_rx); // compute power spectral density of transmitted signal unsigned int nfft = 1024; float psd[nfft]; spgramcf periodogram = spgramcf_create_kaiser(nfft, nfft/2, 8.0f); spgramcf_estimate_psd(periodogram, y, num_samples, psd); spgramcf_destroy(periodogram); // // export results // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); fprintf(fid,"k = %u;\n", k); fprintf(fid,"h = %f;\n", h); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"num_samples = %u;\n", num_samples); fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"delay = %u; %% receive filter delay\n", tx_delay); fprintf(fid,"x = zeros(1,num_samples);\n"); fprintf(fid,"y = zeros(1,num_samples);\n"); fprintf(fid,"z = zeros(1,num_samples);\n"); fprintf(fid,"phi = zeros(1,num_samples);\n"); for (i=0; i<num_samples; i++) { fprintf(fid,"x(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(x[i]), cimagf(x[i])); fprintf(fid,"y(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]), cimagf(y[i])); fprintf(fid,"z(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(z[i]), cimagf(z[i])); fprintf(fid,"phi(%4u) = %12.8f;\n", i+1, phi[i]); } // save PSD fprintf(fid,"psd = zeros(1,nfft);\n"); for (i=0; i<nfft; i++) fprintf(fid,"psd(%4u) = %12.8f;\n", i+1, psd[i]); fprintf(fid,"t=[0:(num_samples-1)]/k;\n"); fprintf(fid,"i = 1:k:num_samples;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"subplot(3,4,1:3);\n"); fprintf(fid," plot(t,real(x),'-', t(i),real(x(i)),'bs','MarkerSize',4,...\n"); fprintf(fid," t,imag(x),'-', t(i),imag(x(i)),'gs','MarkerSize',4);\n"); fprintf(fid," axis([0 num_symbols -1.2 1.2]);\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('x(t)');\n"); fprintf(fid," grid on;\n"); fprintf(fid,"subplot(3,4,5:7);\n"); fprintf(fid," plot(t-delay,real(z),'-', t(i)-delay,real(z(i)),'bs','MarkerSize',4,...\n"); fprintf(fid," t-delay,imag(z),'-', t(i)-delay,imag(z(i)),'gs','MarkerSize',4);\n"); fprintf(fid," axis([0 num_symbols -1.2 1.2]);\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('\"matched\" filter output');\n"); fprintf(fid," grid on;\n"); // plot I/Q constellations fprintf(fid,"subplot(3,4,4);\n"); fprintf(fid," plot(real(y),imag(y),'-',real(y(i)),imag(y(i)),'rs','MarkerSize',3);\n"); fprintf(fid," xlabel('I');\n"); fprintf(fid," ylabel('Q');\n"); fprintf(fid," axis([-1 1 -1 1]*1.2);\n"); fprintf(fid," axis square;\n"); fprintf(fid," grid on;\n"); fprintf(fid,"subplot(3,4,8);\n"); fprintf(fid," plot(real(z),imag(z),'-',real(z(i)),imag(z(i)),'rs','MarkerSize',3);\n"); fprintf(fid," xlabel('I');\n"); fprintf(fid," ylabel('Q');\n"); fprintf(fid," axis([-1 1 -1 1]*1.2);\n"); fprintf(fid," axis square;\n"); fprintf(fid," grid on;\n"); // plot PSD fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"subplot(3,4,9:12);\n"); fprintf(fid," plot(f,psd,'LineWidth',1.5);\n"); fprintf(fid," axis([-0.5 0.5 -40 20]);\n"); fprintf(fid," xlabel('Normalized Frequency [f/F_s]');\n"); fprintf(fid," ylabel('PSD [dB]');\n"); fprintf(fid," grid on;\n"); #if 0 fprintf(fid,"figure;\n"); fprintf(fid," %% compute instantaneous received frequency\n"); fprintf(fid," freq_rx = arg( conj(z(:)) .* circshift(z(:),-1) )';\n"); fprintf(fid," freq_rx(1:(k*delay)) = 0;\n"); fprintf(fid," freq_rx(end) = 0;\n"); fprintf(fid," %% compute instantaneous tx/rx phase\n"); if (tx_filter_type == TXFILT_SQUARE) { fprintf(fid," theta_tx = filter([0 1],[1 -1],phi)/(h*pi);\n"); fprintf(fid," theta_rx = filter([0 1],[1 -1],freq_rx)/(h*pi);\n"); } else { fprintf(fid," theta_tx = filter([0.5 0.5],[1 -1],phi)/(h*pi);\n"); fprintf(fid," theta_rx = filter([0.5 0.5],[1 -1],freq_rx)/(h*pi);\n"); } fprintf(fid," %% plot instantaneous tx/rx phase\n"); fprintf(fid," plot(t, theta_tx,'-b', t(i), theta_tx(i),'sb',...\n"); fprintf(fid," t-delay,theta_rx,'-r', t(i)-delay,theta_rx(i),'sr');\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('instantaneous phase/(h \\pi)');\n"); fprintf(fid," legend('transmitted','syms','received/filtered','syms','location','northwest');\n"); fprintf(fid," grid on;\n"); #else // plot filter response fprintf(fid,"ht_len = %u;\n", ht_len); fprintf(fid,"ht = zeros(1,ht_len);\n"); for (i=0; i<ht_len; i++) fprintf(fid,"ht(%4u) = %12.8f;\n", i+1, ht[i]); fprintf(fid,"gt1 = filter([0.5 0.5],[1 -1],ht) / (pi*h);\n"); fprintf(fid,"gt2 = filter([0.0 1.0],[1 -1],ht) / (pi*h);\n"); fprintf(fid,"tfilt = [0:(ht_len-1)]/k - delay + 0.5;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(tfilt,ht, '-x','MarkerSize',4,...\n"); fprintf(fid," tfilt,gt1,'-x','MarkerSize',4,...\n"); fprintf(fid," tfilt,gt2,'-x','MarkerSize',4);\n"); fprintf(fid,"axis([tfilt(1) tfilt(end) -0.1 1.1]);\n"); fprintf(fid,"legend('pulse','trap. int.','rect. int.','location','northwest');\n"); fprintf(fid,"grid on;\n"); #endif fclose(fid); printf("results written to '%s'\n", OUTPUT_FILENAME); // free allocated filter memory free(ht); return 0; }
int main() { // parameters float phase_offset = 0.8f; // carrier phase offset float frequency_offset = 0.01f; // carrier frequency offset float wn = 0.05f; // pll bandwidth float zeta = 0.707f; // pll damping factor float K = 1000; // pll loop gain unsigned int n = 256; // number of samples unsigned int d = n/32; // print every "d" lines // float theta[n]; // input phase float complex x[n]; // input sinusoid float phi[n]; // output phase float complex y[n]; // output sinusoid // generate iir loop filter object iirfilt_rrrf H = iirfilt_rrrf_create_pll(wn, zeta, K); iirfilt_rrrf_print(H); unsigned int i; // generate input float t=phase_offset; float dt = frequency_offset; for (i=0; i<n; i++) { theta[i] = t; x[i] = cexpf(_Complex_I*theta[i]); t += dt; } // run loop float phi_hat=0.0f; for (i=0; i<n; i++) { y[i] = cexpf(_Complex_I*phi_hat); // compute error float e = cargf(x[i]*conjf(y[i])); if ( (i%d)==0 ) printf("e(%3u) = %12.8f;\n", i, e); // filter error iirfilt_rrrf_execute(H,e,&phi_hat); phi[i] = phi_hat; } // destroy filter iirfilt_rrrf_destroy(H); // open output file FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"clear all;\n"); fprintf(fid,"n=%u;\n",n); for (i=0; i<n; i++) { fprintf(fid,"theta(%3u) = %16.8e;\n", i+1, theta[i]); fprintf(fid," phi(%3u) = %16.8e;\n", i+1, phi[i]); } fprintf(fid,"t=0:(n-1);\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(t,theta,t,phi);\n"); fprintf(fid,"xlabel('sample index');\n"); fprintf(fid,"ylabel('phase');\n"); fclose(fid); printf("output written to %s.\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
int main() { // parameters float phase_offset = 0.8f; float frequency_offset = 0.01f; float pll_bandwidth = 0.05f; float pll_damping_factor = 0.707f; unsigned int n=256; // number of iterations unsigned int d=n/32; // print every "d" lines // float theta[n]; // input phase float complex x[n]; // input sinusoid float phi[n]; // output phase float complex y[n]; // output sinusoid // generate iir loop filter(s) float a[3]; float b[3]; float wn = pll_bandwidth; float zeta = pll_damping_factor; float K = 10; // loop gain #if 0 // loop filter (active lag) float t1 = K/(wn*wn); float t2 = 2*zeta/wn - 1/K; b[0] = 2*K*(1.+t2/2.0f); b[1] = 2*K*2.; b[2] = 2*K*(1.-t2/2.0f); a[0] = 1 + t1/2.0f; a[1] = -t1; a[2] = -1 + t1/2.0f; #else // loop filter (active PI) float t1 = K/(wn*wn); float t2 = 2*zeta/wn; b[0] = 2*K*(1.+t2/2.0f); b[1] = 2*K*2.; b[2] = 2*K*(1.-t2/2.0f); a[0] = t1/2.0f; a[1] = -t1; a[2] = t1/2.0f; #endif iirfilt_rrrf H = iirfilt_rrrf_create(b,3,a,3); iirfilt_rrrf_print(H); unsigned int i; // generate input float t=phase_offset; float dt = frequency_offset; for (i=0; i<n; i++) { theta[i] = t; x[i] = cexpf(_Complex_I*theta[i]); t += dt; } // run loop float phi_hat=0.0f; for (i=0; i<n; i++) { y[i] = cexpf(_Complex_I*phi_hat); // compute error float e = cargf(x[i]*conjf(y[i])); if ( (i%d)==0 ) printf("e(%3u) = %12.8f;\n", i, e); // filter error iirfilt_rrrf_execute(H,e,&phi_hat); phi[i] = phi_hat; } // destroy filter iirfilt_rrrf_destroy(H); // open output file FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"clear all;\n"); fprintf(fid,"n=%u;\n",n); fprintf(fid,"a(1) = %16.8e;\n", a[0]); fprintf(fid,"a(2) = %16.8e;\n", a[1]); fprintf(fid,"a(3) = %16.8e;\n", a[2]); fprintf(fid,"b(1) = %16.8e;\n", b[0]); fprintf(fid,"b(2) = %16.8e;\n", b[1]); fprintf(fid,"b(3) = %16.8e;\n", b[2]); //fprintf(fid,"figure;\n"); //fprintf(fid,"freqz(b,a);\n"); for (i=0; i<n; i++) { fprintf(fid,"theta(%3u) = %16.8e;\n", i+1, theta[i]); fprintf(fid," phi(%3u) = %16.8e;\n", i+1, phi[i]); } fprintf(fid,"t=0:(n-1);\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(t,theta,t,phi);\n"); fprintf(fid,"xlabel('sample index');\n"); fprintf(fid,"ylabel('phase');\n"); fclose(fid); printf("output written to %s.\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
int main() { // options unsigned int n = 200; // input sequence length unsigned int p = 4; // prediction filter order // original filter #if 1 // autoregressive moving average filter // ./examples/iirdes_example -t butter -n3 -otf -f0.2 float b[4] = {0.01809893, 0.05429679, 0.05429679, 0.01809893}; float a[4] = {1.00000000, -1.76004195, 1.18289328, -0.27805993}; #else // autoregressive filter float b[4] = {1.0f, 0.0f, 0.0f, 0.0f}; float a[4] = {1.0f, 0.5f, 0.4f, 0.3f}; #endif // create filter object iirfilt_rrrf f = iirfilt_rrrf_create(b,4, a,4); iirfilt_rrrf_print(f); unsigned int i; // allocate memory for data arrays float x[n]; // input noise sequence float y[n]; // output filtered noise sequence float a_hat[p+1]; // lpc output float g_hat[p+1]; // lpc output // generate input noise signal for (i=0; i<n; i++) { x[i] = randnf(); //x[i] = ( (i%20) == 0 ) ? 1.0f : 0.0f; } // run filter for (i=0; i<n; i++) iirfilt_rrrf_execute(f, x[i], &y[i]); // destroy filter object iirfilt_rrrf_destroy(f); // run linear prediction algorithm liquid_lpc(y,n,p,a_hat,g_hat); // run prediction filter float a_lpc[p+1]; float b_lpc[p+1]; for (i=0; i<p+1; i++) { a_lpc[i] = (i==0) ? 1.0f : 0.0f; b_lpc[i] = (i==0) ? 0.0f : -a_hat[i]; } f = iirfilt_rrrf_create(b_lpc,p+1, a_lpc,p+1); iirfilt_rrrf_print(f); float y_hat[n]; for (i=0; i<n; i++) iirfilt_rrrf_execute(f, y[i], &y_hat[i]); iirfilt_rrrf_destroy(f); // compute prediction error float err[n]; for (i=0; i<n; i++) err[i] = y[i] - y_hat[i]; // compute autocorrelation of prediction error float lag[n]; float rxx[n]; for (i=0; i<n; i++) { lag[i] = (float)i; rxx[i] = 0.0f; unsigned int j; for (j=i; j<n; j++) rxx[i] += err[j] * err[j-i]; } float rxx0 = rxx[0]; for (i=0; i<n; i++) rxx[i] /= rxx0; // print results for (i=0; i<p+1; i++) printf(" a[%3u] = %12.8f, g[%3u] = %12.8f\n", i, a_hat[i], i, g_hat[i]); printf(" prediction rmse = %12.8f\n", sqrtf(rxx0 / n)); // // plot results to output file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"\n"); fprintf(fid,"p=%u;\n", p); fprintf(fid,"n=%u;\n",n); #if 0 fprintf(fid,"b = zeros(1,p+1);\n"); fprintf(fid,"a = zeros(1,p+1);\n"); for (i=0; i<p+1; i++) { fprintf(fid,"b(%4u) = %12.4e;\n", i+1, b_lpc[i]); fprintf(fid,"a(%4u) = %12.4e;\n", i+1, a_lpc[i]); } #endif fprintf(fid,"x = zeros(1,n);\n"); fprintf(fid,"y = zeros(1,n);\n"); fprintf(fid,"y_hat = zeros(1,n);\n"); fprintf(fid,"lag = zeros(1,n);\n"); fprintf(fid,"rxx = zeros(1,n);\n"); for (i=0; i<n; i++) { fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i])); fprintf(fid,"y(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i])); fprintf(fid,"y_hat(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(y_hat[i]), cimagf(y_hat[i])); fprintf(fid,"lag(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(lag[i]), cimagf(lag[i])); fprintf(fid,"rxx(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rxx[i]), cimagf(rxx[i])); } // plot output fprintf(fid,"t=0:(n-1);\n"); fprintf(fid,"figure;\n"); fprintf(fid," plot(t,x,'-','Color',[1 1 1]*0.5,'LineWidth',1,...\n"); fprintf(fid," t,y,'-','Color',[0 0.5 0.25],'LineWidth',2);\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('real');\n"); fprintf(fid," legend('input','filtered output',1);\n"); fprintf(fid," grid on;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"subplot(5,1,1:3);\n"); fprintf(fid," plot(t,y,t,y_hat);\n"); fprintf(fid," ylabel('signal');\n"); fprintf(fid," legend('y','lpc estimate',1);\n"); fprintf(fid," grid on;\n"); fprintf(fid,"subplot(5,1,4);\n"); fprintf(fid," plot(t,y-y_hat);\n"); fprintf(fid," ylabel('error');\n"); fprintf(fid,"subplot(5,1,5);\n"); fprintf(fid," plot(t,rxx);\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('r_{xx}(e)');\n"); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }