Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
EST_track_aux.cc
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 */
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 
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 
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 
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 
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 
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 
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 
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 */
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. */
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 
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 
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 
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 
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 
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 
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 
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 
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 */
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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