00001
00006 #include <bpm/bpm_wf.h>
00007
00008 doublewf_t* doublewf( int ns, double fs ) {
00009
00010 doublewf_t *w;
00011
00012 if ( fs <= 0 ) {
00013 bpm_error( "Cannot have sampling frequency <= 0. in doublewf()",
00014 __FILE__, __LINE__ );
00015 return NULL;
00016 }
00017
00018 if ( ns > MAX_ALLOWED_NS ) {
00019 bpm_error( "Maximum allowed number of samples exceeded, failed to allocate.",
00020 __FILE__, __LINE__ );
00021 return NULL;
00022 }
00023
00024 if ( ns > 1 ) {
00025 w = (doublewf_t*) calloc( 1, sizeof(doublewf_t) );
00026 if ( ! w ) {
00027 bpm_error( "Cannot allocate memory for waveform structure in doublewf()",
00028 __FILE__, __LINE__ );
00029 return NULL;
00030 }
00031 w->ns = ns;
00032 w->fs = fs;
00033 w->wf = (double*) calloc( w->ns, sizeof( double ) );
00034 if ( ! w->wf ) {
00035 bpm_error( "Cannot allocate memory for waveform data in doublewf()",
00036 __FILE__, __LINE__ );
00037 free( w );
00038 return NULL;
00039 }
00040 } else {
00041 bpm_error( "Invalid number of samples in doublewf()", __FILE__, __LINE__ );
00042 return NULL;
00043 }
00044
00045 return w;
00046 }
00047
00048
00049
00050 doublewf_t* doublewf_sample_series( int ns, double fs ) {
00051
00052 int i = 0;
00053 doublewf_t *w = doublewf( ns, fs );
00054
00055 if ( ! w ) return w;
00056 for ( i=0; i<w->ns; i++ ) w->wf[i] = (double) i;
00057
00058 return w;
00059 }
00060
00061
00062
00063 doublewf_t* doublewf_time_series( int ns, double fs ) {
00064
00065 int i = 0;
00066 doublewf_t *w = doublewf( ns, fs );
00067
00068 if ( ! w ) return w;
00069 for ( i=0; i<w->ns; i++ ) w->wf[i] = (double) i / w->fs;
00070
00071 return w;
00072 }
00073
00074
00075
00076 doublewf_t* doublewf_frequency_series( int ns, double fs ) {
00077
00078 int i = 0;
00079 doublewf_t *w = doublewf( ns, fs );
00080
00081 if ( ! w ) return w;
00082 for ( i=0; i<w->ns; i++ ) w->wf[i] = (double) i * w->fs / (double) w->ns;
00083
00084 return w;
00085 }
00086
00087
00088
00089 doublewf_t* doublewf_copy_new( doublewf_t *w ) {
00090
00091 int i = 0;
00092 doublewf_t *s = doublewf( w->ns, w->fs );
00093
00094 if ( ! s ) {
00095 bpm_error( "Cannot allocate memory in doublewf_copy_new()", __FILE__, __LINE__ );
00096 return NULL;
00097 };
00098
00099 for ( i=0; i<w->ns; i++ ) s->wf[i] = w->wf[i];
00100
00101 return s;
00102 }
00103
00104
00105
00106 int doublewf_copy( doublewf_t *copy, doublewf_t *src ) {
00107
00108 int i = 0;
00109
00110 if ( ! copy || ! src ) {
00111 bpm_error( "Invalid pointer arguments in doublewf_copy()", __FILE__, __LINE__ );
00112 return BPM_FAILURE;
00113 };
00114
00115 if ( doublewf_compat( copy, src ) ) {
00116 for ( i=0; i<copy->ns; i++ ) copy->wf[i] = src->wf[i];
00117 } else {
00118 bpm_error( "Incompatible waveforms for in doublewf_copy()", __FILE__, __LINE__ );
00119 return BPM_FAILURE;
00120 }
00121
00122 return BPM_SUCCESS;
00123 }
00124
00125
00126
00127 int doublewf_subset( doublewf_t *sub, doublewf_t *w, int i1, int i2 ) {
00128
00129 int i = 0;
00130
00131 if ( ! sub || ! w ) {
00132 bpm_error( "Invalid pointer arguments in doublewf_subset()", __FILE__, __LINE__ );
00133 return BPM_FAILURE;
00134 };
00135
00136
00137 sub->ns = 0;
00138 sub->fs = w->fs;
00139
00140 for ( i=MAX(0,i1); i<=MIN(w->ns-1,i2); i++ ) {
00141 sub->wf[i] = w->wf[i-i1];
00142 sub->ns++;
00143 }
00144
00145
00146 return BPM_SUCCESS;
00147 }
00148
00149
00150
00151 int doublewf_setvalues( doublewf_t *w, double *x ) {
00152
00153 int i = 0;
00154 if ( ! w || ! x ) {
00155 bpm_error( "Invalid pointer arguments in doublewf_setvalues()",
00156 __FILE__, __LINE__ );
00157 return BPM_FAILURE;
00158 }
00159
00160 for ( i=0; i<w->ns; i++ ) w->wf[i] = x[i];
00161
00162 return BPM_SUCCESS;
00163 }
00164
00165
00166
00167 int doublewf_setfunction( doublewf_t *w,
00168 double (*wffun)( double, int, double* ),
00169 int npars, double *par ) {
00170
00171 int i = 0;
00172 if ( ! w || ! wffun ) {
00173 bpm_error( "Invalid pointer arguments in doublewf_setfunction()",
00174 __FILE__, __LINE__ );
00175 return BPM_FAILURE;
00176 }
00177
00178 for ( i=0; i<w->ns; i++ ) w->wf[i] = (*wffun)( (double) i / w->fs, npars, par );
00179
00180 return BPM_SUCCESS;
00181 }
00182
00183
00184
00185 int doublewf_reset( doublewf_t *w ) {
00186
00187 int i = 0;
00188
00189 if ( ! w ) {
00190 bpm_error( "Invalid pointer argument in doublewf_reset()",
00191 __FILE__, __LINE__ );
00192 return BPM_FAILURE;
00193 }
00194
00195 for ( i=0; i<w->ns; i++ ) w->wf[i] = 0.;
00196
00197 return BPM_SUCCESS;
00198 }
00199
00200
00201
00202 void doublewf_delete( doublewf_t *w ) {
00203
00204 if ( w ) {
00205 if ( w->wf ) free( w->wf ); else
00206 bpm_warning( "Cannot free doublewf_t::wf pointer in doublewf()_delete, already NULL !",
00207 __FILE__, __LINE__ );
00208 free( w );
00209 } else {
00210 bpm_warning( "Cannot free doublewf_t pointer in doublewf()_delete, already NULL !",
00211 __FILE__, __LINE__ );
00212 }
00213
00214 return;
00215 }
00216
00217
00218
00219 intwf_t* intwf_cast_new( doublewf_t *w ) {
00220
00221 int i = 0;
00222 intwf_t *iw;
00223
00224 if ( ! w ) {
00225 bpm_error( "Invalid pointer argument in intwf_cast_new()",
00226 __FILE__, __LINE__ );
00227 return NULL;
00228 }
00229
00230 iw = intwf( w->ns, w->fs );
00231 if ( ! iw ) {
00232 bpm_error( "Cannot allocate memory for intwf_t in intwf_cast_new()",
00233 __FILE__, __LINE__ );
00234 return NULL;
00235 }
00236
00237
00238 for (i=0;i<iw->ns;i++) iw->wf[i] = (int) dround( w->wf[i] );
00239
00240 return iw;
00241 }
00242
00243
00244
00245 int intwf_cast( intwf_t *iw, doublewf_t *w ) {
00246
00247 int i = 0;
00248
00249 if ( ! w || ! iw ) {
00250 bpm_error( "Invalid pointer argument in intwf_cast()",
00251 __FILE__, __LINE__ );
00252 return BPM_FAILURE;
00253 }
00254
00255
00256 for (i=0;i<iw->ns;i++) iw->wf[i] = (int) dround( w->wf[i] );
00257
00258 return BPM_SUCCESS;
00259 }
00260
00261
00262
00263 int doublewf_compat( doublewf_t *w1, doublewf_t *w2 ) {
00264
00265 if ( ! w1 || ! w2 ) {
00266 bpm_error( "Invalid pointer arguments in doublewf_compat()",
00267 __FILE__, __LINE__ );
00268 return 0;
00269 }
00270
00271 return ((w1->ns==w2->ns)&&(fabs(w1->fs-w2->fs)<WF_EPS)?1:0);
00272 }
00273
00274
00275
00276 int doublewf_add( doublewf_t *w1, doublewf_t *w2 ) {
00277
00278 int i = 0;
00279
00280 if ( ! w1 || ! w2 ) {
00281 bpm_error( "Invalid pointer arguments in doublewf_add()",
00282 __FILE__, __LINE__ );
00283 return BPM_FAILURE;
00284 }
00285
00286 if ( ! doublewf_compat( w1, w2 ) ) {
00287 bpm_warning( "Incompatible waveforms in doublewf_add()", __FILE__, __LINE__ );
00288 }
00289
00290 for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) w1->wf[i] += w2->wf[i];
00291
00292 return BPM_SUCCESS;
00293 }
00294
00295
00296
00297 int doublewf_subtract( doublewf_t *w1, doublewf_t *w2 ) {
00298
00299 int i = 0;
00300
00301 if ( ! w1 || ! w2 ) {
00302 bpm_error( "Invalid pointer arguments in doublewf_subtract()",
00303 __FILE__, __LINE__ );
00304 return BPM_FAILURE;
00305 }
00306
00307 if ( ! doublewf_compat( w1, w2 ) ) {
00308 bpm_warning( "Incompatible waveforms in doublewf_subtract()", __FILE__, __LINE__ );
00309 }
00310 for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) w1->wf[i] -= w2->wf[i];
00311
00312 return BPM_SUCCESS;
00313 }
00314
00315
00316
00317 int doublewf_multiply( doublewf_t *w1, doublewf_t *w2 ) {
00318
00319 int i = 0;
00320
00321 if ( ! w1 || ! w2 ) {
00322 bpm_error( "Invalid pointer arguments in doublewf_multiply()",
00323 __FILE__, __LINE__ );
00324 return BPM_FAILURE;
00325 }
00326
00327 if ( ! doublewf_compat( w1, w2 ) ) {
00328 bpm_warning( "Incompatible waveforms in doublewf_multiply()",
00329 __FILE__, __LINE__ );
00330 }
00331 for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) w1->wf[i] *= w2->wf[i];
00332
00333 return BPM_SUCCESS;
00334 }
00335
00336
00337
00338 int doublewf_divide( doublewf_t *w1, doublewf_t *w2 ) {
00339
00340 int i = 0;
00341
00342 if ( ! w1 || ! w2 ) {
00343 bpm_error( "Invalid pointer arguments in doublewf_divide()",
00344 __FILE__, __LINE__ );
00345 return BPM_FAILURE;
00346 }
00347
00348 if ( ! doublewf_compat( w1, w2 ) ) {
00349 bpm_warning( "Incompatible waveforms in doublewf_divide()",
00350 __FILE__, __LINE__ );
00351 }
00352
00353 for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) {
00354 if ( w2->wf[i] != 0. ) {
00355 w1->wf[i] /= w2->wf[i] ;
00356 } else {
00357 bpm_warning( "Trapped division by 0. in doublewf_divide()",
00358 __FILE__, __LINE__ );
00359 w1->wf[i] = 0.;
00360 }
00361 }
00362
00363 return BPM_SUCCESS;
00364 }
00365
00366
00367
00368 int doublewf_scale( double f, doublewf_t *w ) {
00369
00370 int i = 0;
00371
00372 if ( ! w ) {
00373 bpm_error( "Invalid pointer argument in doublewf_scale()",
00374 __FILE__, __LINE__ );
00375 return BPM_FAILURE;
00376 }
00377
00378 for ( i=0; i<w->ns; i++ ) w->wf[i] *= f;
00379
00380 return BPM_SUCCESS;
00381 }
00382
00383
00384
00385 int doublewf_bias( double c, doublewf_t *w ) {
00386
00387 int i = 0;
00388
00389 if ( ! w ) {
00390 bpm_error( "Invalid pointer argument in doublewf_bias()",
00391 __FILE__, __LINE__ );
00392 return BPM_FAILURE;
00393 }
00394
00395 for ( i=0; i<w->ns; i++ ) w->wf[i] += c;
00396
00397 return BPM_SUCCESS;
00398 }
00399
00400
00401
00402 int doublewf_add_cwtone( doublewf_t *w, double amp, double phase, double freq,
00403 double phasenoise ) {
00404
00405 int i = 0;
00406
00407 if ( ! w ) {
00408 bpm_error( "Invalid pointer argument in doublewf_add_cwtone()",
00409 __FILE__, __LINE__ );
00410 return BPM_FAILURE;
00411 }
00412
00413 for (i=0; i<w->ns; i++ )
00414 w->wf[i] += amp * cos( 2. * PI * freq * (double) i / w->fs +
00415 nr_rangauss( phase, phasenoise ) );
00416
00417 return BPM_SUCCESS;
00418 }
00419
00420
00421
00422 int doublewf_add_dcywave( doublewf_t *w, double amp, double phase, double freq,
00423 double ttrig, double tdcy, double phasenoise ) {
00424
00425 int i = 0;
00426 double t = 0.;
00427
00428 if ( ! w ) {
00429 bpm_error( "Invalid pointer argument in doublewf_add_dcywave()",
00430 __FILE__, __LINE__ );
00431 return BPM_FAILURE;
00432 }
00433
00434 for (i=0; i<w->ns; i++ ) {
00435 t = (double) i / w->fs;
00436 if ( t >= ttrig ) {
00437 w->wf[i] += amp * exp( -( t - ttrig ) / tdcy ) *
00438 cos( 2. * PI * freq * ( t - ttrig ) + nr_rangauss( phase, phasenoise ) );
00439 }
00440 }
00441
00442 return BPM_SUCCESS;
00443 }
00444
00445
00446
00447 int doublewf_add_ampnoise( doublewf_t *w, double sigma ) {
00448
00449 int i = 0;
00450
00451 if ( ! w ) {
00452 bpm_error( "Invalid pointer argument in doublewf_add_ampnoise()",
00453 __FILE__, __LINE__ );
00454 return BPM_FAILURE;
00455 }
00456
00457 for (i=0; i<w->ns; i++ ) {
00458 w->wf[i] += nr_rangauss( 0., sigma );
00459 }
00460
00461 return BPM_SUCCESS;
00462
00463 }
00464
00465
00466
00467 int doublewf_basic_stats( doublewf_t *w, int s0, int s1, wfstat_t *stats ) {
00468
00469 int i = 0;
00470
00471 if ( ! w || ! stats ) {
00472 bpm_error( "Invalid pointer arguments in doublewf_basic_stats()",
00473 __FILE__, __LINE__ );
00474 return BPM_FAILURE;
00475 }
00476
00477
00478 wfstat_reset( stats );
00479
00480
00481 if ( s0 > s1 ) {
00482 bpm_warning( "Swapping limits in doublewf_basic_stats()", __FILE__, __LINE__ );
00483 i=s1; s1=s0; s0=i;
00484 }
00485
00486
00487 if ( s0 < 0 ) s0 = 0;
00488 if ( s1 >= w->ns ) s1 = w->ns-1;
00489
00490 for (i=s0; i<=s1; i++ ) {
00491
00492 stats->mean += w->wf[i];
00493 stats->rms += SQR( w->wf[i] );
00494
00495 if ( w->wf[i] > stats->max ) { stats->max = w->wf[i]; stats->imax = i; }
00496 if ( w->wf[i] < stats->min ) { stats->min = w->wf[i]; stats->imin = i; }
00497 }
00498
00499 stats->mean /= (double) ( s1 - s0 + 1.);
00500 stats->rms = sqrt( stats->rms / (double) ( s1 - s0 + 1.) - SQR( stats->mean ) );
00501
00502 return BPM_SUCCESS;
00503 }
00504
00505
00506
00507 int doublewf_derive( doublewf_t *w ) {
00508
00509 int i = 0;
00510 double dt = 0;
00511
00512 if ( ! w ) {
00513 bpm_error( "Invalid pointer argument in doublewf_derive()",
00514 __FILE__, __LINE__ );
00515 return BPM_FAILURE;
00516 }
00517
00518
00519 dt = 1./w->fs;
00520
00521
00522 for ( i=0; i<w->ns-1; i++ ) w->wf[i] = ( w->wf[i+1] - w->wf[i] ) / dt;
00523
00524
00525 w->wf[w->ns-1] = w->wf[w->ns-2];
00526
00527 return BPM_SUCCESS;
00528 }
00529
00530
00531
00532 int doublewf_integrate( doublewf_t *w ) {
00533
00534 int i = 0;
00535 double dt = 0;
00536
00537 if ( ! w ) {
00538 bpm_error( "Invalid pointer argument in doublewf_integrate()",
00539 __FILE__, __LINE__ );
00540 return BPM_FAILURE;
00541 }
00542
00543
00544 dt = 1./w->fs;
00545
00546
00547 for ( i=0; i<w->ns; i++ ) {
00548 w->wf[i] *= dt;
00549 if ( i > 0 ) w->wf[i] += w->wf[i-1];
00550 }
00551
00552 return BPM_SUCCESS;
00553 }
00554
00555
00556 void doublewf_print( FILE *of, doublewf_t *w ) {
00557
00558 int i = 0;
00559 if ( !of || !w ) {
00560 bpm_error( "Invalid pointers in doublewf_print()", __FILE__, __LINE__ );
00561 return;
00562 }
00563
00564 fprintf( of, "Waveform:\n" );
00565 fprintf( of, "Number of samples : %d\n", w->ns );
00566 fprintf( of, "Sampling frequency : %f MHz\n", w->fs / MHz );
00567 for( i = 0; i < w->ns; i++ ) fprintf( of, " wf[%5d] = %.14e \n", i, w->wf[i] );
00568 fflush( of );
00569
00570 return;
00571 }
00572
00573
00574
00575 double doublewf_getvalue( doublewf_t *w, double t, unsigned int mode ) {
00576
00577 double val = 0.;
00578 int i = 0, i0 = 0, i1 = 0;
00579
00580 int lanczos_a = 3;
00581
00582 if ( ! w ) {
00583 bpm_error( "Invalid pointer argument in doublewf_sample()",
00584 __FILE__, __LINE__ );
00585 return -DBL_MAX;
00586 }
00587
00588
00589 if ( mode & WF_LANCZOS ) {
00590 for ( i=0; i<w->ns; i++ ) {
00591 val += w->wf[i] * lanczos( ( t - (double) i / w->fs ) * w->fs, lanczos_a );
00592 }
00593 return val;
00594
00595 }
00596
00597
00598 if ( mode & WF_SINC ) {
00599 for ( i=0; i<w->ns; i++ ) {
00600 val += w->wf[i] * sinc( ( t - (double) i / w->fs ) * w->fs );
00601 }
00602 return val;
00603
00604 }
00605
00606
00607 i0 = (int) ( t * w->fs );
00608 i1 = i0 + 1;
00609
00610 if ( i0 < 0 ) i0 = 0;
00611 if ( i0 > w->ns-2 ) i0 = w->ns-2;
00612
00613 if ( i1 < 1 ) i1 = 1;
00614 if ( i1 > w->ns-1 ) i1 = w->ns-1;
00615
00616
00617
00618 if ( mode & WF_LINEAR ) {
00619 val = w->wf[i0] + ( w->wf[i1] - w->wf[i0] ) * ( t * w->fs - (double) i0 );
00620 return val;
00621 }
00622
00623
00624
00625 if ( mode & WF_QUADRATIC ) {
00626
00627 if ( ( t*w->fs - (double) i0 ) < 0.5 ) {
00628 if ( i0 > 0 ) {
00629 return nr_quadinterpol( t,
00630 (double)(i0-1)/w->fs, (double)i0/w->fs, (double)(i1)/w->fs,
00631 w->wf[i0-1], w->wf[i0], w->wf[i1] );
00632 } else {
00633 return nr_quadinterpol( t,
00634 (double)i0/w->fs, (double)i1/w->fs, (double)(i1+1)/w->fs,
00635 w->wf[i0], w->wf[i1], w->wf[i1+1] );
00636 }
00637
00638 } else {
00639
00640 if ( i1 < w->ns-1 ) {
00641 return nr_quadinterpol( t,
00642 (double)i0/w->fs, (double)i1/w->fs, (double)(i1+1)/w->fs,
00643 w->wf[i0], w->wf[i1], w->wf[i1+1] );
00644 } else {
00645 return nr_quadinterpol( t,
00646 (double)(i0-1)/w->fs, (double)i0/w->fs, (double)(i1)/w->fs,
00647 w->wf[i0-1], w->wf[i0], w->wf[i1] );
00648 }
00649
00650 }
00651
00652 }
00653
00654
00655 if ( ( t * w->fs - (double) i0 ) < 0.5 ) {
00656 return w->wf[i0];
00657 } else return w->wf[i1];
00658
00659 return -DBL_MAX;
00660 }
00661
00662
00663
00664 int doublewf_resample( doublewf_t *w2, double fs, doublewf_t *w1, unsigned int mode ) {
00665
00666 int i = 0;
00667 if ( ! w1 || ! w2 ) {
00668 bpm_error( "Invalid pointer arguments in doublewf_resample()",
00669 __FILE__, __LINE__ );
00670 return BPM_FAILURE;
00671 }
00672
00673
00674 w2->ns = (int) (w1->ns * fs / w1->fs);
00675 w2->fs = fs;
00676
00677 if ( w2->ns > MAX_ALLOWED_NS ) {
00678 bpm_error( "Maximum allowed number of samples exceeded in doublewf_resample()",
00679 __FILE__, __LINE__ );
00680 return BPM_FAILURE;
00681 }
00682
00683 if ( w2->ns < 1 ) {
00684 bpm_error( "Number of new samples is zero in doublewf_resample()",
00685 __FILE__, __LINE__ );
00686 return BPM_FAILURE;
00687 }
00688
00689
00690 for ( i=0; i<w2->ns; i++ ) {
00691 w2->wf[i] = doublewf_getvalue( w1, (double) i / w2->fs, mode );
00692 }
00693
00694
00695 return BPM_SUCCESS;
00696 }