// create a resamp2 object // _m : filter semi-length (effective length: 4*_m+1) // _fc : center frequency of half-band filter // _As : stop-band attenuation [dB], _As > 0 RESAMP2() RESAMP2(_create)(unsigned int _m, float _fc, float _As) { // validate input if (_m < 2) { fprintf(stderr,"error: resamp2_%s_create(), filter semi-length must be at least 2\n", EXTENSION_FULL); exit(1); } RESAMP2() q = (RESAMP2()) malloc(sizeof(struct RESAMP2(_s))); q->m = _m; q->fc = _fc; q->As = _As; if ( q->fc < -0.5f || q->fc > 0.5f ) { fprintf(stderr,"error: resamp2_%s_create(), fc (%12.4e) must be in (-1,1)\n", EXTENSION_FULL, q->fc); exit(1); } // change filter length as necessary q->h_len = 4*(q->m) + 1; q->h = (TC *) malloc((q->h_len)*sizeof(TC)); q->h1_len = 2*(q->m); q->h1 = (TC *) malloc((q->h1_len)*sizeof(TC)); // design filter prototype unsigned int i; float t, h1, h2; TC h3; float beta = kaiser_beta_As(q->As); for (i=0; i<q->h_len; i++) { t = (float)i - (float)(q->h_len-1)/2.0f; h1 = sincf(t/2.0f); h2 = kaiser(i,q->h_len,beta,0); #if TC_COMPLEX == 1 h3 = cosf(2.0f*M_PI*t*q->fc) + _Complex_I*sinf(2.0f*M_PI*t*q->fc); #else h3 = cosf(2.0f*M_PI*t*q->fc); #endif q->h[i] = h1*h2*h3; } // resample, alternate sign, [reverse direction] unsigned int j=0; for (i=1; i<q->h_len; i+=2) q->h1[j++] = q->h[q->h_len - i - 1]; // create dotprod object q->dp = DOTPROD(_create)(q->h1, 2*q->m); // create window buffers q->w0 = WINDOW(_create)(2*(q->m)); q->w1 = WINDOW(_create)(2*(q->m)); RESAMP2(_clear)(q); return q; }
// parameterized function float gsfunc(float _x, float * _v) { float c0 = _v[0]; float c1 = _v[1]; float c2 = _v[2]; return c0 + sincf(c1*(_x-c2)); }
// Design FIR using kaiser window // _n : filter length, _n > 0 // _fc : cutoff frequency, 0 < _fc < 0.5 // _As : stop-band attenuation [dB], _As > 0 // _mu : fractional sample offset, -0.5 < _mu < 0.5 // _h : output coefficient buffer, [size: _n x 1] void liquid_firdes_kaiser(unsigned int _n, float _fc, float _As, float _mu, float *_h) { // validate inputs if (_mu < -0.5f || _mu > 0.5f) { fprintf(stderr,"error: liquid_firdes_kaiser(), _mu (%12.4e) out of range [-0.5,0.5]\n", _mu); exit(1); } else if (_fc < 0.0f || _fc > 0.5f) { fprintf(stderr,"error: liquid_firdes_kaiser(), cutoff frequency (%12.4e) out of range (0, 0.5)\n", _fc); exit(1); } else if (_n == 0) { fprintf(stderr,"error: liquid_firdes_kaiser(), filter length must be greater than zero\n"); exit(1); } // choose kaiser beta parameter (approximate) float beta = kaiser_beta_As(_As); float t, h1, h2; unsigned int i; for (i=0; i<_n; i++) { t = (float)i - (float)(_n-1)/2 + _mu; // sinc prototype h1 = sincf(2.0f*_fc*t); // kaiser window h2 = kaiser(i,_n,beta,_mu); //printf("t = %f, h1 = %f, h2 = %f\n", t, h1, h2); // composite _h[i] = h1*h2; } }
int main() { // options unsigned int num_samples = 400; // number of samples float sig = 0.1f; // noise variance unsigned int num_iterations = 1000; // number of iterations to run float v[3] = {1, 1, 1}; unsigned int i; // range float xmin = 0.0f; float xmax = 6.0f; float dx = (xmax - xmin) / (num_samples-1); // generate data set float x[num_samples]; float y[num_samples]; for (i=0; i<num_samples; i++) { x[i] = xmin + i*dx; y[i] = sincf(x[i]) + randnf()*sig; } struct gsdataset q = {x, y, num_samples}; // create gradsearch object gradsearchprops_s gsprops; gradsearchprops_init_default(&gsprops); gsprops.delta = 1e-6f; // gradient approximation step size gsprops.gamma = 0.002f; // vector step size gsprops.alpha = 0.1f; // momentum parameter gsprops.mu = 0.999f; // decremental gamma paramter (best if not exactly 1.0) gradsearch gs = gradsearch_create((void*)&q, v, 3, gserror, LIQUID_OPTIM_MINIMIZE, &gsprops); float rmse; // execute search //rmse = gradsearch_run(gs, num_iterations, -1e-6f); // open 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"); // execute search one iteration at a time fprintf(fid,"u = zeros(1,%u);\n", num_iterations); for (i=0; i<num_iterations; i++) { rmse = gserror((void*)&q,v,3); fprintf(fid,"u(%3u) = %12.4e;\n", i+1, rmse); gradsearch_step(gs); if (((i+1)%100)==0) gradsearch_print(gs); } // print results printf("\n"); gradsearch_print(gs); printf(" c0 = %12.8f, opt = 1\n", v[0]); printf(" c1 = %12.8f, opt = 0\n", v[1]); printf(" c2 = %12.8f, opt = 1\n", v[2]); printf(" rmse = %12.4e\n", rmse); fprintf(fid,"figure;\n"); fprintf(fid,"semilogy(u);\n"); fprintf(fid,"xlabel('iteration');\n"); fprintf(fid,"ylabel('error');\n"); fprintf(fid,"title('gradient search results');\n"); fprintf(fid,"grid on;\n"); // save sampled data set for (i=0; i<num_samples; i++) { fprintf(fid," x(%4u) = %12.8f;\n", i+1, x[i]); fprintf(fid," y(%4u) = %12.8f;\n", i+1, y[i]); fprintf(fid," y_hat(%4u) = %12.8f;\n", i+1, gsfunc(x[i],v)); } fprintf(fid,"figure;\n"); fprintf(fid,"plot(x,y,'x', x,y_hat,'-');\n"); fprintf(fid,"xlabel('x');\n"); fprintf(fid,"ylabel('f(x)');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"legend('data','fit',1);\n"); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME); gradsearch_destroy(gs); return 0; }
// // AUTOTEST: sincf // void autotest_sincf() { float tol = 1e-3f; CONTEND_DELTA(sincf(0.0f), 1.0f, tol); }