1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1995,1996 */
6 /* All Rights Reserved. */
7 /* */
8 /* Permission is hereby granted, free of charge, to use and distribute */
9 /* this software and its documentation without restriction, including */
10 /* without limitation the rights to use, copy, modify, merge, publish, */
11 /* distribute, sublicense, and/or sell copies of this work, and to */
12 /* permit persons to whom this work is furnished to do so, subject to */
13 /* the following conditions: */
14 /* 1. The code must retain the above copyright notice, this list of */
15 /* conditions and the following disclaimer. */
16 /* 2. Any modifications must be clearly marked as such. */
17 /* 3. Original authors' names are not deleted. */
18 /* 4. The authors' names are not used to endorse or promote products */
19 /* derived from this software without specific prior written */
20 /* permission. */
21 /* */
22 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30 /* THIS SOFTWARE. */
31 /* */
32 /*************************************************************************/
33 /* Author : Paul Taylor */
34 /* Date : August 1995 */
35 /*-----------------------------------------------------------------------*/
36 /* EST_Track Auxiliary routines */
37 /* */
38 /*=======================================================================*/
39
40 #include <cmath>
41 #include <cstdlib>
42 #include "EST_cutils.h"
43 #include "EST_simplestats.h"
44 #include "EST_sort.h"
45 #include "EST_Track.h"
46 #include "EST_TrackFile.h"
47 #include "EST_Option.h"
48 #include "EST_track_aux.h"
49 #include "EST_error.h"
50
51 //static inline int irint(float f) { return (int)(f+0.5); }
52 //static inline int irint(double f) { return (int)(f+0.5); }
53 //static inline int ifloor(float f) { return (int)(f); }
54
55 float correlation(EST_Track &a, EST_Track &b, int cha, int chb);
56
57 /* Allow EST_Track to be used in an EST_Val */
VAL_REGISTER_CLASS(track,EST_Track)58 VAL_REGISTER_CLASS(track,EST_Track)
59
60 static int sorttest(const void *a, const void *b)
61 { // for use with qsort C library function.
62 float *c = (float *)a;
63 float *d = (float *)b;
64 float res = (*c - *d);
65 if (res == 0.0)
66 return 0;
67 return (res < 0.0) ? -1 : 1;
68 }
69
track_smooth(EST_Track & c,float x,EST_String stype)70 void track_smooth(EST_Track &c, float x, EST_String stype)
71 {
72 if (stype == "median")
73 time_med_smooth(c, x);
74 else
75 time_mean_smooth(c, x);
76 }
77
time_med_smooth(EST_Track & c,float x)78 void time_med_smooth(EST_Track &c, float x)
79 {
80 if (!c.equal_space())
81 {
82 cerr << "Error: Time smoothing can only operate on fixed contours\n";
83 return;
84 }
85 // want to check for divide by zero
86 if (c.shift() == 0.0)
87 {
88 cerr << "Error in smoothing: time spacing problem\n";
89 return;
90 }
91 int n = (int)(x / c.shift());
92 for (int i = 0; i < c.num_channels(); ++i)
93 simple_med_smooth(c, n, i);
94 }
95
time_mean_smooth(EST_Track & c,float x)96 void time_mean_smooth(EST_Track &c, float x)
97 {
98 int j;
99 EST_Track t;
100 int n = (int)(x / c.shift());
101
102 for (j = 0; j < c.num_channels(); ++j)
103 simple_mean_smooth(c, n, j);
104 }
105
simple_med_smooth(EST_Track & c,int n,int channel)106 void simple_med_smooth(EST_Track &c, int n, int channel)
107 {// simple median smoother of order n
108
109
110 // windows longer than twice the track length cause problems
111 // here is one solution
112 if(n > c.num_frames())
113 n=c.num_frames();
114
115 // and tiny windows don't work either
116 // can't do median of 2 of fewer points
117 if(n < 3)
118 return;
119
120 int i, j, h, k;
121 float *a = new float[c.num_frames()];
122 float *m = new float[n];
123 h = n/2;
124
125
126 // sort start using < n order smoothing
127 for (i = 0; i < h; ++i)
128 {
129 k = (i * 2) + 1;
130 for (j = 0; j < k; ++j)
131 m[j] = c.a(j, channel);
132 qsort(m, k, sizeof(float), sorttest);
133 a[i] = m[i];
134 }
135
136 // sort main section using n order smoothing
137 for (i = h; i < c.num_frames() - h; ++i)
138 {
139 for (j = 0; j < n; ++j)
140 m[j] = c.a(i - h + j, channel);
141
142 qsort(m, n, sizeof(float), sorttest);
143 a[i] = m[h];
144 }
145 // sort end section using < n order smoothing
146 for (; i < c.num_frames(); ++i)
147 {
148 k = ((c.num_frames() - i)* 2) -1;
149 for (j = 0; j < k; ++j)
150 m[j] = c.a(i - (k/2) + j, channel);
151 qsort(m, k, sizeof(float), sorttest);
152 a[i] = m[k/2];
153 }
154
155 for (i = 0; i < c.num_frames(); ++i)
156 c.a(i,channel) = a[i];
157
158 delete [] a;
159 delete [] m;
160 }
161
simple_mean_smooth(EST_Track & c,int n,int channel)162 void simple_mean_smooth(EST_Track &c, int n, int channel)
163 { // simple mean smoother of order n
164 int i, j, h, k=1;
165 float *a = new float[c.num_frames()];
166 float sum;
167 h = n/2;
168
169 for (i = 0; i < h; ++i)
170 {
171 k = (i * 2) + 1;
172 sum = 0.0;
173 for (j = 0; j < k; ++j)
174 sum += c.a(j, channel);
175 a[i] = sum /(float) k;
176 }
177
178 k= h*2 + 1;
179
180 for (i = h; i < c.num_frames() - h; ++i)
181 {
182 sum = 0.0;
183 for (j = 0; j < k; ++j)
184 sum += c.a(i - h + j, channel);
185 a[i] = sum /(float) k;
186 }
187
188 for (; i < c.num_frames(); ++i)
189 {
190 k = ((c.num_frames() - i)* 2) -1;
191 sum = 0.0;
192 for (j = 0; j < k; ++j)
193 sum += c.a(i - (k/2) + j, channel);
194 a[i] = sum /(float) k;
195 }
196
197 for (i = 0; i < c.num_frames(); ++i)
198 c.a(i,channel) = a[i];
199
200 delete [] a;
201 }
202
absolute(EST_Track & tr)203 void absolute(EST_Track &tr)
204 {
205 int i, j;
206 for (i = 0; i < tr.num_frames(); ++i)
207 for (j = 0; j < tr.num_channels(); ++j)
208 tr.a(i, j) = fabs(tr.a(i, j));
209 }
210
normalise(EST_Track & tr)211 void normalise(EST_Track &tr)
212 {
213 EST_FVector mean, sd;
214
215 meansd(tr, mean, sd);
216 normalise(tr, mean, sd, -1.0, 1.0);
217 }
218
219 /* Normalise a list of tracks */
normalise(EST_TrackList & trlist,EST_FVector & mean,EST_FVector & sd,float upper,float lower)220 void normalise(EST_TrackList &trlist, EST_FVector &mean, EST_FVector &sd,
221 float upper, float lower)
222 {
223 for (EST_Litem *p = trlist.head(); p; p = p->next())
224 normalise(trlist(p), mean, sd, upper, lower);
225 }
226
227 /* Normalise by subtracting the mean and dividing by TWICE the
228 standard deviation. */
normalise(EST_Track & tr,EST_FVector & mean,EST_FVector & sd,float upper,float lower)229 void normalise(EST_Track &tr, EST_FVector &mean, EST_FVector &sd,
230 float upper, float lower)
231 {
232 for (int i = 0; i < tr.num_channels(); ++i)
233 normalise(tr, mean(i), sd(i), i, upper, lower);
234 }
235
normalise(EST_Track & tr,float mean,float sd,int channel,float upper,float lower)236 void normalise(EST_Track &tr, float mean, float sd, int channel,
237 float upper, float lower)
238 {
239 // This scales the data so that 2 standard deviations worth of values
240 // lie between upper and lower.
241 int i;
242 // cout << "upper = " << upper << " lower " << lower << endl;
243 for (i = 0; i < tr.num_frames(); ++i)
244 if (!tr.track_break(i))
245 tr.a(i, channel) = ((((tr.a(i, channel) - mean) / (4 *sd)) + 0.5)
246 * (upper -lower)) + lower;
247 }
248
differentiate(EST_Track & c,float samp_int)249 EST_Track differentiate(EST_Track &c, float samp_int)
250 {
251 // Differentiate track. SEE ALSO delta(EST_Track, int) which does
252 // this in a more sophisticated way!!!
253
254 EST_Track diff;
255 int i, j;
256 float dist;
257
258 if (samp_int != 0.0)
259 c.sample(samp_int);
260
261 diff.copy_setup(c);
262 diff.resize(c.num_frames() - 1, c.num_channels());
263
264 for (i = 0; i < diff.num_frames(); ++i)
265 {
266 dist = c.t(i + 1) - c.t(i);
267 for (j = 0; j < diff.num_channels(); ++j)
268 diff.a(i, j) = (c.track_break(i) || c.track_break(i + 1)) ? 0.0
269 : (c.a(i + 1) - c.a(i)) / dist;
270 diff.t(i) = c.t(i) + (dist / 2.0);
271 }
272
273 return diff;
274 }
275
difference(EST_Track & a,EST_Track & b)276 EST_Track difference(EST_Track &a, EST_Track &b)
277 {
278 int i, j;
279
280 int size = Lof(a.num_frames(), b.num_frames());
281 EST_Track diff = a;
282
283 // ERROR REORG - this needs to return a proper error
284 if (a.num_channels() != b.num_channels())
285 {
286 cerr << "Error: Can't compare " << a.num_channels() <<
287 " channel EST_Track with " << b.num_channels() << " channel EST_Track\n";
288 return diff;
289 }
290
291 for (i = 0; i < size; ++i)
292 for (j = 0; j < a.num_channels(); ++j)
293 diff.a(i, j) = a.a(i, j) - b.a(i, j);
294
295 return diff;
296 }
297
difference(EST_Track & a,EST_Track & b,int channel_a,int channel_b)298 EST_Track difference(EST_Track &a, EST_Track &b, int channel_a, int channel_b)
299 {
300 int i;
301
302 int size = Lof(a.num_frames(), b.num_frames());
303 EST_Track diff = a;
304
305 for (i = 0; i < size; ++i)
306 diff.a(i, channel_a) = a.a(i, channel_a) - b.a(i, channel_b);
307
308 return diff;
309 }
310
difference(EST_Track & a,EST_Track & b,EST_String fname)311 EST_Track difference(EST_Track &a, EST_Track &b, EST_String fname)
312 {
313 int ch_a, ch_b;
314 EST_Track cor;
315
316 if (!a.has_channel(fname))
317 {
318 cerr << "Error: Couldn't find field named " << fname <<
319 " in first Track\n";
320 return cor;
321 }
322
323 if (!b.has_channel(fname))
324 {
325 cerr << "Error: Couldn't find field named " << fname <<
326 " in second Track\n";
327 return cor;
328 }
329
330 ch_a = a.channel_position(fname);
331 ch_b = b.channel_position(fname);
332
333 return difference(a, b, ch_a, ch_b);
334 }
335
336
mean(const EST_Track & tr,int channel)337 float mean( const EST_Track &tr, int channel )
338 {
339 if ( channel<0 || channel >= tr.num_channels() )
340 EST_error( "Tried to access channel %d of %d channel track",
341 channel, tr.num_channels() );
342
343 float mean=0.0;
344 int i, n;
345 int tr_num_frames = tr.num_frames();
346
347 for( i=0, n=0; i<tr_num_frames; ++i )
348 if( !tr.track_break(i) ){
349 mean += tr.a_no_check( i, channel );
350 ++n;
351 }
352
353 return mean/(float)n;
354 }
355
mean(const EST_Track & tr,EST_FVector & m)356 void mean( const EST_Track &tr, EST_FVector &m )
357 {
358 unsigned int tr_num_channels = tr.num_channels();
359
360 m.resize( tr_num_channels, 0 );
361
362 for( unsigned int i=0; i<tr_num_channels; ++i )
363 m.a_no_check(i) = mean( tr, i );
364 }
365
366
367 /** Calculate the mead and standard deviation for a single channel of a track
368 */
369
meansd(EST_Track & tr,float & m,float & sd,int channel)370 void meansd(EST_Track &tr, float &m, float &sd, int channel)
371 {
372 int i, n;
373
374 m = mean( tr, channel );
375
376 float var=0.0;
377 int tr_num_frames = tr.num_frames();
378 for( i=0, n=0; i<tr_num_frames; ++i)
379 if( !tr.track_break(i) ){
380 var += pow(tr.a_no_check(i, channel) - m, float(2.0));
381 ++n;
382 }
383
384 if( n>1 ){ // use n, not tr_num_frames because of breaks
385 var /= (float) (n-1);
386 sd = sqrt(var);
387 }
388 else
389 sd = 0.0;
390 }
391
392 /** Calculate the root mean square error between the same channel in
393 two tracks
394 @see abs_error, rms_error
395 */
rms_error(EST_Track & a,EST_Track & b,int channel)396 float rms_error(EST_Track &a, EST_Track &b, int channel)
397 {
398 int i;
399 int size = Lof(a.num_frames(), b.num_frames());
400 float sum = 0;
401
402 for (i = 0; i < size; ++i)
403 if (a.val(i) && b.val(i))
404 sum += pow((a.a(i, channel) - b.a(i, channel)), float(2.0));
405
406 sum = sqrt(sum / size);
407 return sum;
408 }
409
abs_error(EST_Track & a,EST_Track & b,int channel)410 float abs_error(EST_Track &a, EST_Track &b, int channel)
411 {
412 int i;
413 int size = Lof(a.num_frames(), b.num_frames());
414 float sum = 0;
415 for (i = 0; i < size; ++i)
416 {
417 // cout << i << " " << a.a(i, channel) << " " << b.a(i, channel) << endl;
418 if (a.val(i) && b.val(i))
419 sum += fabs(a.a(i, channel) - b.a(i, channel));
420 }
421 return sum / size;
422 }
423
correlation(EST_Track & a,EST_Track & b,int channela,int channelb)424 float correlation(EST_Track &a, EST_Track &b, int channela, int channelb)
425 {
426 int i;
427 int size = Lof(a.num_frames(), b.num_frames());
428 float predict,real;
429 EST_SuffStats x,y,xx,yy,xy,se,e;
430 float cor,error;
431
432 for (i = 0; i < size; ++i)
433 if (a.val(i) && b.val(i))
434 {
435 // cout << a.t(i) << " " << a.a(i, channela) << " " << b.a(i, channelb) << endl;
436 predict = b.a(i, channelb);
437 real = a.a(i, channela);
438 x += predict;
439 y += real;
440 error = predict-real;
441 se += error*error;
442 e += fabs(error);
443 xx += predict*predict;
444 yy += real*real;
445 xy += predict*real;
446 }
447
448 cor = (xy.mean() - (x.mean()*y.mean()))/
449 (sqrt(xx.mean()-(x.mean()*x.mean())) *
450 sqrt(yy.mean()-(y.mean()*y.mean())));
451
452 // cout << xy.mean() << " " << x.mean() << " " << y.mean() << " "
453 // << xx.mean() << " " << yy.mean() << endl;
454
455 cout << "RMSE " << sqrt(se.mean()) << " Correlation is " << cor
456 << " Mean (abs) Error " << e.mean() << " (" << e.stddev() << ")"
457 << endl;
458 return cor;
459 }
460
meansd(EST_Track & a,EST_FVector & m,EST_FVector & sd)461 void meansd(EST_Track &a, EST_FVector &m, EST_FVector &sd)
462 {
463 int i;
464
465 m.resize(a.num_channels());
466 sd.resize(a.num_channels());
467
468 for (i = 0; i < a.num_channels(); ++i)
469 meansd(a, m[i], sd[i], i);
470 }
471
meansd(EST_TrackList & tl,float & mean,float & sd,int channel)472 void meansd(EST_TrackList &tl, float &mean, float &sd, int channel)
473 {
474 EST_Litem *p;
475 float var=0.0;
476 int i, n;
477
478 n = 0;
479 mean = 0.0;
480
481 for (p = tl.head(); p; p = p->next())
482 for (i = 0; i < tl(p).num_frames(); ++i)
483 {
484 if (!tl(p).track_break(i))
485 {
486 mean += tl(p).a(i, channel);
487 ++n;
488 }
489 }
490
491 mean /= n;
492
493 for (p = tl.head(); p; p = p->next())
494 for (i = 0; i < tl(p).num_frames(); ++i)
495 if (!tl(p).track_break(i))
496 var += pow(tl(p).a(i, channel) - mean, float(2.0));
497
498 var /= n;
499 sd = sqrt(var);
500 }
501
meansd(EST_TrackList & tl,EST_FVector & m,EST_FVector & sd)502 void meansd(EST_TrackList &tl, EST_FVector &m, EST_FVector &sd)
503 {
504 int i;
505
506 m.resize(tl.first().num_channels());
507 sd.resize(tl.first().num_channels());
508
509 for (i = 0; i < tl.first().num_channels(); ++i)
510 meansd(tl, m[i], sd[i], i);
511 }
512
rms_error(EST_Track & a,EST_Track & b)513 EST_FVector rms_error(EST_Track &a, EST_Track &b)
514 {
515 int i;
516 EST_FVector e;
517
518 // ERROR REORG - this needs to return a proper error
519 if (a.num_channels() != b.num_channels())
520 {
521 cerr << "Error: Can't compare " << a.num_channels() <<
522 " channel EST_Track with " << b.num_channels() << " channel EST_Track\n";
523 return e;
524 }
525 e.resize(a.num_channels());
526 for (i = 0; i < a.num_channels(); ++i)
527 e[i] = rms_error(a, b, i);
528
529 return e;
530 }
531
abs_error(EST_Track & a,EST_Track & b)532 EST_FVector abs_error(EST_Track &a, EST_Track &b)
533 {
534 int i;
535 EST_FVector e;
536
537 // ERROR REORG - this needs to return a proper error
538 if (a.num_channels() != b.num_channels())
539 {
540 cerr << "Error: Can't compare " << a.num_channels() <<
541 " channel EST_Track with " << b.num_channels() << " channel EST_Track\n";
542 return e;
543 }
544 e.resize(a.num_channels());
545 for (i = 0; i < a.num_channels(); ++i)
546 e[i] = abs_error(a, b, i);
547
548 return e;
549 }
550
correlation(EST_Track & a,EST_Track & b)551 EST_FVector correlation(EST_Track &a, EST_Track &b)
552 {
553 int i;
554 EST_FVector cor;
555
556 // ERROR REORG - this needs to return a proper error
557 if (a.num_channels() != b.num_channels())
558 {
559 cerr << "Error: Can't compare " << a.num_channels() <<
560 " channel EST_Track with " << b.num_channels() << " channel EST_Track\n";
561 return cor;
562 }
563 cor.resize(a.num_channels());
564 for (i = 0; i < a.num_channels(); ++i)
565 cor[i] = correlation(a, b, i, i);
566
567 return cor;
568 }
569
correlation(EST_Track & a,EST_Track & b,EST_String fname)570 EST_FVector correlation(EST_Track &a, EST_Track &b, EST_String fname)
571 {
572 int ch_a, ch_b;
573 EST_FVector cor;
574
575 if (!a.has_channel(fname))
576 {
577 cerr << "Error: Couldn't find field named " << fname <<
578 " in first Track\n";
579 return cor;
580 }
581
582 if (!b.has_channel(fname))
583 {
584 cerr << "Error: Couldn't find field named " << fname <<
585 " in second Track\n";
586 return cor;
587 }
588
589 ch_a = a.channel_position(fname);
590 ch_b = b.channel_position(fname);
591
592 cor.resize(1);
593 cor[0] = correlation(a, b, ch_a, ch_b);
594
595 return cor;
596 }
597
error(EST_Track & ref,EST_Track & test,int relax)598 EST_Track error(EST_Track &ref, EST_Track &test, int relax)
599 {
600 int i, j, k, l;
601 EST_Track diff;
602 diff = ref;
603 float t;
604
605 // relaxation allows an error to be ignored near boundaries. The
606 // degree of relation specifies how many frames can be ignored.
607
608 float *r = new float[relax*3];
609
610 for (l = 0; l < ref.num_channels(); ++l)
611 for (i = 0; i < ref.num_frames(); ++i)
612 {
613 t = 0;
614 for (k = 0, j = Gof((i - relax), 0); j < i + relax + 1; ++j, ++k)
615 {
616 if (ref.a(i, l) > 0.5)
617 r[k] = ((j < test.num_frames()) && (test.a(j, l)> 0.6)) ?1
618 : 0.5;
619 else
620 r[k] = ((j < test.num_frames()) && (test.a(j, l)< 0.4)) ? -1
621 : -0.5;
622
623 // fix for relaxation
624 t = r[k];
625 }
626 // cout << "ref: " << ref.a(i, l) << " test:" << test.a(i, l) << " error:" << t << endl;
627 diff.a(i, l) = t;
628 }
629
630 delete [] r;
631 return diff;
632 }
633
align_to_track(EST_Track & tr,float & start,float & end)634 void align_to_track(EST_Track &tr, float &start, float &end)
635 {
636 int is, ie;
637
638 // cout << " in " << start << " " << end << "\n";
639
640 is = tr.index(start);
641 ie = tr.index(end);
642
643 // cout << " indexes " << is << " " << ie << "\n";
644
645 start = tr.t(is);
646 end = tr.t(ie);
647 // cout << " out " << start << " " << end << "\n";
648 }
649
align_to_track(EST_Track & tr,int & start,int & end,int sample_rate)650 void align_to_track(EST_Track &tr, int &start, int &end, int sample_rate)
651 {
652 float start_t = start/(float)sample_rate;
653 float end_t = end/(float)sample_rate;
654
655
656 // cout << "align " << start_t << " " << end_t << " " << sample_rate << "\n";
657 align_to_track(tr, start_t, end_t);
658 // cout << " gives " << start_t << " " << end_t << "\n";
659
660 start = (int)(start_t*sample_rate + 0.5);
661 end = (int)( end_t*sample_rate + 0.5);
662 }
663
move_to_frame_ends(EST_Track & tr,int & start,int & end,int sample_rate,float offset)664 void move_to_frame_ends(EST_Track &tr,
665 int &start, int &end,
666 int sample_rate,
667 float offset)
668 {
669 float start_t = start/(float)sample_rate;
670 float end_t = end/(float)sample_rate;
671
672 // cout << "move " << start_t << " " << end_t << " " << sample_rate << "\n";
673
674 int is = tr.index(start_t-offset);
675 int ie = tr.index(end_t-offset);
676
677 int start_s, start_c, start_e;
678 int end_s, end_c, end_e=0;
679
680 if (tr.has_channel(channel_length))
681 {
682 get_frame(tr, sample_rate, is, start_s, start_c, start_e);
683 get_frame(tr, sample_rate, ie, end_s, end_c, end_e);
684 }
685 else
686 {
687 start_s = (int)(tr.t(is) * sample_rate);
688 end_s = (int)(tr.t(ie) * sample_rate);
689 }
690
691 start = start_s + (int)(offset*sample_rate + 0.5);
692 end = end_e + (int)(offset*sample_rate + 0.5);
693 }
694
nearest_boundary(EST_Track & tr,float time,int sample_rate,float offset)695 int nearest_boundary(EST_Track &tr, float time, int sample_rate, float offset)
696 {
697 time -= offset;
698
699 float distance = 10000;
700
701 for (int i = 0; i < tr.num_frames(); ++i)
702 {
703 float start, center, end;
704
705 get_frame(tr, sample_rate, i, start, center, end);
706
707 // printf("nb %f: %d distance %f start %f\n", time, i, distance, start);
708
709 if (fabs(start-time) > distance)
710 return i-1;
711 distance = fabs(start-time);
712 }
713
714 return tr.num_frames();
715 }
716
move_start(EST_Track & tr,float shift)717 void move_start(EST_Track &tr, float shift)
718 {
719 for(int i=0; i<tr.num_frames(); i++)
720 tr.t(i) += shift;
721 }
722
set_start(EST_Track & tr,float start)723 void set_start(EST_Track &tr, float start)
724 {
725 float shift = start - tr.t(0);
726
727 move_start(tr, shift);
728 }
729
730
extract2(EST_Track & orig,float start,float end,EST_Track & ret)731 void extract2(EST_Track &orig, float start, float end, EST_Track &ret)
732 {
733 int from, to;
734 int i, j;
735 from = orig.index(start);
736 to = orig.index_below(end);
737
738 ret.copy_setup(orig);
739
740 ret.resize(to - from, orig.num_channels());
741
742 for (i = 0; i < ret.num_frames(); ++i)
743 for (j = 0; j < ret.num_channels(); ++j)
744 {
745 ret.a(i, j) = orig.a(i + from, j);
746 ret.t(i) = orig.t(i + from);
747 if (orig.track_break(i + from))
748 ret.set_break(i);
749 else
750 ret.set_value(i);
751 }
752
753
754 // cout << "from " << from << " to " << to << endl;
755 // cout << "times from " << orig.t(from) << " to " << orig.t(to) << endl;
756
757 // orig.sub_track(ret, from, to);
758 // cout << ret.num_frames() << " " << ret.start() << " " << ret.end() << endl;
759 // cout << "ret " << ret;
760 }
761
762
extract(EST_Track & orig,float start,float end,EST_Track & ret)763 void extract(EST_Track &orig, float start, float end, EST_Track &ret)
764 {
765 int new_num_frames;
766
767 ret.copy_setup(orig);
768
769 int i, j;
770 int is = 0, ie = 0;
771
772 is = orig.index(start);
773 ie = orig.index(end);
774
775 // check in case above results in negative length
776 new_num_frames = (ie - is) > 0 ?ie - is : 0;
777 ret.resize(new_num_frames, orig.num_channels());
778
779 for (i = 0; i < new_num_frames; ++i)
780 {
781 for (j = 0; j < orig.num_channels(); ++j)
782 ret.a(i, j) = orig.a(i + is, j);
783 ret.t(i) = orig.t(i + is);
784 if (orig.track_break(i + is))
785 ret.set_break(i);
786 else
787 ret.set_value(i);
788 }
789 }
790
get_order(const EST_Track & t,EST_CoefficientType type,int d)791 int get_order(const EST_Track &t, EST_CoefficientType type, int d)
792 {
793 int order;
794 EST_ChannelType start_c = (EST_ChannelType)EST_CoefChannelId(type, d, 0);
795 EST_ChannelType end_c = (EST_ChannelType)EST_CoefChannelId(type, d, 1);
796
797 if (t.has_channel(start_c))
798 if (t.has_channel(end_c))
799 order = t.channel_position(end_c) - t.channel_position(start_c);
800 else
801 order = t.num_channels()-t.channel_position(start_c)-1;
802 else
803 order=0;
804 return order;
805 }
806
get_order(const EST_Track & tr)807 int get_order(const EST_Track &tr)
808 {
809 int order=0;
810 EST_CoefficientType t;
811
812 for(t=cot_first; t <cot_free; t=(EST_CoefficientType)(t+1))
813 if ((order=get_order(tr,t))>0)
814 return order;
815
816 cout << "No coefficients in track\n";
817 return 0;
818 }
819
sum_lengths(const EST_Track & t,int sample_rate,int start_frame,int end_frame)820 int sum_lengths(const EST_Track &t,
821 int sample_rate,
822 int start_frame, int end_frame)
823 {
824 (void)sample_rate;
825 int l=0;
826
827 if (end_frame < 0)
828 end_frame = t.num_frames();
829
830 if (t.has_channel(channel_length))
831 for(int i=start_frame; i<end_frame; i++)
832 l += (int)t.a(i, channel_length);
833 else
834 {
835 cout << "no length channel";
836 }
837
838 return l;
839 }
840
get_start_positions(const EST_Track & t,int sample_rate,EST_TBuffer<int> & pos)841 void get_start_positions(const EST_Track &t, int sample_rate,
842 EST_TBuffer<int> &pos)
843 {
844 pos.ensure(t.num_frames());
845
846 if (!t.has_channel(channel_length))
847 {
848 cout << "no length channel\n";
849 return;
850 }
851
852 for(int i=0; i<t.num_frames(); i++)
853 {
854 int wstart, wcent, wend;
855 get_frame(t, sample_rate, i, wstart, wcent, wend);
856 pos[i] = wstart;
857 // cout << "frame " << i << " t " << t.t(i) << " sr " << sample_rate << " offset " << t.a(i,channel_offset) << " cent " << wcent << " pos " << wstart << "\n";
858 }
859 }
860
861
extract(EST_Track & tr,EST_Option & al)862 void extract(EST_Track &tr, EST_Option &al)
863 {
864 int from, to;
865 EST_Track sub_track;
866
867 if (al.present("-start"))
868 from = tr.index(al.fval("-start"));
869 else if (al.present("-from"))
870 from = al.ival("-from");
871 else
872 from = 0;
873
874 if (al.present("-end"))
875 to = tr.index(al.fval("-end"));
876 else if (al.present("-to"))
877 to = al.ival("-to");
878 else
879 to = tr.num_frames() - 1;
880
881 tr.sub_track(sub_track, from, to-from+1, 0, EST_ALL);
882 EST_Track tr2 = sub_track;
883 tr = tr2;
884 }
885
extract_channel(EST_Track & orig,EST_Track & nt,EST_IList & ch_list)886 void extract_channel(EST_Track &orig, EST_Track &nt, EST_IList &ch_list)
887 {
888 int new_ch, i, j, k;
889 EST_Litem *p;
890 new_ch = ch_list.length();
891
892 nt.copy_setup(orig);
893 nt.resize(orig.num_frames(), new_ch);
894
895 for (i = 0, p = ch_list.head(); p; p = p->next(), ++i)
896 {
897 k = ch_list(p);
898
899 if (k >= orig.num_channels())
900 EST_error("Tried to extract channel number %d from track with "
901 "only %d channels\n", k, orig.num_channels());
902
903 for (j = 0; j < orig.num_frames(); ++j)
904 nt.a(j, i) = orig.a(j, k);
905 nt.set_channel_name(orig.channel_name(k), i);
906 }
907 for (j = 0; j < orig.num_frames(); ++j)
908 nt.t(j) = orig.t(j);
909 }
910
ParallelTracks(EST_Track & a,EST_TrackList & list,const EST_String & style)911 void ParallelTracks(EST_Track &a, EST_TrackList &list,const EST_String &style)
912 {
913 // Make multi channel track out of list of tracks. There are two
914 // "styles". "0" means take the size of the first track in the list,
915 // "1" means take the size of the longest as the number of frames in
916 // the created track.
917 EST_Litem *p, *longest;
918 int num_channels, num_frames;
919 int i, j, k, n;
920
921 for (num_channels=0,p=list.head(); p; p=p->next())
922 num_channels += list(p).num_channels();
923
924 if (style == "first")
925 {
926 num_frames = list.first().num_frames();
927 longest = list.head();
928 }
929 else
930 {
931 if (style != "longest")
932 cerr << "EST_Track: unknown combine style \"" << style <<
933 "\" assuming longest" << endl;
934 for (num_frames = 0, longest = p = list.head(); p; p = p->next())
935 if (num_frames < list(p).num_frames())
936 {
937 num_frames = list(p).num_frames();
938 longest = p;
939 }
940 }
941
942 a.resize(num_frames, num_channels);
943 a.fill(0.0);
944
945 for (k = 0, p = list.head(); p; p = p->next())
946 {
947 n = Lof(num_frames, list(p).num_frames());
948 for (j = 0; j < list(p).num_channels(); ++j, ++k)
949 {
950 for (i = 0; i < n; ++i)
951 a(i, k) = list(p).a(i, j);
952 a.set_channel_name(list(p).channel_name(j), k);
953 }
954 }
955 // fill time with times from longest file.
956 for (i = 0; i < list(longest).num_frames(); ++i)
957 a.t(i) = list(longest).t(i);
958 }
959
channel_to_time(EST_Track & tr,int channel,float scale)960 void channel_to_time(EST_Track &tr, int channel, float scale)
961 {
962
963 for(int i=0; i < tr.num_frames(); i++)
964 {
965 tr.t(i) = tr.a(i,channel) * scale;
966 }
967 tr.set_equal_space(FALSE);
968 }
969
channel_to_time(EST_Track & tr,EST_ChannelType c,float scale)970 void channel_to_time(EST_Track &tr, EST_ChannelType c, float scale)
971 {
972 int channel = NO_SUCH_CHANNEL;
973
974 if (tr.map() != 0 && (channel = (tr.map()->get(c)) != NO_SUCH_CHANNEL))
975 {
976 channel_to_time(tr, channel, scale);
977 return;
978 }
979 else
980 {
981 cerr << "no channel '" << EST_default_channel_names.name(c) << "' = " << (int)c << "\n";
982 abort();
983 }
984 }
985
channel_to_time(EST_Track & tr,const EST_String c_name,float scale)986 void channel_to_time(EST_Track &tr, const EST_String c_name, float scale)
987 {
988 for (int c=0; c<tr.num_channels(); c++)
989 if (tr.channel_name(c) == c_name)
990 {
991 channel_to_time(tr, c, scale);
992 return;
993 }
994
995 cerr << "no channel named '" << c_name << "'\n";
996 abort();
997 }
998
channel_to_time_lengths(EST_Track & tr,int channel,float scale)999 void channel_to_time_lengths(EST_Track &tr, int channel, float scale)
1000 {
1001 float tt=0;
1002 for(int i=0; i < tr.num_frames(); i++)
1003 {
1004 // cout << "c_t_t " << i << " " << tt << "\n";
1005 tr.t(i) = tt;
1006 tt += tr.a(i,channel) * scale;
1007 }
1008 tr.set_equal_space(FALSE);
1009 }
1010
channel_to_time_lengths(EST_Track & tr,EST_ChannelType c,float scale)1011 void channel_to_time_lengths(EST_Track &tr, EST_ChannelType c, float scale)
1012 {
1013 int channel = NO_SUCH_CHANNEL;
1014
1015 if (tr.map()!=0 && (channel = tr.map()->get(c)) != NO_SUCH_CHANNEL)
1016 {
1017 channel_to_time_lengths(tr, channel, scale);
1018 return;
1019 }
1020 else
1021 {
1022 cerr << "no channel '" << EST_default_channel_names.name(c) << "' = " << (int)c << "\n";
1023 abort();
1024 }
1025 }
1026
channel_to_time_lengths(EST_Track & tr,const EST_String c_name,float scale)1027 void channel_to_time_lengths(EST_Track &tr, const EST_String c_name, float scale)
1028 {
1029 for (int c=0; c<tr.num_channels(); c++)
1030 if (tr.channel_name(c) == c_name)
1031 {
1032 channel_to_time_lengths(tr, c, scale);
1033 return;
1034 }
1035
1036 cerr << "no channel named '" << c_name << "'\n";
1037 abort();
1038 }
1039
options_subtrack(void)1040 EST_String options_subtrack(void)
1041 {
1042 return
1043 EST_String("")+
1044 "-start <float> Extract track starting at this time, \n"
1045 " specified in seconds\n\n"
1046 "-end <float> Extract track ending at this time, \n"
1047 " specified in seconds\n\n"
1048 "-from <int> Extract track starting at this frame position\n\n"
1049 "-to <int> Extract track ending at this frame position\n\n";
1050 }
1051
options_track_input(void)1052 EST_String options_track_input(void)
1053 {
1054 // The standard waveform input options
1055 return
1056 EST_String("")+
1057 "-itype <string> Input file type (optional). If no type is\n"
1058 " specified type is automatically derived from\n"
1059 " file's header. Supported types\n"
1060 " are: "+options_track_filetypes()+"\n\n"
1061 // remove ???
1062 "-ctype <string> Contour type: F0, track\n\n"
1063 "-s <float> Frame spacing of input in seconds, for unheadered input file\n\n"
1064 "-startt <float> Time of first frame, for formats which don't provide this\n\n"
1065 "-c <string> Select a subset of channels (starts from 0). \n"
1066 " Tracks can have multiple channels. This option \n"
1067 " specifies a list of numbers, refering to the channel \n"
1068 " numbers which are to be used for for processing. \n\n"+
1069 options_subtrack();
1070 }
1071
1072
options_track_output(void)1073 EST_String options_track_output(void)
1074 {
1075 // The standard track output options
1076 return
1077 EST_String("")+
1078 "-otype <string> {ascii}\n"+
1079 " Output file type, if unspecified ascii is\n"+
1080 " assumed, types are: "+options_track_filetypes()+", label\n\n"+
1081 "-S <float> Frame spacing of output in seconds. If this is \n"
1082 " different from the internal spacing, the contour is \n"
1083 " resampled at this spacing \n\n"
1084 "-o <ofile> Output filename, defaults to stdout\n\n";
1085 }
1086
track_info(EST_Track & t)1087 void track_info(EST_Track &t)
1088 {
1089 cout << t.name() << endl;
1090 cout << "Number of frames: " << t.num_frames() << endl;
1091 cout << "Number of channels: " << t.num_channels() << endl;
1092 cout << "File type: " << EST_TrackFile::map.name(t.file_type()) << endl;
1093 if (t.equal_space())
1094 cout << "Frame shift: " << t.shift() << endl;
1095 else
1096 cout << "Frame shift: varied" << endl;
1097 for (int i = 0; i < t.num_channels(); ++i)
1098 cout << "Channel: " << i << ": " << t.channel_name(i) << endl;
1099 }
1100
options_track_filetypes(void)1101 EST_String options_track_filetypes(void)
1102 {
1103 // Returns list of currently support track filetypes
1104 // Should be extracted from the list in EST_Track
1105
1106 return EST_TrackFile::options_short();
1107 }
1108
options_track_filetypes_long(void)1109 EST_String options_track_filetypes_long(void)
1110 {
1111 // Returns list of currently support track filetypes
1112 // Should be extracted from the list in EST_Track
1113
1114 return EST_TrackFile::options_supported();
1115 }
1116
1117