/* Performs 1st order linear interpolation with out-of-bound interpolation */ void srslte_interp_linear_offset_cabs(cf_t *input, cf_t *output, uint32_t M, uint32_t len, uint32_t off_st, uint32_t off_end) { uint32_t i, j; float mag0=0, mag1=0, arg0=0, arg1=0, mag=0, arg=0; for (i=0;i<len-1;i++) { mag0 = cabsf(input[i]); mag1 = cabsf(input[i+1]); arg0 = cargf(input[i]); arg1 = cargf(input[i+1]); if (i==0) { for (j=0;j<off_st;j++) { mag = mag0 - (j+1)*(mag1-mag0)/M; arg = arg0 - (j+1)*(arg1-arg0)/M; output[j] = mag * cexpf(I * arg); } } for (j=0;j<M;j++) { mag = mag0 + j*(mag1-mag0)/M; arg = arg0 + j*(arg1-arg0)/M; output[i*M+j+off_st] = mag * cexpf(I * arg); } } if (len > 1) { for (j=0;j<off_end;j++) { mag = mag1 + j*(mag1-mag0)/M; arg = arg1 + j*(arg1-arg0)/M; output[i*M+j+off_st] = mag * cexpf(I * arg); } } }
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); }
/* Performs 1st order linear interpolation with out-of-bound interpolation */ void interp_linear_offset(cf_t *input, cf_t *output, int M, int len, int off_st, int off_end) { int i, j; float mag0, mag1, arg0, arg1, mag, arg; for (i=0;i<len-1;i++) { mag0 = cabsf(input[i]); mag1 = cabsf(input[i+1]); arg0 = cargf(input[i]); arg1 = cargf(input[i+1]); if (i==0) { for (j=0;j<off_st;j++) { mag = mag0 - (j+1)*(mag1-mag0)/M; arg = arg0 - (j+1)*(arg1-arg0)/M; output[j] = mag * cexpf(I * arg); } } for (j=0;j<M;j++) { mag = mag0 + j*(mag1-mag0)/M; arg = arg0 + j*(arg1-arg0)/M; output[i*M+j+off_st] = mag * cexpf(I * arg); } } if (len > 1) { for (j=0;j<off_end;j++) { mag = mag1 + j*(mag1-mag0)/M; arg = arg1 + j*(arg1-arg0)/M; output[i*M+j+off_st] = mag * cexpf(I * arg); } } }
void myradon2_lop(bool adj, bool add, int nm, int nd, sf_complex *mm, sf_complex *dd) /*< radon linear operator >*/ { int ix, ip; sf_complex sumc; if (nm != np || nd != nx) sf_error("%s: mismatched data sizes",__FILE__); sf_cadjnull(adj, add, nm, nd, mm, dd); if(adj){// mm(p,w)=sum_{ix=0}^{nx} dd(xx[ix],w)*exp(i*w*p*xx[ix]) for(ip=0; ip<np; ip++) // loop over slopes { sumc=sf_cmplx(0,0); for(ix=0; ix<nx; ix++) sumc+=cexpf(I*w*p[ip]*xx[ix])*dd[ix]; mm[ip]=sumc; } }else{// dd(xx,w)=sum_{ip=0}^{np} mm(p[ip],w)*exp(-i*w*p[ip]*xx) for(ix=0; ix<nx; ix++) { sumc=sf_cmplx(0,0); for(ip=0; ip<np; ip++) sumc+=cexpf(-I*w*p[ip]*xx[ix])*mm[ip]; dd[ix]=sumc; } } }
/* _m : number of correlators */ PRESYNC() PRESYNC(_create)(TC * _v, unsigned int _n, float _dphi_max, unsigned int _m) { // validate input if (_n < 1) { fprintf(stderr, "error: bpresync_%s_create(), invalid input length\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr, "error: bpresync_%s_create(), number of correlators must be at least 1\n", EXTENSION_FULL); exit(1); } // allocate main object memory and initialize PRESYNC() _q = (PRESYNC()) malloc(sizeof(struct PRESYNC(_s))); _q->n = _n; _q->m = _m; _q->n_inv = 1.0f / (float)(_q->n); unsigned int i; // create internal receive buffers _q->rx_i = WINDOW(_create)(_q->n); _q->rx_q = WINDOW(_create)(_q->n); // create internal array of frequency offsets _q->dphi = (float*) malloc( _q->m*sizeof(float) ); // create internal synchronizers _q->sync_i = (DOTPROD()*) malloc( _q->m*sizeof(DOTPROD()) ); _q->sync_q = (DOTPROD()*) malloc( _q->m*sizeof(DOTPROD()) ); // buffer T vi_prime[_n]; T vq_prime[_n]; for (i=0; i<_q->m; i++) { // generate signal with frequency offset _q->dphi[i] = (float)i / (float)(_q->m-1)*_dphi_max; unsigned int k; for (k=0; k<_q->n; k++) { vi_prime[k] = REAL( _v[k] * cexpf(-_Complex_I*k*_q->dphi[i]) ); vq_prime[k] = IMAG( _v[k] * cexpf(-_Complex_I*k*_q->dphi[i]) ); } _q->sync_i[i] = DOTPROD(_create)(vi_prime, _q->n); _q->sync_q[i] = DOTPROD(_create)(vq_prime, _q->n); } // allocate memory for cross-correlation _q->rxy = (float*) malloc( _q->m*sizeof(float) ); // reset object PRESYNC(_reset)(_q); return _q; }
static void init_wave(int init, int nx, float dx, int nz, float dz, sf_complex *pp /* [nx] */, float wov, int nw, int iw) { int ix; float x,x0,z0,phase,amp; x0 = nx*dx/3; z0 = nz*dz/3; switch(init) { case 1: /* planar wave @ 15deg */ for (ix=0; ix < nx; ix++) { x = (ix+1)*dx - x0; phase = wov*x*sinf(15*SF_PI/180.); pp[ix] = cexpf(sf_cmplx(0.,phase)); } break; case 2: /* expanding spherical wave */ for (ix=0; ix < nx; ix++) { x = (ix+1)*dx - x0; phase = wov*hypotf(z0,x); pp[ix] = cexpf(sf_cmplx(0.,phase)); } break; case 3: /* point source */ for (ix=0; ix < nx; ix++) { pp[ix]=sf_cmplx(0.,0.); } pp[nx/3-1] = sf_cmplx(1.,0.); break; case 4: /* collapsing spherical wave */ for (ix=0; ix < nx; ix++) { x = (ix+1)*dx - x0; phase = -wov*hypotf(z0,x); pp[ix] = cexpf(sf_cmplx(0.,phase)); } break; default: sf_error("Unknown init=%d",init); } amp = (nw-iw+1.0)/nw; amp = cosf((1-amp)*(0.5*SF_PI)); amp *= amp; for (ix=0; ix < nx; ix++) { #ifdef SF_HAS_COMPLEX_H pp[ix] *= amp; #else pp[ix] = sf_crmul(pp[ix],amp); #endif } }
// [AC-Adaptive] static void radial_self_delays(unsigned int N, float shifts[N], const float phi[N], const long dims[DIMS], const complex float* in) { unsigned int d = 2; unsigned int flags = (1 << d); assert(N == dims[d]); long dims1[DIMS]; md_select_dims(DIMS, ~flags, dims1, dims); complex float* tmp1 = md_alloc(DIMS, dims1, CFL_SIZE); complex float* tmp2 = md_alloc(DIMS, dims1, CFL_SIZE); long pos[DIMS] = { 0 }; for (unsigned int i = 0; i < dims[d]; i++) { pos[d] = i; md_copy_block(DIMS, pos, dims1, tmp1, dims, in, CFL_SIZE); // find opposing spoke float mdelta = 0.; int mindex = 0; for (unsigned int j = 0; j < dims[d]; j++) { float delta = cabsf(cexpf(1.i * phi[j]) - cexpf(1.i * phi[i])); if (mdelta <= delta) { mdelta = delta; mindex = j; } } pos[d] = mindex; md_copy_block(DIMS, pos, dims1, tmp2, dims, in, CFL_SIZE); unsigned int d2 = 1; float rshifts[DIMS]; md_flip(DIMS, dims1, MD_BIT(d2), tmp2, tmp2, CFL_SIZE); // could be done by iFFT in est_subpixel_shift est_subpixel_shift(DIMS, rshifts, dims1, MD_BIT(d2), tmp2, tmp1); float mshift = rshifts[d2] / 2.; // mdelta shifts[i] = mshift; } md_free(tmp1); md_free(tmp2); }
void xkolmog(sf_complex *trace1, sf_complex *trace2) /*< convert Fourier-domain cross-correlation to minimum-phase >*/ { int i1; const double eps=1.e-32; for (i1=0; i1 < nk; i1++) { #ifdef SF_HAS_COMPLEX_H fft1[i1] = clogf(trace1[i1]+eps)/nk; #else fft1[i1] = sf_crmul(clogf(sf_cadd(trace1[i1],sf_cmplx(eps,0.))), 1.0/nk); #endif } /* Inverse transform */ kiss_fft(invs,(const kiss_fft_cpx *) fft1, (kiss_fft_cpx *) trace1); #ifdef SF_HAS_COMPLEX_H trace1[0] *= 0.5; trace2[0] = trace1[0]; trace1[nk/2] *= 0.5; trace2[nk/2] = trace1[nk/2]; #else trace1[0] = sf_crmul(trace1[0], 0.5); trace2[0] = trace1[0]; trace1[nk/2] = sf_crmul(trace1[nk/2],0.5); trace2[nk/2] = trace1[nk/2]; #endif for (i1=1+nk/2; i1 < nk; i1++) { trace2[nk-i1] = trace1[i1]; trace1[i1] = sf_cmplx(0.,0.); trace2[i1] = sf_cmplx(0.,0.); } /* Fourier transform */ kiss_fft(forw,(const kiss_fft_cpx *) trace1, (kiss_fft_cpx *) fft1); kiss_fft(forw,(const kiss_fft_cpx *) trace2, (kiss_fft_cpx *) fft2); for (i1=0; i1 < nk; i1++) { #ifdef SF_HAS_COMPLEX_H fft1[i1] = cexpf(fft1[i1])/nk; fft2[i1] = cexpf(fft2[i1])/nk; #else fft1[i1] = sf_crmul(cexpf(fft1[i1]),1./nk); fft2[i1] = sf_crmul(cexpf(fft2[i1]),1./nk); #endif } /* Inverse transform */ kiss_fft(invs,(const kiss_fft_cpx *) fft1, (kiss_fft_cpx *) trace1); kiss_fft(invs,(const kiss_fft_cpx *) fft2, (kiss_fft_cpx *) trace2); for (i1=0; i1 < nk; i1++) { trace2[i1] = conjf(trace2[i1]); } }
sf_complex Green(float r1,float r2,float r3,float s1,float s2,float s3,float omega) /*< Green's function >*/ { double tt,amp; sf_complex val; GreenTtAmp(r1,r2,r3,s1,s2,s3,&tt,&); #ifdef SF_HAS_COMPLEX_H val=amp*cexpf(sf_cmplx(0.,omega*tt)); #else val=sf_crmul(cexpf(sf_cmplx(0.,omega*tt)),amp); #endif return (val); }
void BornScatteredField(float xx,float xy,float xz,float *output) /*< Born scattering field >*/ { int iw; double omega,scale; sf_complex U,dU; sf_complex val,fkern; ZeroArray(u, nt); ZeroArray(du, nt); *output=0.; for (iw=0; iw<nw; iw++) { omega=ow+dw*iw; scale =cos((SF_PI/2)*(((double) iw+1)/((double) nw+1))); scale*=scale*omega; #ifdef SF_HAS_COMPLEX_H /* background field */ U=Green(xx,xy,xz,sx,sy,sz,omega)*scale; /* scattered field */ val=Green(px,py,pz,sx,sy,sz,omega)*scale; val *= Green(xx,xy,xz,px,py,pz,omega); dU = val*(-omega*omega*dv); U += dU; fkern=cexpf(sf_cmplx(0.,-omega*0.6)); val=fkern*U; #else /* background field */ U=sf_crmul(Green(xx,xy,xz,sx,sy,sz,omega),scale); /* scattered field */ val=sf_crmul(Green(px,py,pz,sx,sy,sz,omega),scale); val=sf_cmul(val,Green(xx,xy,xz,px,py,pz,omega)); dU=sf_crmul(val,-omega*omega*dv); U=sf_cadd(U,dU); fkern=cexpf(sf_cmplx(0.,-omega*0.6)); val=sf_cmul(fkern,U); #endif *output+=crealf(val); } return; }
// // 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); }
void fbdip_init(float rad, int m1, int m2, int *rect, int niter, float dip0, bool vb) /*< initialize >*/ { int n, nn[2]; n1 = m1; n2 = m2; verb = vb; u1 = sf_floatalloc2(n1, n2); u2 = sf_floatalloc2(n1, n2); u3 = sf_floatalloc2(n1, n2); u4 = sf_floatalloc2(n1, n2); u5 = sf_floatalloc2(n1, n2); p = sf_complexalloc2(n1, n2); r=rad; p0 = rad*cexpf(sf_cmplx(0, dip0)); if(rect[0]>0 && rect[1]>0) { n = n1*n2; nn[0] = n1; nn[1] = n2; sf_divn_init (2, n, nn, rect, niter, false); use_divn=true; }else use_divn=false; }
// create freqmod object // _kf : modulation factor FREQMOD() FREQMOD(_create)(float _kf) { // validate input if (_kf <= 0.0f || _kf > 1.0) { fprintf(stderr,"error: freqmod_create(), modulation factor %12.4e out of range [0,1]\n", _kf); exit(1); } // create main object memory FREQMOD() q = (freqmod) malloc(sizeof(struct FREQMOD(_s))); // set modulation factor q->kf = _kf; q->ref = q->kf * (1<<16); // initialize look-up table q->sincos_table_len = 1024; q->sincos_table = (TC*) malloc( q->sincos_table_len*sizeof(TC) ); unsigned int i; for (i=0; i<q->sincos_table_len; i++) { q->sincos_table[i] = cexpf(_Complex_I*2*M_PI*(float)i / (float)(q->sincos_table_len) ); } // reset modem object FREQMOD(_reset)(q); // return object return q; }
void benchmark_gmskmodem_demodulate(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { // options unsigned int k=2; // filter samples/symbol unsigned int m=3; // filter delay (symbols) float BT=0.3f; // bandwidth-time product // create modem object gmskdem demod = gmskdem_create(k, m, BT); float complex x[k]; unsigned int symbol_out = 0; unsigned long int i; for (i=0; i<k; i++) x[i] = randnf()*cexpf(_Complex_I*2*M_PI*randf()); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { gmskdem_demodulate(demod, x, &symbol_out); gmskdem_demodulate(demod, x, &symbol_out); gmskdem_demodulate(demod, x, &symbol_out); gmskdem_demodulate(demod, x, &symbol_out); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; // destroy modem objects gmskdem_destroy(demod); }
/*------------------------------------------------------------*/ void cam3_ssf( sf_complex w /* frequency */, sf_complex ***wx /* wavefield */, cub3d cub, cam3d cam, tap3d tap, slo3d slo, int imz, int ompith ) /*< Wavefield extrapolation by SSF >*/ { sf_complex co,cs,cr,w2,khy,kss,krr; float s, kmy, d,dsc,drc; int imy,imx,ihx,jmy, js,jr; co = sf_cmplx(0,0); #ifdef SF_HAS_COMPLEX_H w2 = w*w; #else w2 = sf_cmul(w,w); #endif #ifdef SF_HAS_COMPLEX_H LOOP( s = slo->so[ompith][ cam->jy[imy] ][ cam->is[ihx][imx] ] + slo->so[ompith][ cam->jy[imy] ][ cam->ir[ihx][imx] ]; wx[ihx][imy][imx] *= cexpf(-w*s* cub->amz.d/2); );
/* inputs: * pdx,pf,n: piecewise linear function dx, values, and length * w: desired angular frequency * returns fourier coefficient as complex number (ISO C99). * If the input is a complex function, the following can be called twice * with the second coefficient multiplied by _Complex_I and added to the * first (see pclin_fourier_trans_cplx). * It is assumed that the length of the x-axis is 2*pi. If it is not, it * should be normalized to 2*pi before calling this function. */ float complex pclin_fourier(float *pdx, float *pf, int n, float w) { int i; float x1,x2; float f1,f2; float slope,offset; float complex sum; float complex alpha; float complex invalpha; x1 = 0.0; sum = 0.0; f1=pf[n-1]; /* different behavior for zero w */ if(w==0.0){ for(i=0;i<n;i++){ sum += 0.5*pdx[i]*(f1 + pf[i]); x1 += pdx[i]; f1 = pf[i]; } return sum; } /* regular behavior for nonzero w */ alpha = -_Complex_I*w; invalpha = 1/alpha; for(i=0;i<n;i++){ f2 = pf[i]; x2 = x1+pdx[i]; /* calculate product of fourier wave with function */ /* first, calculate slope and offset of curve */ slope=(f2-f1)/(x2-x1); offset=f1-slope*x1; /* now use formula (refer to pclin_fourier.tex) */ sum += cexpf(alpha*x2)*(slope*(x2-invalpha)+offset) - cexpf(alpha*x1)*(slope*(x1-invalpha)+offset); f1 = f2; x1 = x2; } return sum/alpha; }
// recover symbol, correcting for gain, pilot phase, etc. void wlanframesync_rxsymbol(wlanframesync _q) { // apply gain unsigned int i; for (i=0; i<64; i++) _q->X[i] *= _q->R[i]; // polynomial curve-fit float x_phase[4] = {-21.0f, -7.0f, 7.0f, 21.0f}; float y_phase[4]; float p_phase[2]; // update pilot phase unsigned int pilot_phase = wlan_lfsr_advance(_q->ms_pilot); y_phase[0] = pilot_phase ? cargf(-_q->X[43]) : cargf( _q->X[43]); y_phase[1] = pilot_phase ? cargf(-_q->X[57]) : cargf( _q->X[57]); y_phase[2] = pilot_phase ? cargf(-_q->X[ 7]) : cargf( _q->X[ 7]); y_phase[3] = pilot_phase ? cargf( _q->X[21]) : cargf(-_q->X[21]); // unwrap phase if ( (y_phase[1]-y_phase[0]) > M_PI ) y_phase[1] -= 2*M_PI; if ( (y_phase[1]-y_phase[0]) < -M_PI ) y_phase[1] += 2*M_PI; if ( (y_phase[2]-y_phase[1]) > M_PI ) y_phase[2] -= 2*M_PI; if ( (y_phase[2]-y_phase[1]) < -M_PI ) y_phase[2] += 2*M_PI; if ( (y_phase[3]-y_phase[2]) > M_PI ) y_phase[3] -= 2*M_PI; if ( (y_phase[3]-y_phase[2]) < -M_PI ) y_phase[3] += 2*M_PI; #if 0 printf(" x = [-21 -7 7 21]; y = [%6.3f %6.3f %6.3f %6.3f];\n", y_phase[0], y_phase[1], y_phase[2], y_phase[3]); #endif // fit phase to 1st-order polynomial (2 coefficients) polyf_fit(x_phase, y_phase, 4, p_phase, 2); // compensate for phase offset // TODO : find more computationally efficient way to do this for (i=0; i<64; i++) { float fx = (i > 31) ? (float)i - (float)(64) : (float)i; float theta = polyf_val(p_phase, 2, fx); _q->X[i] *= cexpf(-_Complex_I*theta); } // adjust NCO frequency based on differential phase if (_q->num_symbols > 0) { // compute phase error (unwrapped) float dphi_prime = p_phase[0] - _q->phi_prime; if (dphi_prime > M_PI) dphi_prime -= M_2_PI; if (dphi_prime < -M_PI) dphi_prime += M_2_PI; // adjust NCO proportionally to phase error nco_crcf_adjust_frequency(_q->nco_rx, 1e-3f*dphi_prime); } // set internal phase state _q->phi_prime = p_phase[0]; }
void wlanframesync_execute_rxlong0(wlanframesync _q) { // set timer to 16, wait for phase to be relatively small _q->timer++; if (_q->timer < 16) return; // reset timer _q->timer = 0; // run fft float complex * rc; windowcf_read(_q->input_buffer, &rc); // estimate S1 gain, adding backoff in gain estimation wlanframesync_estimate_gain_S1(_q, &rc[16-2], _q->G1a); // compute S1 metrics float complex s_hat; wlanframesync_S1_metrics(_q, _q->G1a, &s_hat); s_hat *= _q->g0; // scale output by raw gain estimate // rotate by complex phasor relative to timing backoff //s_hat *= cexpf(_Complex_I * 2.0f * 2.0f * M_PI / 64.0f); s_hat *= cexpf(_Complex_I * 0.19635f); // save first 'long' symbol statistic _q->s1a_hat = s_hat; #if DEBUG_WLANFRAMESYNC_PRINT printf(" s_hat : %12.8f <%12.8f>\n", cabsf(s_hat), cargf(s_hat)); #endif float s_hat_abs = cabsf(s_hat); float s_hat_arg = cargf(s_hat); if (s_hat_arg > M_PI) s_hat_arg -= 2.0f*M_PI; if (s_hat_arg < -M_PI) s_hat_arg += 2.0f*M_PI; // check conditions for s_hat: // 1. magnitude should be large (near unity) when aligned // 2. phase should be very near zero (time aligned) if (s_hat_abs > WLANFRAMESYNC_S1A_ABS_THRESH && fabsf(s_hat_arg) < WLANFRAMESYNC_S1A_ARG_THRESH) { #if DEBUG_WLANFRAMESYNC_PRINT printf(" acquisition S1[a]\n"); #endif // set state _q->state = WLANFRAMESYNC_STATE_RXLONG1; // reset timer _q->timer = 0; } }
/* _m : number of correlators */ BPRESYNC() BPRESYNC(_create)(TC * _v, unsigned int _n, float _dphi_max, unsigned int _m) { // validate input if (_n < 1) { fprintf(stderr, "error: bpresync_%s_create(), invalid input length\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr, "error: bpresync_%s_create(), number of correlators must be at least 1\n", EXTENSION_FULL); exit(1); } // allocate main object memory and initialize BPRESYNC() _q = (BPRESYNC()) malloc(sizeof(struct BPRESYNC(_s))); _q->n = _n; _q->m = _m; _q->n_inv = 1.0f / (float)(_q->n); unsigned int i; // create internal receive buffers _q->rx_i = bsequence_create(_q->n); _q->rx_q = bsequence_create(_q->n); // create internal array of frequency offsets _q->dphi = (float*) malloc( _q->m*sizeof(float) ); // create internal synchronizers _q->sync_i = (bsequence*) malloc( _q->m*sizeof(bsequence) ); _q->sync_q = (bsequence*) malloc( _q->m*sizeof(bsequence) ); for (i=0; i<_q->m; i++) { _q->sync_i[i] = bsequence_create(_q->n); _q->sync_q[i] = bsequence_create(_q->n); // generate signal with frequency offset _q->dphi[i] = (float)i / (float)(_q->m-1)*_dphi_max; unsigned int k; for (k=0; k<_q->n; k++) { TC v_prime = _v[k] * cexpf(-_Complex_I*k*_q->dphi[i]); bsequence_push(_q->sync_i[i], crealf(v_prime)>0); bsequence_push(_q->sync_q[i], cimagf(v_prime)>0); } } // allocate memory for cross-correlation _q->rxy = (float*) malloc( _q->m*sizeof(float) ); // reset object BPRESYNC(_reset)(_q); return _q; }
void rweone_ssh( sf_complex *v, float w, float *aa) /*< space-domain phase shift >*/ { int ig; sf_complex ikz; for(ig=0;ig<ag.n;ig++) { ikz = sf_cmplx(0.,w * aa[ig]); #ifdef SF_HAS_COMPLEX_H v[ig] *= cexpf( ikz * at.d ); #else v[ig] = sf_cmul(v[ig],cexpf(sf_crmul( ikz, at.d ))); #endif } }
int main() { unsigned int m=5; // filter semi-length float fc=0.2f; // input tone frequency unsigned int N=128; // number of input samples float As=60.0f; // stop-band attenuation [dB] // create/print the half-band resampler, centered on // tone frequency with a specified stop-band attenuation resamp2_cccf f = resamp2_cccf_create(m,fc,As); resamp2_cccf_print(f); // open 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,"h_len=%u;\n", 4*m+1); fprintf(fid,"N=%u;\n", N); unsigned int i; float theta=0.0f, dtheta=2*M_PI*fc; float complex x, y[2]; for (i=0; i<N; i++) { // generate input : complex sinusoid x = cexpf(_Complex_I*theta) * (i<N/2 ? 2.0f*1.8534f*hamming(i,N/2) : 0.0f); theta += dtheta; // run the interpolator resamp2_cccf_interp_execute(f, x, y); // save results to output file fprintf(fid,"x(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(x), cimagf(x)); fprintf(fid,"y(%3u) = %12.4e + j*%12.4e;\n", 2*i+1, crealf(y[0]), cimagf(y[0])); fprintf(fid,"y(%3u) = %12.4e + j*%12.4e;\n", 2*i+2, crealf(y[1]), cimagf(y[1])); printf("y(%3u) = %8.4f + j*%8.4f;\n", 2*i+1, crealf(y[0]), cimagf(y[0])); printf("y(%3u) = %8.4f + j*%8.4f;\n", 2*i+2, crealf(y[1]), cimagf(y[1])); } fprintf(fid,"nfft=512;\n"); fprintf(fid,"X=20*log10(abs(fftshift(fft(x/N, nfft))));\n"); fprintf(fid,"Y=20*log10(abs(fftshift(fft(y/(2*N),nfft))));\n"); fprintf(fid,"f=[0:(nfft-1)]/nfft-0.5;\n"); fprintf(fid,"figure; plot(f/2,X,'Color',[0.5 0.5 0.5],f,Y,'LineWidth',2);\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"xlabel('normalized frequency');\n"); fprintf(fid,"ylabel('PSD [dB]');\n"); fprintf(fid,"legend('original','interpolated',1);"); fprintf(fid,"axis([-0.5 0.5 -100 10]);\n"); fclose(fid); printf("results written to %s\n",OUTPUT_FILENAME); // clean up allocated objects resamp2_cccf_destroy(f); printf("done.\n"); return 0; }
void rweone_ssf( sf_complex *v, float w, float *aa, float a0) /*< split-step Fourier correction >*/ { int ig; sf_complex ikz; for(ig=0; ig<ag.n; ig++) { ikz = sf_cmplx(0.,w * (aa[ig] - a0)); #ifdef SF_HAS_COMPLEX_H v[ig] *= cexpf( ikz * ( at.d) ); #else v[ig] = sf_cmul(v[ig],cexpf(sf_crmul(ikz, at.d))); #endif } }
void rweone_phs( sf_complex *v, float w, float a0, float b0 ) /*< Fourier-domain phase shift >*/ { int ig,ikg; float kg; float a2,b2,k2; sf_complex iw,ikt,w2; a2 = a0*a0; b2 = b0*b0; iw = sf_cmplx(2e-3,-w); #ifdef SF_HAS_COMPLEX_H w2 = iw*iw; #else w2 = sf_cmul(iw,iw); #endif rweone_fft(false,(kiss_fft_cpx*) v); for(ig=0;ig<ag.n;ig++) { ikg = KMAP(ig,ag.n); kg = okg + ikg * dkg; k2 = kg*kg; #ifdef SF_HAS_COMPLEX_H ikt = csqrtf( w2*a2 + k2*b2 ); v[ig] *= cexpf(-ikt*at.d); #else ikt = csqrtf(sf_cadd(sf_crmul(w2,a2),sf_cmplx(k2*b2,0.))); v[ig] = sf_cmul(v[ig],cexpf(sf_crmul(ikt,-at.d))); #endif } rweone_fft( true,(kiss_fft_cpx*) v); }
// Compute group delay for an IIR filter // _b : filter coefficients array (numerator), [size: _nb x 1] // _nb : filter length (numerator) // _a : filter coefficients array (denominator), [size: _na x 1] // _na : filter length (denominator) // _fc : frequency at which delay is evaluated (-0.5 < _fc < 0.5) float iir_group_delay(float * _b, unsigned int _nb, float * _a, unsigned int _na, float _fc) { // validate input if (_nb == 0) { fprintf(stderr,"error: iir_group_delay(), numerator length must be greater than zero\n"); exit(1); } else if (_na == 0) { fprintf(stderr,"error: iir_group_delay(), denominator length must be greater than zero\n"); exit(1); } else if (_fc < -0.5 || _fc > 0.5) { fprintf(stderr,"error: iir_group_delay(), _fc must be in [-0.5,0.5]\n"); exit(1); } // compute c = conv(b,fliplr(a)) // c(z) = b(z)*a(1/z)*z^(-_na) unsigned int nc = _na + _nb - 1; float c[nc]; unsigned int i,j; for (i=0; i<nc; i++) c[i] = 0.0; for (i=0; i<_na; i++) { for (j=0; j<_nb; j++) { c[i+j] += conjf(_a[_na-i-1])*_b[j]; } } // compute // sum(c[i] * exp(j 2 pi fc i) * i) // -------------------------------- // sum(c[i] * exp(j 2 pi fc i)) float complex t0=0.0f; float complex t1=0.0f; float complex c0; for (i=0; i<nc; i++) { c0 = c[i] * cexpf(_Complex_I*2*M_PI*_fc*i); t0 += c0*i; t1 += c0; } // prevent divide-by-zero (check magnitude for tolerance range) float tol = 1e-5f; if (cabsf(t1)<tol) return 0.0f; // return result, scaled by length of denominator return crealf(t0/t1) - (_na - 1); }
// Compute relative out-of-band energy // // _h : filter coefficients [size: _h_len x 1] // _h_len : filter length // _fc : analysis cut-off frequency // _nfft : fft size float liquid_filter_energy(float * _h, unsigned int _h_len, float _fc, unsigned int _nfft) { // validate input if (_fc < 0.0f || _fc > 0.5f) { fprintf(stderr,"error: liquid_filter_energy(), cut-off frequency must be in [0,0.5]\n"); exit(1); } else if (_h_len == 0) { fprintf(stderr,"error: liquid_filter_energy(), filter length must be greater than zero\n"); exit(1); } else if (_nfft == 0) { fprintf(stderr,"error: liquid_filter_energy(), fft size must be greater than zero\n"); exit(1); } // allocate memory for complex phasor float complex expjwt[_h_len]; // initialize accumulators float e_total = 0.0f; // total energy float e_stopband = 0.0f; // stop-band energy // create dotprod object dotprod_crcf dp = dotprod_crcf_create(_h,_h_len); unsigned int i; unsigned int k; for (i=0; i<_nfft; i++) { float f = 0.5f * (float)i / (float)(_nfft); // initialize complex phasor for (k=0; k<_h_len; k++) expjwt[k] = cexpf(_Complex_I*2*M_PI*f*k); // compute vector dot product float complex v; dotprod_crcf_execute(dp, expjwt, &v); // accumulate output float e2 = crealf( v*conjf(v) ); e_total += e2; e_stopband += (f >= _fc) ? e2 : 0.0f; } // destroy dotprod object dotprod_crcf_destroy(dp); // return energy ratio return e_stopband / e_total; }
// create firhilb object // _m : filter semi-length (delay: 2*m+1) // _As : stop-band attenuation [dB] FIRHILB() FIRHILB(_create)(unsigned int _m, float _As) { // validate firhilb inputs if (_m < 2) { fprintf(stderr,"error: firhilb_create(), filter semi-length (m) must be at least 2\n"); exit(1); } // allocate memory for main object FIRHILB() q = (FIRHILB()) malloc(sizeof(struct FIRHILB(_s))); q->m = _m; // filter semi-length q->As = fabsf(_As); // stop-band attenuation // set filter length and allocate memory for coefficients q->h_len = 4*(q->m) + 1; q->h = (T *) malloc((q->h_len)*sizeof(T)); q->hc = (T complex *) malloc((q->h_len)*sizeof(T complex)); // allocate memory for quadrature filter component q->hq_len = 2*(q->m); q->hq = (T *) malloc((q->hq_len)*sizeof(T)); // compute filter coefficients for half-band filter liquid_firdes_kaiser(q->h_len, 0.25f, q->As, 0.0f, q->h); // alternate sign of non-zero elements unsigned int i; for (i=0; i<q->h_len; i++) { float t = (float)i - (float)(q->h_len-1)/2.0f; q->hc[i] = q->h[i] * cexpf(_Complex_I*0.5f*M_PI*t); q->h[i] = cimagf(q->hc[i]); } // resample, reverse direction unsigned int j=0; for (i=1; i<q->h_len; i+=2) q->hq[j++] = q->h[q->h_len - i - 1]; // create windows for upper and lower polyphase filter branches q->w1 = WINDOW(_create)(2*(q->m)); q->w0 = WINDOW(_create)(2*(q->m)); WINDOW(_clear)(q->w0); WINDOW(_clear)(q->w1); // create internal dot product object q->dpq = DOTPROD(_create)(q->hq, q->hq_len); // reset internal state and return object FIRHILB(_reset)(q); return q; }
// Compute analog zeros, poles, gain of low-pass Butterworth // filter, grouping complex conjugates together. If filter // order is odd, the single real pole (-1) is at the end of // the array. There are no zeros for the analog Butterworth // filter. The gain is unity. // _n : filter order // _za : output analog zeros [length: 0] // _pa : output analog poles [length: _n] // _ka : output analog gain void butter_azpkf(unsigned int _n, liquid_float_complex * _za, liquid_float_complex * _pa, liquid_float_complex * _ka) { unsigned int r = _n%2; unsigned int L = (_n - r)/2; unsigned int i; unsigned int k=0; for (i=0; i<L; i++) { float theta = (float)(2*(i+1) + _n - 1)*M_PI/(float)(2*_n); _pa[k++] = cexpf( _Complex_I*theta); _pa[k++] = cexpf(-_Complex_I*theta); } if (r) _pa[k++] = -1.0f; assert(k==_n); *_ka = 1.0; }
// // 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); }
void _fft(cplx buf[], cplx out[], int n, int step){ int i; if (step < n) { _fft(out, buf, n, step * 2); _fft(out + step, buf + step, n, step * 2); for (i = 0; i < n; i += 2 * step){ cplx t = cexpf(-I * PI * i / n) * out[i + step]; buf[i / 2] = out[i] + t; buf[(i + n)/2] = out[i] - t; } } }
// // 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); }