1 /**
2 @file
3 @ingroup wave
4 */
5
6 #include <bpm/bpm_wf.h>
7
intwf(int ns,double fs)8 intwf_t* intwf( int ns, double fs ) {
9
10 intwf_t *w;
11
12 if ( fs <= 0 ) {
13 bpm_error( "Cannot have sampling frequency <= 0. in intwf()",
14 __FILE__, __LINE__ );
15 return NULL;
16 }
17
18 if ( ns > MAX_ALLOWED_NS ) {
19 bpm_error( "Maximum allowed number of samples exceeded, failed to allocate.",
20 __FILE__, __LINE__ );
21 return NULL;
22 }
23
24 if ( ns > 1 ) {
25 w = (intwf_t*) calloc( 1, sizeof(intwf_t) );
26 if ( ! w ) {
27 bpm_error( "Cannot allocate memory for waveform structure in intwf()",
28 __FILE__, __LINE__ );
29 return NULL;
30 }
31 w->ns = ns;
32 w->fs = fs;
33 w->wf = (int*) calloc( w->ns, sizeof( int ) );
34 if ( ! w->wf ) {
35 bpm_error( "Cannot allocate memory for waveform data in intwf()",
36 __FILE__, __LINE__ );
37 free( w );
38 return NULL;
39 }
40 } else {
41 bpm_error( "Invalid number of samples in intwf()", __FILE__, __LINE__ );
42 return NULL;
43 }
44
45 return w;
46 }
47
48 // ----------------------------------------------------------------------------
49
intwf_sample_series(int ns,double fs)50 intwf_t* intwf_sample_series( int ns, double fs ) {
51
52 int i = 0;
53 intwf_t *w = intwf( ns, fs );
54
55 if ( ! w ) return w;
56 for ( i=0; i<w->ns; i++ ) w->wf[i] = i;
57
58 return w;
59 }
60
61 // ----------------------------------------------------------------------------
62
intwf_copy_new(intwf_t * w)63 intwf_t* intwf_copy_new( intwf_t *w ) {
64
65 int i = 0;
66 intwf_t *s = intwf( w->ns, w->fs );
67
68 if ( ! s ) {
69 bpm_error( "Cannot allocate memory in intwf_copy_new()",
70 __FILE__, __LINE__ );
71 return NULL;
72 };
73
74 for ( i=0; i<w->ns; i++ ) s->wf[i] = w->wf[i];
75
76 return s;
77 }
78
79 // ----------------------------------------------------------------------------
80
intwf_copy(intwf_t * copy,intwf_t * src)81 int intwf_copy( intwf_t *copy, intwf_t *src ) {
82
83 int i = 0;
84
85 if ( ! copy || ! src ) {
86 bpm_error( "Invalid pointer arguments in intwf_copy()", __FILE__, __LINE__ );
87 return BPM_FAILURE;
88 };
89
90 if ( intwf_compat( copy, src ) ) {
91 for ( i=0; i<copy->ns; i++ ) copy->wf[i] = src->wf[i];
92 } else {
93 bpm_error( "Incompatible waveforms for in intwf_copy()", __FILE__, __LINE__ );
94 return BPM_FAILURE;
95 }
96
97 return BPM_SUCCESS;
98 }
99
100 // ----------------------------------------------------------------------------
101
intwf_subset(intwf_t * sub,intwf_t * w,int i1,int i2)102 int intwf_subset( intwf_t *sub, intwf_t *w, int i1, int i2 ) {
103
104 int i = 0;
105
106 if ( ! sub || ! w ) {
107 bpm_error( "Invalid pointer arguments in intwf_subset()", __FILE__, __LINE__ );
108 return BPM_FAILURE;
109 };
110
111 // reset the number of samples in the subset
112 sub->ns = 0;
113 sub->fs = w->fs;
114
115 for ( i=MAX(0,i1); i<=MIN(w->ns-1,i2); i++ ) {
116 sub->wf[i] = w->wf[i-i1];
117 sub->ns++;
118 }
119
120
121 return BPM_SUCCESS;
122 }
123
124 // ----------------------------------------------------------------------------
125
intwf_setvalues(intwf_t * w,int * x)126 int intwf_setvalues( intwf_t *w, int *x ) {
127
128 int i = 0;
129 if ( ! w || ! x ) {
130 bpm_error( "Invalid pointer arguments in intwf_setvalues()",
131 __FILE__, __LINE__ );
132 return BPM_FAILURE;
133 }
134
135 for ( i=0; i<w->ns; i++ ) w->wf[i] = x[i];
136
137 return BPM_SUCCESS;
138 }
139
140 // ----------------------------------------------------------------------------
141
intwf_setfunction(intwf_t * w,int (* wffun)(double,int,double *),int npars,double * par)142 int intwf_setfunction( intwf_t *w,
143 int (*wffun)( double, int, double* ),
144 int npars, double *par ) {
145
146 int i = 0;
147 if ( ! w || ! wffun ) {
148 bpm_error( "Invalid pointer arguments in intwf_setfunction()",
149 __FILE__, __LINE__ );
150 return BPM_FAILURE;
151 }
152
153 for ( i=0; i<w->ns; i++ ) w->wf[i] = (*wffun)( (double) i / w->fs, npars, par );
154
155 return BPM_SUCCESS;
156 }
157
158 // ----------------------------------------------------------------------------
159
intwf_reset(intwf_t * w)160 int intwf_reset( intwf_t *w ) {
161
162 int i = 0;
163
164 if ( ! w ) {
165 bpm_error( "Invalid pointer argument in intwf_reset()",
166 __FILE__, __LINE__ );
167 return BPM_FAILURE;
168 }
169
170 for ( i=0; i<w->ns; i++ ) w->wf[i] = 0;
171
172 return BPM_SUCCESS;
173 }
174
175 // ----------------------------------------------------------------------------
176
intwf_delete(intwf_t * w)177 void intwf_delete( intwf_t *w ) {
178
179 if ( w ) {
180 if ( w->wf ) free( w->wf ); else
181 bpm_warning( "Cannot free intwf_t::wf pointer in intwf()_delete, already NULL !",
182 __FILE__, __LINE__ );
183 free( w );
184 } else {
185 bpm_warning( "Cannot free intwf_t pointer in intwf()_delete, already NULL !",
186 __FILE__, __LINE__ );
187 }
188
189 return;
190 }
191
192 // ----------------------------------------------------------------------------
193
doublewf_cast_new(intwf_t * iw)194 doublewf_t* doublewf_cast_new( intwf_t *iw ) {
195
196 int i = 0;
197 doublewf_t *w;
198
199 if ( ! w ) {
200 bpm_error( "Invalid pointer argument in doublewf_cast_new()",
201 __FILE__, __LINE__ );
202 return NULL;
203 }
204
205 w = doublewf( iw->ns, iw->fs );
206 if ( ! w ) {
207 bpm_error( "Cannot allocate memory for doublewf_t in doublewf_cast_new()",
208 __FILE__, __LINE__ );
209 return NULL;
210 }
211
212 // cast to the double waveform
213 for (i=0;i<iw->ns;i++) w->wf[i] = (double) iw->wf[i];
214
215 return w;
216 }
217
218 // ----------------------------------------------------------------------------
219
doublewf_cast(doublewf_t * w,intwf_t * iw)220 int doublewf_cast( doublewf_t *w, intwf_t *iw ) {
221
222 int i = 0;
223
224 if ( ! w || ! iw ) {
225 bpm_error( "Invalid pointer argument in doublewf_cast()",
226 __FILE__, __LINE__ );
227 return BPM_FAILURE;
228 }
229
230 // cast to the double waveform
231 for (i=0;i<iw->ns;i++) w->wf[i] = (double) iw->wf[i];
232
233 return BPM_SUCCESS;
234 }
235
236 // ----------------------------------------------------------------------------
237
intwf_compat(intwf_t * w1,intwf_t * w2)238 int intwf_compat( intwf_t *w1, intwf_t *w2 ) {
239
240 if ( ! w1 || ! w2 ) {
241 bpm_error( "Invalid pointer arguments in intwf_compat()",
242 __FILE__, __LINE__ );
243 return 0;
244 }
245
246 return ((w1->ns==w2->ns)&&(fabs(w1->fs-w2->fs)<WF_EPS)?1:0);
247 }
248
249 // ----------------------------------------------------------------------------
250
intwf_add(intwf_t * w1,intwf_t * w2)251 int intwf_add( intwf_t *w1, intwf_t *w2 ) {
252
253 int i = 0;
254
255 if ( ! w1 || ! w2 ) {
256 bpm_error( "Invalid pointer arguments in intwf_add()",
257 __FILE__, __LINE__ );
258 return BPM_FAILURE;
259 }
260
261 if ( ! intwf_compat( w1, w2 ) ) {
262 bpm_warning( "Incompatible waveforms in intwf_add()", __FILE__, __LINE__ );
263 }
264 for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) w1->wf[i] += w2->wf[i];
265
266 return BPM_SUCCESS;
267 }
268
269 // ----------------------------------------------------------------------------
270
intwf_subtract(intwf_t * w1,intwf_t * w2)271 int intwf_subtract( intwf_t *w1, intwf_t *w2 ) {
272
273 int i = 0;
274
275 if ( ! w1 || ! w2 ) {
276 bpm_error( "Invalid pointer arguments in intwf_subtract()",
277 __FILE__, __LINE__ );
278 return BPM_FAILURE;
279 }
280
281 if ( ! intwf_compat( w1, w2 ) ) {
282 bpm_warning( "Incompatible waveforms in intwf_subtract()", __FILE__, __LINE__ );
283 }
284 for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) w1->wf[i] -= w2->wf[i];
285
286 return BPM_SUCCESS;
287 }
288
289 // ----------------------------------------------------------------------------
290
intwf_multiply(intwf_t * w1,intwf_t * w2)291 int intwf_multiply( intwf_t *w1, intwf_t *w2 ) {
292
293 int i = 0;
294
295 if ( ! w1 || ! w2 ) {
296 bpm_error( "Invalid pointer arguments in intwf_multiply()",
297 __FILE__, __LINE__ );
298 return BPM_FAILURE;
299 }
300
301 if ( ! intwf_compat( w1, w2 ) ) {
302 bpm_warning( "Incompatible waveforms in intwf_multiply()",
303 __FILE__, __LINE__ );
304 }
305
306 for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) w1->wf[i] *= w2->wf[i];
307
308 return BPM_SUCCESS;
309 }
310
311 // ----------------------------------------------------------------------------
312
intwf_divide(intwf_t * w1,intwf_t * w2)313 int intwf_divide( intwf_t *w1, intwf_t *w2 ) {
314
315 int i = 0;
316
317 if ( ! w1 || ! w2 ) {
318 bpm_error( "Invalid pointer arguments in intwf_divide()",
319 __FILE__, __LINE__ );
320 return BPM_FAILURE;
321 }
322
323 if ( ! intwf_compat( w1, w2 ) ) {
324 bpm_warning( "Incompatible waveforms in intwf_divide()",
325 __FILE__, __LINE__ );
326 }
327
328 for ( i=0; i < MIN(w1->ns,w2->ns); i++ ) {
329 if ( w2->wf[i] != 0. ) {
330 w1->wf[i] /= w2->wf[i] ;
331 } else {
332 bpm_warning( "Trapped division by 0. in intwf_divide()",
333 __FILE__, __LINE__ );
334 w1->wf[i] = 0.;
335 }
336 }
337
338 return BPM_SUCCESS;
339 }
340
341 // ----------------------------------------------------------------------------
342
intwf_scale(int f,intwf_t * w)343 int intwf_scale( int f, intwf_t *w ) {
344
345 int i = 0;
346
347 if ( ! w ) {
348 bpm_error( "Invalid pointer argument in intwf_scale()",
349 __FILE__, __LINE__ );
350 return BPM_FAILURE;
351 }
352
353 for ( i=0; i<w->ns; i++ ) w->wf[i] *= f;
354
355 return BPM_SUCCESS;
356 }
357
358 // ----------------------------------------------------------------------------
359
intwf_bias(int c,intwf_t * w)360 int intwf_bias( int c, intwf_t *w ) {
361
362 int i = 0;
363
364 if ( ! w ) {
365 bpm_error( "Invalid pointer argument in intwf_bias()",
366 __FILE__, __LINE__ );
367 return BPM_FAILURE;
368 }
369
370 for ( i=0; i<w->ns; i++ ) w->wf[i] += c;
371
372 return BPM_SUCCESS;
373 }
374
375 // ----------------------------------------------------------------------------
376
intwf_add_cwtone(intwf_t * w,double amp,double phase,double freq,double phasenoise)377 int intwf_add_cwtone( intwf_t *w, double amp, double phase, double freq,
378 double phasenoise ) {
379
380 int i = 0;
381
382 if ( ! w ) {
383 bpm_error( "Invalid pointer argument in intwf_add_cwtone()",
384 __FILE__, __LINE__ );
385 return BPM_FAILURE;
386 }
387
388 for (i=0; i<w->ns; i++ )
389 w->wf[i] += (int) dround ( amp * cos( 2. * PI * freq * (double) i / w->fs +
390 nr_rangauss( phase, phasenoise ) ) );
391
392 return BPM_SUCCESS;
393 }
394
395 // ----------------------------------------------------------------------------
396
intwf_add_dcywave(intwf_t * w,double amp,double phase,double freq,double ttrig,double tdcy,double phasenoise)397 int intwf_add_dcywave( intwf_t *w, double amp, double phase, double freq,
398 double ttrig, double tdcy, double phasenoise ) {
399
400 int i = 0;
401 double t = 0.;
402
403 if ( ! w ) {
404 bpm_error( "Invalid pointer argument in intwf_add_dcywave()",
405 __FILE__, __LINE__ );
406 return BPM_FAILURE;
407 }
408
409 for (i=0; i<w->ns; i++ ) {
410 t = (double) i / w->fs;
411 if ( t >= ttrig ) {
412 w->wf[i] += (int) dround( amp * exp( -( t - ttrig ) / tdcy ) *
413 cos( 2. * PI * freq * ( t - ttrig ) +
414 nr_rangauss( phase, phasenoise ) ) );
415 }
416 }
417
418 return BPM_SUCCESS;
419 }
420
421 // ----------------------------------------------------------------------------
422
intwf_add_ampnoise(intwf_t * w,double sigma)423 int intwf_add_ampnoise( intwf_t *w, double sigma ) {
424
425 int i = 0;
426
427 if ( ! w ) {
428 bpm_error( "Invalid pointer argument in intwf_add_ampnoise()",
429 __FILE__, __LINE__ );
430 return BPM_FAILURE;
431 }
432
433 for (i=0; i<w->ns; i++ ) {
434 w->wf[i] += (int) dround( nr_rangauss( 0., sigma ) );
435 }
436
437 return BPM_SUCCESS;
438
439 }
440
441 // ----------------------------------------------------------------------------
442
intwf_basic_stats(intwf_t * w,int s0,int s1,wfstat_t * stats)443 int intwf_basic_stats( intwf_t *w, int s0, int s1, wfstat_t *stats ) {
444
445 doublewf_t *dw = NULL;
446
447 if ( ! w || ! stats ) {
448 bpm_error( "Invalid pointer arguments in intwf_basic_stats()",
449 __FILE__, __LINE__ );
450 return BPM_FAILURE;
451 }
452
453 dw = doublewf_cast_new( w );
454 if ( ! dw ) {
455 bpm_error( "Cannot allocate memory for temporary doublewf in intwf_basic_stats",
456 __FILE__, __LINE__ );
457 return BPM_FAILURE;
458 }
459
460 if ( doublewf_basic_stats( dw, s0, s1, stats ) ) return BPM_FAILURE;
461
462 doublewf_delete( dw );
463
464 return BPM_SUCCESS;
465 }
466
467 // ----------------------------------------------------------------------------
468
intwf_derive(intwf_t * w)469 int intwf_derive( intwf_t *w ) {
470
471 int i = 0;
472 double dt = 0;
473
474 if ( ! w ) {
475 bpm_error( "Invalid pointer argument in intwf_derive()",
476 __FILE__, __LINE__ );
477 return BPM_FAILURE;
478 }
479
480 // the time step...
481 dt = 1./w->fs;
482
483 // derivative...
484 for ( i=0; i<w->ns-1; i++ ) w->wf[i] = (int) dround( ( w->wf[i+1] - w->wf[i] ) / dt );
485
486 // the last sample.. extrapolate linear, so same slope
487 w->wf[w->ns-1] = w->wf[w->ns-2];
488
489 return BPM_SUCCESS;
490 }
491
492 // ----------------------------------------------------------------------------
493
intwf_integrate(intwf_t * w)494 int intwf_integrate( intwf_t *w ) {
495
496 double tmp = 0., tmp_prev = 0.;
497 double dt = 0.;
498 int i = 0;
499
500 if ( ! w ) {
501 bpm_error( "Invalid pointer argument in intwf_integrate()",
502 __FILE__, __LINE__ );
503 return BPM_FAILURE;
504 }
505
506 // the time step...
507 dt = 1./w->fs;
508
509 // integral
510 for ( i=0; i<w->ns; i++ ) {
511 tmp = (double) w->wf[i];
512 tmp *= dt;
513
514 if ( i > 0 ) tmp += tmp_prev;
515
516 w->wf[i] = (int) dround( tmp );
517 tmp_prev = tmp;
518 }
519
520 return BPM_SUCCESS;
521 }
522
523 // ----------------------------------------------------------------------------
524
intwf_print(FILE * of,intwf_t * w)525 void intwf_print( FILE *of, intwf_t *w ) {
526
527 int i = 0;
528 if ( !of || !w ) {
529 bpm_error( "Invalid pointers in intwf_print()", __FILE__, __LINE__ );
530 return;
531 }
532
533 fprintf( of, "Waveform:\n" );
534 fprintf( of, "Number of samples : %d\n", w->ns );
535 fprintf( of, "Sampling frequency : %f MHz\n", w->fs / _MHz__ );
536 for( i = 0; i < w->ns; i++ ) fprintf( of, " wf[%5d] = %d \n", i, w->wf[i] );
537 fflush( of );
538
539 return;
540 }
541
542 // ----------------------------------------------------------------------------
543
intwf_getvalue(intwf_t * w,double t,unsigned int mode)544 int intwf_getvalue( intwf_t *w, double t, unsigned int mode ) {
545
546 int val = 0;
547 doublewf_t *dw = NULL;
548
549 if ( ! w ) {
550 bpm_error( "Invalid pointer arguments in intwf_getvalue()",
551 __FILE__, __LINE__ );
552 return BPM_FAILURE;
553 }
554
555 dw = doublewf_cast_new( w );
556 if ( ! dw ) {
557 bpm_error( "Cannot allocate memory for temporary doublewf in intwf_getvalue()",
558 __FILE__, __LINE__ );
559 return BPM_FAILURE;
560 }
561
562 val = (int) dround ( doublewf_getvalue( dw, t, mode ) );
563
564 doublewf_delete( dw );
565
566 return val;
567 }
568
569 // ----------------------------------------------------------------------------
570
intwf_resample(intwf_t * w2,double fs,intwf_t * w1,unsigned int mode)571 int intwf_resample( intwf_t *w2, double fs, intwf_t *w1, unsigned int mode ) {
572
573 int i = 0;
574 doublewf_t *dw = NULL;
575
576 if ( ! w1 || ! w2 ) {
577 bpm_error( "Invalid pointer arguments in intwf_resample()",
578 __FILE__, __LINE__ );
579 return BPM_FAILURE;
580 }
581
582 dw = doublewf_cast_new( w1 );
583 if ( ! dw ) {
584 bpm_error( "Cannot allocate memory for temporary doublewf in intwf_resample()",
585 __FILE__, __LINE__ );
586 return BPM_FAILURE;
587 }
588
589 // number of samples
590 w2->ns = (int) (w1->ns * fs / w1->fs);
591 w2->fs = fs;
592
593 if ( w2->ns > MAX_ALLOWED_NS ) {
594 bpm_error( "Maximum allowed number of samples exceeded in intwf_resample()",
595 __FILE__, __LINE__ );
596 return BPM_FAILURE;
597 }
598
599 if ( w2->ns < 1 ) {
600 bpm_error( "Number of new samples is zero in intwf_resample()",
601 __FILE__, __LINE__ );
602 return BPM_FAILURE;
603 }
604
605 // fill the new waveform
606 for ( i=0; i<w2->ns; i++ ) {
607 w2->wf[i] = (int) dround( doublewf_getvalue( dw, (double) i / w2->fs, mode ) );
608 }
609
610 doublewf_delete( dw );
611
612 return BPM_SUCCESS;
613 }
614