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