void SDRPostThread::initPFBChannelizer() { // std::cout << "Initializing post-process FIR polyphase filterbank channelizer with " << numChannels << " channels." << std::endl; if (channelizer) { firpfbch_crcf_destroy(channelizer); } channelizer = firpfbch_crcf_create_kaiser(LIQUID_ANALYZER, numChannels, 4, 60); chanBw = (sampleRate / numChannels); chanCenters.resize(numChannels+1); demodChannelActive.resize(numChannels+1); // std::cout << "Channel bandwidth spacing: " << (chanBw) << std::endl; }
int main() { // options unsigned int num_channels=8; // number of channels unsigned int m=2; // filter delay float As=-60; // stop-band attenuation unsigned int num_frames=25; // number of frames // create objects firpfbch_crcf c = firpfbch_crcf_create_kaiser(LIQUID_ANALYZER, num_channels, m, As); //firpfbch_crcf_print(c); FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\nclose all;\n\n"); fprintf(fid,"num_channels=%u;\n", num_channels); fprintf(fid,"num_frames=%u;\n", num_frames); fprintf(fid,"x = zeros(1,%u);\n", num_channels * num_frames); fprintf(fid,"y = zeros(%u,%u);\n", num_channels, num_frames); unsigned int i, j, n=0; float complex x[num_channels]; // time-domain input float complex y[num_channels]; // channelized output // create nco: sweeps entire range of frequencies over the evaluation interval nco_crcf nco_tx = nco_crcf_create(LIQUID_VCO); nco_crcf_set_frequency(nco_tx, 0.0f); float df = 2*M_PI/(num_channels*num_frames); printf("fr/ch:"); for (j=0; j<num_channels; j++) printf("%3u",j); printf("\n"); for (i=0; i<num_frames; i++) { // generate frame of data for (j=0; j<num_channels; j++) { nco_crcf_cexpf(nco_tx, &x[j]); nco_crcf_adjust_frequency(nco_tx, df); nco_crcf_step(nco_tx); } // execute analysis filter bank firpfbch_crcf_analyzer_execute(c, x, y); printf("%4u : ", i); for (j=0; j<num_channels; j++) { if (cabsf(y[j]) > num_channels / 4) printf(" x "); else printf(" . "); } printf("\n"); // write output to file for (j=0; j<num_channels; j++) { // frequency data fprintf(fid,"y(%4u,%4u) = %12.4e + j*%12.4e;\n", j+1, i+1, crealf(y[j]), cimagf(y[j])); // time data fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", n+1, crealf(x[j]), cimag(x[j])); n++; } } // destroy objects nco_crcf_destroy(nco_tx); firpfbch_crcf_destroy(c); // plot results fprintf(fid,"\n\n"); fprintf(fid,"figure;\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(1:length(x),real(x),1:length(x),imag(x));\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('signal');\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(20*log10(abs(y.')/num_channels));\n"); fprintf(fid," xlabel('time (decimated)');\n"); fprintf(fid," ylabel('channelized energy [dB]');\n"); fprintf(fid,"n=min(num_channels,8);\n"); fprintf(fid,"figure;\n"); fprintf(fid,"for i=1:n\n"); fprintf(fid," subplot(n,1,i);\n"); fprintf(fid," plot(1:num_frames,real(y(i,:)),1:num_frames,imag(y(i,:)));\n"); fprintf(fid," axis off;\n"); fprintf(fid," ylabel(num2str(i));\n"); fprintf(fid,"end;\n"); fclose(fid); printf("results written to %s\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
int main() { // options unsigned int num_channels = 16; // number of channels unsigned int m = 5; // filter delay float As = 60; // stop-band attenuation unsigned int num_frames = 25; // number of frames // unsigned int i; unsigned int k; // derived values unsigned int num_samples = num_frames * num_channels; // data arrays float complex x[num_channels][num_frames]; // channelized input float complex y[num_samples]; // time-domain output [size: num_samples x 1] // create narrow-band pulse unsigned int pulse_len = 17; // pulse length [samples] float bw = 0.30f; // pulse width (bandwidth) float pulse[pulse_len]; // buffer liquid_firdes_kaiser(pulse_len, bw, 50.0f, 0.0f, pulse); // generate input signal(s) int enabled[num_channels]; // signal enabled? for (i=0; i<num_channels; i++) { // pseudo-random channel enabled flag enabled[i] = ((i*37)%101)%2; if (enabled[i]) { // move pulse to input buffer for (k=0; k<num_frames; k++) x[i][k] = k < pulse_len ? bw*pulse[k] : 0.0f; } else { // channel disabled; set as nearly zero (-100 dB impulse) for (k=0; k<num_frames; k++) x[i][k] = (k == 0) ? 1e-5f : 0.0f; } } // create prototype filter unsigned int h_len = 2*num_channels*m + 1; float h[h_len]; liquid_firdes_kaiser(h_len, 0.5f/(float)num_channels, As, 0.0f, h); #if 0 // create filterbank channelizer object using internal method for filter firpfbch_crcf q = firpfbch_crcf_create_kaiser(LIQUID_SYNTHESIZER, num_channels, m, As); #else // create filterbank channelizer object using external filter coefficients firpfbch_crcf q = firpfbch_crcf_create(LIQUID_SYNTHESIZER, num_channels, 2*m, h); #endif // channelize input data float complex v[num_channels]; for (i=0; i<num_frames; i++) { // assemble input vector for (k=0; k<num_channels; k++) v[k] = x[k][i]; // execute synthesis filter bank firpfbch_crcf_synthesizer_execute(q, v, &y[i*num_channels]); } // destroy channelizer object firpfbch_crcf_destroy(q); // // export results to file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"num_channels = %u;\n", num_channels); fprintf(fid,"m = %u;\n", m); fprintf(fid,"num_frames = %u;\n", num_frames); fprintf(fid,"h_len = 2*num_channels*m+1;\n"); fprintf(fid,"num_samples = num_frames*num_channels;\n"); fprintf(fid,"h = zeros(1,h_len);\n"); fprintf(fid,"x = zeros(num_channels, num_frames);\n"); fprintf(fid,"y = zeros(1,num_samples);\n"); // save prototype filter for (i=0; i<h_len; i++) fprintf(fid," h(%6u) = %12.4e;\n", i+1, h[i]); // save channelized input signals for (i=0; i<num_frames; i++) { for (k=0; k<num_channels; k++) { float complex v = x[k][i]; fprintf(fid," x(%3u,%6u) = %12.4e + 1i*%12.4e;\n", k+1, i+1, crealf(v), cimagf(v)); } } // save output time signal for (i=0; i<num_samples; i++) fprintf(fid," y(%6u) = %12.4e + 1i*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i])); // compute the PSD of each input and plot results on a square grid fprintf(fid,"nfft = 1024;\n"); // TODO: use nextpow2 fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"n = ceil(sqrt(num_channels));\n"); fprintf(fid,"figure;\n"); fprintf(fid,"for i=1:num_channels,\n"); fprintf(fid," X = 20*log10(abs(fftshift(fft(x(i,:),nfft))));\n"); fprintf(fid," subplot(n,n,i);\n"); fprintf(fid," plot(f, X, 'Color', [0.25 0 0.25], 'LineWidth', 1.5);\n"); fprintf(fid," axis([-0.5 0.5 -120 20]);\n"); fprintf(fid," grid on;\n"); fprintf(fid," title(num2str(i-1));\n"); fprintf(fid,"end;\n"); // plot results fprintf(fid,"\n"); fprintf(fid,"H = 20*log10(abs(fftshift(fft(h/num_channels,nfft))));\n"); fprintf(fid,"Y = 20*log10(abs(fftshift(fft(y/num_channels,nfft))));\n"); fprintf(fid,"figure;\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(f, H, 'Color', [0 0.5 0.25], 'LineWidth', 2);\n"); fprintf(fid," axis([-0.5 0.5 -100 10]);\n"); fprintf(fid," grid on;\n"); fprintf(fid," xlabel('Normalized Frequency [f/F_s]');\n"); fprintf(fid," ylabel('Prototype Filter PSD');\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(f, Y, 'Color', [0 0.25 0.5], 'LineWidth', 2);\n"); fprintf(fid," axis([-0.5 0.5 -100 0]);\n"); fprintf(fid," grid on;\n"); fprintf(fid," xlabel('Normalized Frequency [f/F_s]');\n"); fprintf(fid," ylabel('Output PSD');\n"); fclose(fid); printf("results written to %s\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
int main() { // options unsigned int num_channels=4; // number of channels unsigned int p=3; // filter length (symbols) unsigned int num_symbols=6; // number of symbols // derived values unsigned int num_samples = num_channels * num_symbols; unsigned int i; unsigned int j; // generate synthesis filter // NOTE : these coefficients can be random; the purpose of this // exercise is to demonstrate mathematical equivalence unsigned int h_len = p*num_channels; float h[h_len]; for (i=0; i<h_len; i++) h[i] = randnf(); // generate analysis filter unsigned int g_len = p*num_channels; float g[g_len]; for (i=0; i<g_len; i++) g[i] = h[g_len-i-1]; // create synthesis/analysis filter objects firfilt_crcf fs = firfilt_crcf_create(h, h_len); firfilt_crcf fa = firfilt_crcf_create(g, g_len); // create synthesis/analysis filterbank channelizer objects firpfbch_crcf qs = firpfbch_crcf_create(LIQUID_SYNTHESIZER, num_channels, p, h); firpfbch_crcf qa = firpfbch_crcf_create(LIQUID_ANALYZER, num_channels, p, g); float complex x[num_samples]; // random input (noise) float complex Y0[num_symbols][num_channels]; // channelized output (filterbank) float complex Y1[num_symbols][num_channels]; // channelized output float complex z0[num_samples]; // time-domain output (filterbank) float complex z1[num_samples]; // time-domain output // generate input sequence (complex noise) for (i=0; i<num_samples; i++) x[i] = randnf() * cexpf(_Complex_I*randf()*2*M_PI); // // ANALYZERS // // // run analysis filter bank // for (i=0; i<num_symbols; i++) firpfbch_crcf_analyzer_execute(qa, &x[i*num_channels], &Y0[i][0]); // // run traditional down-converter (inefficient) // float dphi; // carrier frequency unsigned int n=0; for (i=0; i<num_channels; i++) { // reset filter firfilt_crcf_clear(fa); // set center frequency dphi = 2.0f * M_PI * (float)i / (float)num_channels; // reset symbol counter n=0; for (j=0; j<num_samples; j++) { // push down-converted sample into filter firfilt_crcf_push(fa, x[j]*cexpf(-_Complex_I*j*dphi)); // compute output at the appropriate sample time assert(n<num_symbols); if ( ((j+1)%num_channels)==0 ) { firfilt_crcf_execute(fa, &Y1[n][i]); n++; } } assert(n==num_symbols); } // // SYNTHESIZERS // // // run synthesis filter bank // for (i=0; i<num_symbols; i++) firpfbch_crcf_synthesizer_execute(qs, &Y0[i][0], &z0[i*num_channels]); // // run traditional up-converter (inefficient) // // clear output array for (i=0; i<num_samples; i++) z1[i] = 0.0f; float complex y_hat; for (i=0; i<num_channels; i++) { // reset filter firfilt_crcf_clear(fs); // set center frequency dphi = 2.0f * M_PI * (float)i / (float)num_channels; // reset input symbol counter n=0; for (j=0; j<num_samples; j++) { // interpolate sequence if ( (j%num_channels)==0 ) { assert(n<num_symbols); firfilt_crcf_push(fs, Y1[n][i]); n++; } else { firfilt_crcf_push(fs, 0); } firfilt_crcf_execute(fs, &y_hat); // accumulate up-converted sample z1[j] += y_hat * cexpf(_Complex_I*j*dphi); } assert(n==num_symbols); } // destroy objects firfilt_crcf_destroy(fs); firfilt_crcf_destroy(fa); firpfbch_crcf_destroy(qs); firpfbch_crcf_destroy(qa); // // RESULTS // // // analyzers // // print filterbank channelizer printf("\n"); printf("filterbank channelizer:\n"); for (i=0; i<num_symbols; i++) { printf("%3u: ", i); for (j=0; j<num_channels; j++) { printf(" %8.5f+j%8.5f, ", crealf(Y0[i][j]), cimagf(Y0[i][j])); } printf("\n"); } // print traditional channelizer printf("\n"); printf("traditional channelizer:\n"); for (i=0; i<num_symbols; i++) { printf("%3u: ", i); for (j=0; j<num_channels; j++) { printf(" %8.5f+j%8.5f, ", crealf(Y1[i][j]), cimagf(Y1[i][j])); } printf("\n"); } float mse_analyzer[num_channels]; float complex d; for (i=0; i<num_channels; i++) { mse_analyzer[i] = 0.0f; for (j=0; j<num_symbols; j++) { d = Y0[j][i] - Y1[j][i]; mse_analyzer[i] += crealf(d*conjf(d)); } mse_analyzer[i] /= num_symbols; } printf("\n"); printf("rmse: "); for (i=0; i<num_channels; i++) printf("%12.4e ", sqrt(mse_analyzer[i])); printf("\n"); // // synthesizers // printf("\n"); printf("output: filterbank: traditional:\n"); for (i=0; i<num_samples; i++) { printf("%3u: %10.5f+%10.5fj %10.5f+%10.5fj\n", i, crealf(z0[i]), cimagf(z0[i]), crealf(z1[i]), cimagf(z1[i])); } float mse_synthesizer = 0.0f; for (i=0; i<num_samples; i++) { d = z0[i] - z1[i]; mse_synthesizer += crealf(d*conjf(d)); } mse_synthesizer /= num_samples; printf("\n"); printf("rmse: %12.4e\n", sqrtf(mse_synthesizer)); // // EXPORT DATA TO FILE // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"num_channels=%u;\n", num_channels); fprintf(fid,"num_symbols=%u;\n", num_symbols); fprintf(fid,"num_samples = num_channels*num_symbols;\n"); fprintf(fid,"x = zeros(1,num_samples);\n"); fprintf(fid,"y0 = zeros(num_symbols,num_channels);\n"); fprintf(fid,"y1 = zeros(num_symbols,num_channels);\n"); fprintf(fid,"z0 = zeros(1,num_samples);\n"); fprintf(fid,"z1 = zeros(1,num_samples);\n"); // input for (i=0; i<num_samples; i++) fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimag(x[i])); // analysis for (i=0; i<num_symbols; i++) { for (j=0; j<num_channels; j++) { fprintf(fid,"y0(%4u,%4u) = %12.4e + j*%12.4e;\n", i+1, j+1, crealf(Y0[i][j]), cimag(Y0[i][j])); fprintf(fid,"y1(%4u,%4u) = %12.4e + j*%12.4e;\n", i+1, j+1, crealf(Y1[i][j]), cimag(Y1[i][j])); } } // synthesis for (i=0; i<num_samples; i++) { fprintf(fid,"z0(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(z0[i]), cimag(z0[i])); fprintf(fid,"z1(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(z1[i]), cimag(z1[i])); } fprintf(fid,"z0 = z0 / num_channels;\n"); fprintf(fid,"z1 = z1 / num_channels;\n"); // plot results fprintf(fid,"\n\n"); fprintf(fid,"ts = 0:(num_symbols-1);\n"); fprintf(fid,"for i=1:num_channels,\n"); fprintf(fid,"figure;\n"); fprintf(fid,"title(['channel ' num2str(i)]);\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(ts,real(y0(:,i)),'-x', ts,real(y1(:,i)),'s');\n"); //fprintf(fid," axis([0 (num_symbols-1) -2 2]);\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(ts,imag(y0(:,i)),'-x', ts,imag(y1(:,i)),'s');\n"); //fprintf(fid," axis([0 (num_symbols-1) -2 2]);\n"); fprintf(fid,"end;\n"); fprintf(fid,"t = 0:(num_samples-1);\n"); fprintf(fid,"figure;\n"); fprintf(fid,"title('composite');\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(t,real(z0),'-x', t,real(z1),'s');\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(t,imag(z0),'-x', t,imag(z1),'s');\n"); fclose(fid); printf("results written to '%s'\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
PfbSynthesizerComponent::~PfbSynthesizerComponent() { firpfbch_crcf_destroy(channelizer); }
int main() { // options unsigned int num_channels=6; // must be even number unsigned int num_symbols=32; // number of symbols unsigned int m=3; // filter delay (symbols) float beta = 0.9f; // filter excess bandwidth factor int ftype = LIQUID_RNYQUIST_ARKAISER; // number of frames (compensate for filter delay) unsigned int num_frames = num_symbols + 2*m; unsigned int num_samples = num_channels * num_frames; // create synthesizer/analyzer objects firpfbch_crcf cs0 = firpfbch_crcf_create_rnyquist(LIQUID_SYNTHESIZER, num_channels, m, beta, ftype); firpfbch_crcf cs1 = firpfbch_crcf_create_rnyquist(LIQUID_SYNTHESIZER, num_channels, m, beta, ftype); firpfbch_crcf ca0 = firpfbch_crcf_create_rnyquist(LIQUID_ANALYZER, num_channels, m, beta, ftype); firpfbch_crcf ca1 = firpfbch_crcf_create_rnyquist(LIQUID_ANALYZER, num_channels, m, beta, ftype); FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\nclose all;\n\n"); fprintf(fid,"num_channels=%u;\n", num_channels); fprintf(fid,"num_symbols=%u;\n", num_symbols); fprintf(fid,"num_samples=%u;\n", num_samples); fprintf(fid,"X = zeros(%u,%u);\n", num_channels, num_frames); fprintf(fid,"y = zeros(1,%u);\n", num_samples); fprintf(fid,"Y = zeros(%u,%u);\n", num_channels, num_frames); unsigned int i, j, n=0; unsigned int k2 = num_channels/2; float complex X[num_channels]; // channelized symbols float complex y[num_channels]; // interpolated time-domain samples float complex Y[num_channels]; // received symbols // temporary buffers float complex X0[num_channels]; float complex X1[num_channels]; float complex y0[num_channels]; float complex y1[num_channels]; float complex y1_prime[num_channels]; for (i=0; i<num_channels; i++) y1_prime[i] = 0.0f; float complex Z0[num_channels]; float complex Z1[num_channels]; float complex z0[num_channels]; float complex z1[num_channels]; //float complex z0_prime[num_channels]; //float complex z1_prime[num_channels]; for (i=0; i<num_channels; i++) z0[i] = 0.0f; for (i=0; i<num_channels; i++) z1[i] = 0.0f; for (i=0; i<num_frames; i++) { // generate frame data (random QPSK symbols) for (j=0; j<num_channels; j++) { X[j] = (rand()%2 ? 1.0f : -1.0f) + (rand()%2 ? 1.0f : -1.0f)*_Complex_I; } // execute synthesyzer //ofdmoqam_execute(cs, X, y); for (j=0; j<num_channels; j+=2) { // even channels X0[j+0] = crealf(X[j+0]); X1[j+0] = cimagf(X[j+0])*_Complex_I; // odd channels X0[j+1] = cimagf(X[j+1])*_Complex_I; X1[j+1] = crealf(X[j+1]); } /* for (j=0; j<num_channels; j++) printf("X(%3u) = %12.8f + j*%12.8f\n", j, crealf(X[j]), cimagf(X[j])); printf("\n"); for (j=0; j<num_channels; j++) printf("X0(%3u) = %12.8f + j*%12.8f\n", j, crealf(X0[j]), cimagf(X0[j])); printf("\n"); */ firpfbch_crcf_synthesizer_execute(cs0, X0, y0); firpfbch_crcf_synthesizer_execute(cs1, X1, y1); // delay lower branch by half a symbol: // copy first half of symbol from lower branch memmove(&y1_prime[k2], &y1[0], k2*sizeof(float complex)); // add symbols for (j=0; j<num_channels; j++) y[j] = y0[j] + y1_prime[j]; // finish delay // copy last half of symbol from lower branch memmove(&y1_prime[0], &y1[k2], k2*sizeof(float complex)); // channel // execute analyzer //ofdmoqam_execute(ca, y, Y); // delay lower branch by half a symbol // copy first half of symbol to lower branch memmove(&z1[k2], &y[0], k2*sizeof(float complex)); // run analyzer firpfbch_crcf_analyzer_execute(ca0, z0, Z0); firpfbch_crcf_analyzer_execute(ca1, z1, Z1); // finish delay // copy last half of symbol to lower branch memmove(&z1[0], &y[k2], k2*sizeof(float complex)); // copy full symbol on upper branch memmove(z0,y,num_channels*sizeof(float complex)); for (j=0; j<num_channels; j+=2) { // even channels Y[j+0] = crealf(Z0[j+0]) + cimagf(Z1[j+0])*_Complex_I; // odd channels Y[j+1] = cimagf(Z0[j+1])*_Complex_I + crealf(Z1[j+1]); } // write output to file for (j=0; j<num_channels; j++) { // frequency data fprintf(fid,"X(%4u,%4u) = %12.4e + j*%12.4e;\n", j+1, i+1, crealf(X[j]), cimagf(X[j])); // time data fprintf(fid,"y(%4u) = %12.4e + j*%12.4e;\n", n+1, crealf(y[j]), cimag(y[j])); // received data fprintf(fid,"Y(%4u,%4u) = %12.4e + j*%12.4e;\n", j+1, i+1, crealf(Y[j]), cimagf(Y[j])); n++; } } // print results fprintf(fid,"\n\n"); fprintf(fid,"s0 = 1:%u;\n", num_symbols); fprintf(fid,"s1 = %u:%u;\n", 2*m+1, num_symbols + 2*m); fprintf(fid,"Y = Y / num_channels; %% normalize by fft size\n"); fprintf(fid,"for i=1:min(6,num_channels),\n"); fprintf(fid," figure;\n"); fprintf(fid," subplot(2,1,1);\n"); fprintf(fid," plot(1:num_symbols,real(X(i,s0)),'-x',1:num_symbols,real(Y(i,s1)),'-x');\n"); fprintf(fid," ylabel('Re');\n"); fprintf(fid," title(['channel ' num2str(i-1)]);\n"); fprintf(fid," subplot(2,1,2);\n"); fprintf(fid," plot(1:num_symbols,imag(X(i,s0)),'-x',1:num_symbols,imag(Y(i,s1)),'-x');\n"); fprintf(fid," ylabel('Im');\n"); fprintf(fid," pause(0.2);\n"); fprintf(fid,"end;\n"); // plot time-domain output fprintf(fid,"\n\n"); fprintf(fid,"t = 1:num_samples;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(t,real(y),'-', t,imag(y),'-');\n"); fprintf(fid,"xlabel('time');\n"); fprintf(fid,"ylabel('time series');\n"); fclose(fid); printf("results written to %s\n", OUTPUT_FILENAME); // destroy objects firpfbch_crcf_destroy(cs0); firpfbch_crcf_destroy(cs1); firpfbch_crcf_destroy(ca0); firpfbch_crcf_destroy(ca1); printf("done.\n"); return 0; }
int main() { // options unsigned int num_channels=8; // number of channels unsigned int m=4; // filter delay float As=60; // stop-band attenuation unsigned int num_frames=25; // number of frames // unsigned int i; unsigned int k; // derived values unsigned int num_samples = num_frames * num_channels; // data arrays float complex x[num_samples]; // time-domain input [size: num_samples x 1 ] float complex y[num_samples]; // channelized output [size: num_channels x num_frames] // initialize input with zeros for (i=0; i<num_samples; i++) x[i] = 0.0f; // generate input signal(s) unsigned int num_signals = 4; float fc[4] = {0.0f, 0.25f, 0.375f, -0.375f}; // center frequencies float bw[4] = {0.035f, 0.035f, 0.035f, 0.035f}; // bandwidths unsigned int pulse_len = 137; float pulse[pulse_len]; for (i=0; i<num_signals; i++) { // create pulse liquid_firdes_kaiser(pulse_len, bw[i], 50.0f, 0.0f, pulse); // add pulse to input signal with carrier offset for (k=0; k<pulse_len; k++) x[k] += pulse[k] * cexpf(_Complex_I*2*M_PI*fc[i]*k) * bw[i]; } // create prototype filter unsigned int h_len = 2*num_channels*m + 1; float h[h_len]; liquid_firdes_kaiser(h_len, 0.5f/(float)num_channels, As, 0.0f, h); #if 0 // create filterbank channelizer object using internal method for filter firpfbch_crcf q = firpfbch_crcf_create_kaiser(LIQUID_ANALYZER, num_channels, m, As); #else // create filterbank channelizer object using external filter coefficients firpfbch_crcf q = firpfbch_crcf_create(LIQUID_ANALYZER, num_channels, 2*m, h); #endif // channelize input data for (i=0; i<num_frames; i++) { // execute analysis filter bank firpfbch_crcf_analyzer_execute(q, &x[i*num_channels], &y[i*num_channels]); } // destroy channelizer object firpfbch_crcf_destroy(q); // // export results to file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"num_channels = %u;\n", num_channels); fprintf(fid,"m = %u;\n", m); fprintf(fid,"num_frames = %u;\n", num_frames); fprintf(fid,"h_len = 2*num_channels*m+1;\n"); fprintf(fid,"num_samples = num_frames*num_channels;\n"); fprintf(fid,"h = zeros(1,h_len);\n"); fprintf(fid,"x = zeros(1,num_samples);\n"); fprintf(fid,"y = zeros(num_channels, num_frames);\n"); // save prototype filter for (i=0; i<h_len; i++) fprintf(fid," h(%6u) = %12.4e;\n", i+1, h[i]); // save input signal for (i=0; i<num_samples; i++) fprintf(fid," x(%6u) = %12.4e + 1i*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i])); // save channelized output signals for (i=0; i<num_frames; i++) { for (k=0; k<num_channels; k++) { float complex v = y[i*num_channels + k]; fprintf(fid," y(%3u,%6u) = %12.4e + 1i*%12.4e;\n", k+1, i+1, crealf(v), cimagf(v)); } } // plot results fprintf(fid,"\n"); fprintf(fid,"nfft = 1024;\n"); // TODO: use nextpow2 fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"H = 20*log10(abs(fftshift(fft(h/num_channels,nfft))));\n"); fprintf(fid,"X = 20*log10(abs(fftshift(fft(x,nfft))));\n"); fprintf(fid,"figure;\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(f, H, 'Color', [0 0.5 0.25], 'LineWidth', 2);\n"); fprintf(fid," axis([-0.5 0.5 -100 10]);\n"); fprintf(fid," grid on;\n"); fprintf(fid," xlabel('Normalized Frequency [f/F_s]');\n"); fprintf(fid," ylabel('Prototype Filter PSD');\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(f, X, 'Color', [0 0.25 0.5], 'LineWidth', 2);\n"); fprintf(fid," axis([-0.5 0.5 -100 0]);\n"); fprintf(fid," grid on;\n"); fprintf(fid," xlabel('Normalized Frequency [f/F_s]');\n"); fprintf(fid," ylabel('Input PSD');\n"); // compute the PSD of each output and plot results on a square grid fprintf(fid,"n = ceil(sqrt(num_channels));\n"); fprintf(fid,"figure;\n"); fprintf(fid,"for i=1:num_channels,\n"); fprintf(fid," Y = 20*log10(abs(fftshift(fft(y(i,:),nfft))));\n"); fprintf(fid," subplot(n,n,i);\n"); fprintf(fid," plot(f, Y, 'Color', [0.25 0 0.25], 'LineWidth', 1.5);\n"); fprintf(fid," axis([-0.5 0.5 -120 20]);\n"); fprintf(fid," grid on;\n"); fprintf(fid," title(num2str(i-1));\n"); fprintf(fid,"end;\n"); fclose(fid); printf("results written to %s\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
// // AUTOTEST: validate analysis correctness // void autotest_firpfbch_crcf_analysis() { float tol = 1e-4f; // error tolerance unsigned int num_channels=4; // number of channels unsigned int p=5; // filter length (symbols) unsigned int num_symbols=12; // number of symbols // derived values unsigned int num_samples = num_channels * num_symbols; unsigned int i; unsigned int j; // generate filter // NOTE : these coefficients can be random; the purpose of this // exercise is to demonstrate mathematical equivalence unsigned int h_len = p*num_channels; float h[h_len]; for (i=0; i<h_len; i++) h[i] = randnf(); // create filterbank object firpfbch_crcf q = firpfbch_crcf_create(LIQUID_ANALYZER, num_channels, p, h); // generate filter object firfilt_crcf f = firfilt_crcf_create(h, h_len); // allocate memory for arrays float complex y[num_samples]; // time-domain input float complex Y0[num_symbols][num_channels]; // channelized output float complex Y1[num_symbols][num_channels]; // channelized output // generate input sequence (complex noise) for (i=0; i<num_samples; i++) y[i] = randnf() * cexpf(_Complex_I*randf()*2*M_PI); // // run analysis filter bank // for (i=0; i<num_symbols; i++) firpfbch_crcf_analyzer_execute(q, &y[i*num_channels], &Y0[i][0]); // // run traditional down-converter (inefficient) // float dphi; // carrier frequency unsigned int n=0; for (i=0; i<num_channels; i++) { // reset filter firfilt_crcf_clear(f); // set center frequency dphi = 2.0f * M_PI * (float)i / (float)num_channels; // reset symbol counter n=0; for (j=0; j<num_samples; j++) { // push down-converted sample into filter firfilt_crcf_push(f, y[j]*cexpf(-_Complex_I*j*dphi)); // compute output at the appropriate sample time assert(n<num_symbols); if ( ((j+1)%num_channels)==0 ) { firfilt_crcf_execute(f, &Y1[n][i]); n++; } } assert(n==num_symbols); } // destroy objects firfilt_crcf_destroy(f); firpfbch_crcf_destroy(q); if (liquid_autotest_verbose) { // print filterbank channelizer printf("\n"); printf("filterbank channelizer:\n"); for (i=0; i<num_symbols; i++) { printf("%3u: ", i); for (j=0; j<num_channels; j++) { printf(" %8.5f+j%8.5f, ", crealf(Y0[i][j]), cimagf(Y0[i][j])); } printf("\n"); } // print traditional channelizer printf("\n"); printf("traditional channelizer:\n"); for (i=0; i<num_symbols; i++) { printf("%3u: ", i); for (j=0; j<num_channels; j++) { printf(" %8.5f+j%8.5f, ", crealf(Y1[i][j]), cimagf(Y1[i][j])); } printf("\n"); } } // compare results for (i=0; i<num_symbols; i++) { for (j=0; j<num_channels; j++) { CONTEND_DELTA( crealf(Y0[i][j]), crealf(Y1[i][j]), tol ); CONTEND_DELTA( cimagf(Y0[i][j]), cimagf(Y1[i][j]), tol ); } } }