void gmskdem_demodulate(gmskdem _q, float complex * _x, unsigned int * _s) { // increment symbol counter _q->num_symbols_demod++; // run matched filter unsigned int i; float phi; float d_hat; for (i=0; i<_q->k; i++) { // compute phase difference phi = cargf( conjf(_q->x_prime)*_x[i] ); _q->x_prime = _x[i]; // run through matched filter #if GMSKDEM_USE_EQUALIZER eqlms_rrrf_push(_q->eq, phi); #else firfilt_rrrf_push(_q->filter, phi); #endif #if DEBUG_GMSKDEM // compute output float d_tmp; # if GMSKDEM_USE_EQUALIZER eqlms_rrrf_execute(_q->eq, &d_tmp); # else firfilt_rrrf_execute(_q->filter, &d_tmp); # endif windowf_push(_q->debug_mfout, d_tmp); #endif // decimate by k if ( i != 0 ) continue; #if GMSKDEM_USE_EQUALIZER // compute filter/equalizer output eqlms_rrrf_execute(_q->eq, &d_hat); #else // compute filter output firfilt_rrrf_execute(_q->filter, &d_hat); #endif } // make decision *_s = d_hat > 0.0f ? 1 : 0; #if GMSKDEM_USE_EQUALIZER // update equalizer, after appropriate delay if (_q->num_symbols_demod >= 2*_q->m) { // compute expected output, scaling by samples/symbol float d_prime = d_hat > 0 ? _q->k_inv : -_q->k_inv; eqlms_rrrf_step(_q->eq, d_prime, d_hat); } #endif }
int main() { // options unsigned int h_len=17; // filter length float fc=0.2f; // filter cutoff float As=30.0f; // stop-band attenuation [dB] float mu=0.0f; // timing offset unsigned int n=64; // number of random input samples // derived values unsigned int num_samples = n + h_len; // arrays float x[num_samples]; // filter input float y[num_samples]; // filter output unsigned int i; float h[h_len]; liquid_firdes_kaiser(h_len,fc,As,mu,h); firfilt_rrrf f = firfilt_rrrf_create(h,h_len); firfilt_rrrf_print(f); for (i=0; i<num_samples; i++) { // generate noise x[i] = (i<n) ? randnf()/sqrtf(n/2) : 0.0f; firfilt_rrrf_push(f, x[i]); firfilt_rrrf_execute(f, &y[i]); printf("x[%4u] = %12.8f, y[%4u] = %12.8f;\n", i, x[i], i, y[i]); } // destroy filter object firfilt_rrrf_destroy(f); // // export results // FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% firfilt_rrrf_example.m: auto-generated file\n\n"); fprintf(fid,"clear all;\nclose all;\n\n"); fprintf(fid,"h_len=%u;\nn=%u;\n", h_len, n); for (i=0; i<h_len; i++) fprintf(fid,"h(%4u) = %12.4e;\n", i+1, h[i]); for (i=0; i<num_samples; i++) fprintf(fid,"x(%4u) = %12.4e; y(%4u) = %12.4e;\n", i+1, x[i], i+1, y[i]); fprintf(fid,"nfft=512;\n"); fprintf(fid,"H=20*log10(abs(fftshift(fft(h,nfft))));\n"); fprintf(fid,"X=20*log10(abs(fftshift(fft(x,nfft))));\n"); fprintf(fid,"Y=20*log10(abs(fftshift(fft(y,nfft))));\n"); fprintf(fid,"f=[0:(nfft-1)]/nfft-0.5;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(f,X,'Color',[0.3 0.3 0.3],...\n"); fprintf(fid," f,Y,'LineWidth',2,...\n"); fprintf(fid," f,H,'-b','LineWidth',2);\n"); fprintf(fid,"axis([-0.5 0.5 -80 40]);\n"); fprintf(fid,"grid on;\nxlabel('normalized frequency');\nylabel('PSD [dB]');\n"); fprintf(fid,"legend('noise','filtered noise','filter prototype',1);"); fclose(fid); printf("results written to %s\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
int main(int argc, char*argv[]) { // options unsigned int h_len=19; // filter length unsigned int p=5; // polynomial order float fc=0.45f; // filter cutoff float As=60.0f; // stop-band attenuation [dB] float mu=0.1f; // fractional sample delay unsigned int num_samples=60; // number of samples to evaluate int verbose = 0; // verbose output? int dopt; while ((dopt = getopt(argc,argv,"hvt:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'v': verbose = 1; break; case 't': mu = atof(optarg); break; default: exit(1); } } // data arrays float x[num_samples]; // input data array float y[num_samples]; // output data array // create and initialize Farrow filter object firfarrow_rrrf f = firfarrow_rrrf_create(h_len, p, fc, As); firfarrow_rrrf_set_delay(f, mu); unsigned int i; // generate input (filtered noise) float hx[21]; liquid_firdes_kaiser(15, 0.1, 60, 0, hx); firfilt_rrrf fx = firfilt_rrrf_create(hx, 15); for (i=0; i<num_samples; i++) { firfilt_rrrf_push(fx, i < 40 ? randnf() : 0.0f); firfilt_rrrf_execute(fx, &x[i]); } firfilt_rrrf_destroy(fx); // push input through filter for (i=0; i<num_samples; i++) { firfarrow_rrrf_push(f, x[i]); firfarrow_rrrf_execute(f, &y[i]); } // destroy Farrow filter object firfarrow_rrrf_destroy(f); 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,"h_len = %u;\n", h_len); fprintf(fid,"mu = %f;\n", mu); fprintf(fid,"num_samples = %u;\n", num_samples); for (i=0; i<num_samples; i++) { fprintf(fid,"x(%4u) = %12.4e; y(%4u) = %12.4e;\n", i+1, x[i], i+1, y[i]); } // plot the results fprintf(fid,"\n\n"); fprintf(fid,"figure;\n"); fprintf(fid,"tx = 0:(num_samples-1); %% input time scale\n"); fprintf(fid,"ty = tx - (h_len-1)/2 + mu; %% output time scale\n"); fprintf(fid,"plot(tx, x,'-s','MarkerSize',3, ...\n"); fprintf(fid," ty, y,'-s','MarkerSize',3);\n"); fprintf(fid,"legend('input','output',0);\n"); fclose(fid); printf("results written to %s\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
int main() { // spectral periodogram options unsigned int nfft = 1024; // spectral periodogram FFT size unsigned int num_samples = 4000; // number of samples float beta = 10.0f; // Kaiser-Bessel window parameter float noise_floor = -60.0f; // noise floor [dB] float alpha = 0.1f; // PSD estimate bandwidth unsigned int i; // derived values float nstd = powf(10.0f, noise_floor/20.0f); // create spectral periodogram unsigned int window_size = nfft/2; // spgramf window size spgramf q = spgramf_create_kaiser(nfft, window_size, beta); // generate signal (filter with frequency offset) unsigned int h_len = 91; // filter length float fc = 0.07f; // filter cut-off frequency float f0 = 0.20f; // filter center frequency float As = 60.0f; // filter stop-band attenuation float h[h_len]; // filter coefficients liquid_firdes_kaiser(h_len, fc, As, 0, h); // add frequency offset for (i=0; i<h_len; i++) h[i] *= cosf(2*M_PI*f0*i); firfilt_rrrf filter = firfilt_rrrf_create(h, h_len); firfilt_rrrf_set_scale(filter, 2.0f*fc); for (i=0; i<num_samples; i++) { // generate random sample float x = randnf(); // filter float y = 0; firfilt_rrrf_push(filter, x); firfilt_rrrf_execute(filter, &y); // add noise y += nstd * randnf(); // push resulting sample through periodogram spgramf_accumulate_psd(q, &y, alpha, 1); } // compute power spectral density output float psd[nfft]; spgramf_write_accumulation(q, psd); // destroy objects firfilt_rrrf_destroy(filter); spgramf_destroy(q); // // export 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\n"); fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"H = zeros(1,nfft);\n"); fprintf(fid,"noise_floor = %12.6f;\n", noise_floor); for (i=0; i<nfft; i++) fprintf(fid,"H(%6u) = %12.4e;\n", i+1, psd[i]); fprintf(fid,"figure;\n"); fprintf(fid,"plot(f, H, '-', 'LineWidth',1.5);\n"); fprintf(fid,"xlabel('Normalized Frequency [f/F_s]');\n"); fprintf(fid,"ylabel('Power Spectral Density [dB]');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"ymin = 10*floor([noise_floor-20]/10);\n"); fprintf(fid,"ymax = 10*floor([noise_floor+80]/10);\n"); fprintf(fid,"axis([-0.5 0.5 ymin ymax]);\n"); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME); printf("done.\n"); return 0; }
void ModemFMStereo::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) { ModemKitFMStereo *fmkit = (ModemKitFMStereo *)kit; size_t bufSize = input->data.size(); liquid_float_complex u, v, w, x, y; double audio_resample_ratio = fmkit->audioResampleRatio; if (demodOutputData.size() != bufSize) { if (demodOutputData.capacity() < bufSize) { demodOutputData.reserve(bufSize); } demodOutputData.resize(bufSize); } size_t audio_out_size = (size_t)ceil((double) (bufSize) * audio_resample_ratio) + 512; freqdem_demodulate_block(demodFM, &input->data[0], bufSize, &demodOutputData[0]); if (resampledOutputData.size() != audio_out_size) { if (resampledOutputData.capacity() < audio_out_size) { resampledOutputData.reserve(audio_out_size); } resampledOutputData.resize(audio_out_size); } unsigned int numAudioWritten; msresamp_rrrf_execute(fmkit->audioResampler, &demodOutputData[0], bufSize, &resampledOutputData[0], &numAudioWritten); if (demodStereoData.size() != bufSize) { if (demodStereoData.capacity() < bufSize) { demodStereoData.reserve(bufSize); } demodStereoData.resize(bufSize); } float phase_error = 0; for (size_t i = 0; i < bufSize; i++) { // real -> complex firhilbf_r2c_execute(fmkit->firStereoR2C, demodOutputData[i], &x); // 19khz pilot band-pass iirfilt_crcf_execute(fmkit->iirStereoPilot, x, &v); nco_crcf_cexpf(fmkit->stereoPilot, &w); w.imag = -w.imag; // conjf(w) // multiply u = v * conjf(w) u.real = v.real * w.real - v.imag * w.imag; u.imag = v.real * w.imag + v.imag * w.real; // cargf(u) phase_error = atan2f(u.imag,u.real); // step pll nco_crcf_pll_step(fmkit->stereoPilot, phase_error); nco_crcf_step(fmkit->stereoPilot); // 38khz down-mix nco_crcf_mix_down(fmkit->stereoPilot, x, &y); nco_crcf_mix_down(fmkit->stereoPilot, y, &x); // complex -> real firhilbf_c2r_execute(fmkit->firStereoC2R, x, &demodStereoData[i]); } // std::cout << "[PLL] phase error: " << phase_error; // std::cout << " freq:" << (((nco_crcf_get_frequency(stereoPilot) / (2.0 * M_PI)) * inp->sampleRate)) << std::endl; if (audio_out_size != resampledStereoData.size()) { if (resampledStereoData.capacity() < audio_out_size) { resampledStereoData.reserve(audio_out_size); } resampledStereoData.resize(audio_out_size); } msresamp_rrrf_execute(fmkit->stereoResampler, &demodStereoData[0], bufSize, &resampledStereoData[0], &numAudioWritten); audioOut->channels = 2; if (audioOut->data.capacity() < (numAudioWritten * 2)) { audioOut->data.reserve(numAudioWritten * 2); } audioOut->data.resize(numAudioWritten * 2); for (size_t i = 0; i < numAudioWritten; i++) { float l, r; float ld, rd; if (fmkit->demph) { iirfilt_rrrf_execute(fmkit->iirDemphL, 0.568f * (resampledOutputData[i] - (resampledStereoData[i])), &ld); iirfilt_rrrf_execute(fmkit->iirDemphR, 0.568f * (resampledOutputData[i] + (resampledStereoData[i])), &rd); firfilt_rrrf_push(fmkit->firStereoLeft, ld); firfilt_rrrf_execute(fmkit->firStereoLeft, &l); firfilt_rrrf_push(fmkit->firStereoRight, rd); firfilt_rrrf_execute(fmkit->firStereoRight, &r); } else { firfilt_rrrf_push(fmkit->firStereoLeft, 0.568f * (resampledOutputData[i] - (resampledStereoData[i]))); firfilt_rrrf_execute(fmkit->firStereoLeft, &l); firfilt_rrrf_push(fmkit->firStereoRight, 0.568f * (resampledOutputData[i] + (resampledStereoData[i]))); firfilt_rrrf_execute(fmkit->firStereoRight, &r); } audioOut->data[i * 2] = l; audioOut->data[i * 2 + 1] = r; } }