// // AUTOTEST : test half-band filterbank (analyzer) // void autotest_resamp2_analysis() { unsigned int m=5; // filter semi-length (actual length: 4*m+1) unsigned int n=37; // number of input samples float As=60.0f; // stop-band attenuation [dB] float f0 = 0.0739f; // low frequency signal float f1 = -0.1387f; // high frequency signal (+pi) float tol = 1e-3f; // error tolerance unsigned int i; // allocate memory for data arrays float complex x[2*n+2*m+1]; // input signal (with delay) float complex y0[n]; // low-pass output float complex y1[n]; // high-pass output // generate the baseband signal for (i=0; i<2*n+2*m+1; i++) x[i] = i < 2*n ? cexpf(_Complex_I*f0*i) + cexpf(_Complex_I*(M_PI+f1)*i) : 0.0f; // create/print the half-band resampler, with a specified // stopband attenuation level resamp2_crcf q = resamp2_crcf_create(m,0,As); // run half-band decimation float complex y_hat[2]; for (i=0; i<n; i++) { resamp2_crcf_analyzer_execute(q, &x[2*i], y_hat); y0[i] = y_hat[0]; y1[i] = y_hat[1]; } // clean up allocated objects resamp2_crcf_destroy(q); // validate output for (i=m; i<n-m; i++) { CONTEND_DELTA( crealf(y0[i+m]), cosf(2*f0*(i+0.5f)), tol ); CONTEND_DELTA( cimagf(y0[i+m]), sinf(2*f0*(i+0.5f)), tol ); CONTEND_DELTA( crealf(y1[i+m]), cosf(2*f1*(i+0.5f)), tol ); CONTEND_DELTA( cimagf(y1[i+m]), sinf(2*f1*(i+0.5f)), tol ); } #if 0 // debugging FILE * fid = fopen("resamp2_test.m", "w"); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); for (i=0; i<2*n; i++) fprintf(fid,"x(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i])); for (i=0; i<n; i++) { fprintf(fid,"y0(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(y0[i]), cimagf(y0[i])); fprintf(fid,"y1(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(y1[i]), cimagf(y1[i])); } // save expected values for (i=0; i<n; i++) { fprintf(fid,"z0(%3u) = %12.4e + j*%12.4e;\n", i+1, cosf(i*2*f0), sinf(i*2*f0)); fprintf(fid,"z1(%3u) = %12.4e + j*%12.4e;\n", i+1, cosf(i*2*f1), sinf(i*2*f1)); } fprintf(fid,"m = %u;\n", m); fprintf(fid,"figure;\n"); fprintf(fid,"t = 0:(length(y0)-1);\n"); //fprintf(fid,"plot(t,real(z0),t-m+0.5,real(y0));\n"); fprintf(fid,"plot(t,real(z1),t-m+0.5,real(y1));\n"); fclose(fid); printf("results written to '%s'\n","resamp2_test.m"); #endif }
int main() { unsigned int m=9; // filter semi-length unsigned int num_samples=128; // number of input samples float As=60.0f; // stop-band attenuation [dB] // derived values unsigned int h_len = 4*m+1; // half-band filter length unsigned int N = num_samples + h_len; // ensure N is even N += (N%2); unsigned int n = N/2; // arrays float complex x[N]; // input time series float complex y[n][2]; // output time series (channelized) float complex z[N]; // output time series // generate input sequence unsigned int i; for (i=0; i<N; i++) { //x[i] = randnf() * cexpf(_Complex_I*M_PI*randf()); x[i] = cexpf(_Complex_I*2*M_PI*0.072f*i) + 0.6f*cexpf(_Complex_I*2*M_PI*0.37f*i); //x[i] = cexpf(_Complex_I*2*M_PI*0.072f*i); //x[i] += 0.6*cexpf(_Complex_I*2*M_PI*0.572f*i); x[i] *= (i < num_samples) ? hamming(i,num_samples) : 0.0f; } // create/print the half-band filter with a specified // stop-band attenuation resamp2_crcf q = resamp2_crcf_create(m,0.0f,As); resamp2_crcf_print(q); // run the resampler as a two-channel analysis filterbank for (i=0; i<n; i++) resamp2_crcf_analyzer_execute(q, &x[2*i], &y[i][0]); // clear resampler resamp2_crcf_clear(q); // run the resampler as a two-channel synthesis filterbank for (i=0; i<n; i++) resamp2_crcf_synthesizer_execute(q, &y[i][0], &z[2*i]); // clean up allocated objects resamp2_crcf_destroy(q); // // export output file // FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\nclose all;\n\n"); fprintf(fid,"m = %u;\n", m); fprintf(fid,"num_samples = %u;\n", num_samples); fprintf(fid,"N = %u;\n", N); // save results to output file for (i=0; i<n; i++) { fprintf(fid,"x(%3u) = %12.4e + j*%12.4e;\n", 2*i+1, crealf(x[2*i+0]), cimagf(x[2*i+0])); fprintf(fid,"x(%3u) = %12.4e + j*%12.4e;\n", 2*i+2, crealf(x[2*i+1]), cimagf(x[2*i+1])); fprintf(fid,"y0(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i][0]), cimagf(y[i][0])); fprintf(fid,"y1(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i][1]), cimagf(y[i][1])); fprintf(fid,"z(%3u) = %12.4e + j*%12.4e;\n", 2*i+1, crealf(z[2*i+0]), cimagf(z[2*i+0])); fprintf(fid,"z(%3u) = %12.4e + j*%12.4e;\n", 2*i+2, crealf(z[2*i+1]), cimagf(z[2*i+1])); } fprintf(fid,"tx = 0:(N-1);\n"); fprintf(fid,"ty = tx(1:2:end);\n"); fprintf(fid,"tz = tx - 4*m + 1;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(tx, real(x), 'LineWidth',1,'Color',[0.50 0.50 0.50],...\n"); fprintf(fid," tz, real(z), 'LineWidth',1,'Color',[0.00 0.25 0.50]);\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('real');\n"); fprintf(fid," legend('original','reconstructed',1);"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(tx, imag(x), 'LineWidth',1,'Color',[0.50 0.50 0.50],...\n"); fprintf(fid," tz, imag(z), 'LineWidth',1,'Color',[0.00 0.50 0.25]);\n"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('imag');\n"); fprintf(fid," legend('original','reconstructed',1);"); fprintf(fid,"nfft=512;\n"); fprintf(fid,"g = 1 / sqrt( real(x*x') );\n"); fprintf(fid,"X =20*log10(abs(fftshift(fft(x*g, nfft))));\n"); fprintf(fid,"Y0=20*log10(abs(fftshift(fft(y0*g,nfft))));\n"); fprintf(fid,"Y1=20*log10(abs(fftshift(fft(y1*g,nfft))));\n"); fprintf(fid,"Z =20*log10(abs(fftshift(fft(z*g, nfft))));\n"); fprintf(fid,"f=[0:(nfft-1)]/nfft-0.5;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(f,X, 'LineWidth',2,'Color',[0.50 0.50 0.50],...\n"); fprintf(fid," f,Z, 'LineWidth',1,'Color',[0.00 0.25 0.50]);\n"); //fprintf(fid," f,Y0,'LineWidth',1,'Color',[0.00 0.25 0.50],...\n"); //fprintf(fid," f,Y1,'LineWidth',1,'Color',[0.00 0.50 0.25]);\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"xlabel('normalized frequency');\n"); fprintf(fid,"ylabel('PSD [dB]');\n"); fprintf(fid,"legend('original','reconstructed',2);"); fprintf(fid,"axis([-0.5 0.5 -80 20]);\n"); fclose(fid); printf("results written to %s\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }