Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
EST_Track.cc
1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1994,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 /* */
34 /* Author : Paul Taylor */
35 /* Date : April 1994 */
36 /* ------------------------------------------------------------------- */
37 /* EST_Track Class source file */
38 /* */
39 /*************************************************************************/
40 
41 #include <fstream>
42 #include <iostream>
43 #include <cmath>
44 #include "EST_unix.h"
45 #include "EST_Track.h"
46 #include "EST_string_aux.h"
47 #include "EST_TrackFile.h"
48 #include "EST_error.h"
49 
50 const int EST_Track::default_sample_rate=16000; // occasionally needed for xmg files
51 const float EST_Track::default_frame_shift=0.005; // default frame spacing.
52 
53 const EST_String DEF_FILE_TYPE = "est";
54 
56 {
57  default_vals();
58 }
59 
61 {
62  default_vals();
63  copy(a);
64 }
65 
66 EST_Track::EST_Track(int n_frames, int n_channels)
67 {
68  default_vals();
69  p_values.resize(n_frames, n_channels);
70  p_times.resize(n_frames);
71  p_is_val.resize(n_frames);
72  p_channel_names.resize(n_channels);
73 
74  p_aux.resize(n_frames, 1);
75  p_aux_names.resize(1);
76 
77  char d = 0;
78  p_is_val.fill(d);
79 }
80 
81 EST_Track::EST_Track(int n_frames, EST_TrackMap &map)
82 {
83  int n_channels = map.last_channel()+1;
84 
85  default_vals();
86  p_values.resize(n_frames, n_channels);
87  p_times.resize(n_frames);
88  p_is_val.resize(n_frames);
89  p_channel_names.resize(n_channels);
90  char d = 0;
91  p_is_val.fill(d);
92  assign_map(map);
93 }
94 
96 {
97  // clear_features();
98 }
99 
100 void EST_Track::default_channel_names()
101 {
102  for (int i = 0; i < num_channels(); ++i)
103  set_channel_name("track" + itoString(i), i);
104 }
105 
106 void EST_Track::default_vals(void)
107 {
108  p_equal_space = FALSE;
109  p_single_break = FALSE;
110  p_values.resize(0, 0);
111  p_times.resize(0);
112  p_is_val.resize(0);
113  p_aux.resize(0, 0);
114  p_aux_names.resize(0);
115  p_channel_names.resize(0);
116  p_map = NULL;
117  p_t_offset=0;
118 
119  init_features();
120 }
121 
122 void EST_Track::set_break(int i) // make location i hold a break
123 {
124  if (i >= num_frames())
125  cerr << "Requested setting of break value of the end of the array\n";
126 
127  p_is_val[i] = 1;
128 }
129 
130 
131 void EST_Track::set_value(int i) // make location i hold a value
132 {
133  p_is_val[i] = 0;
134 }
135 
136 const EST_String EST_Track::channel_name(int i, const EST_ChannelNameMap &map, int strings_override) const
137 {
138  (void)map;
139  (void)strings_override;
140  return p_channel_names(i);
141 }
142 
143 /* OLD ENUM VERSION
144 
145 const EST_String EST_Track::channel_name(int i, const EST_ChannelNameMap &map, int strings_override) const
146 {
147  EST_ChannelType type = channel_unknown;
148 
149  if (strings_override && p_channel_names(i) != "")
150  return p_channel_names(i);
151  else if (p_map!=NULL && ((type = p_map->channel_type(i)) != channel_unknown))
152  {
153  const char *name = map.name(type);
154  if (!name)
155  name = EST_default_channel_names.name(type);
156  if (name != NULL)
157  return EST_String(name);
158  return "unnamed_channel" + itoString(type);
159  }
160  else if (!strings_override && p_channel_names(i) != "")
161  return p_channel_names(i);
162  else
163  return "track" + itoString(i);
164 }
165 */
167 {
168  p_channel_names[i] = fn;
169 }
170 
172 {
173  p_aux_names[i] = fn;
174 }
175 
176 ostream& operator << (ostream& s, const EST_Track &tr)
177 {
178  int i, j;
179  for (i = 0; i < tr.num_frames(); ++i)
180  {
181  s << tr.t(i);
182  for (j = 0; j < tr.num_channels(); ++j)
183  s << "\t" << tr(i, j);
184  for (j = 0; j < tr.num_aux_channels(); ++j)
185  s << "\t" << tr.aux(i, j);
186  s << "\t" << !tr.track_break(i) << endl;
187  }
188  return s;
189 }
190 
191 void EST_Track::copy(const EST_Track& a)
192 {
193  copy_setup(a);
194  p_values = a.p_values;
195  p_times = a.p_times;
196  p_is_val = a.p_is_val;
197  p_t_offset = a.p_t_offset;
198  p_aux = a.p_aux;
199  p_aux_names = a.p_aux_names;
200 }
201 
203 {
204  p_equal_space = a.p_equal_space;
205  p_single_break = a.p_single_break;
206  p_channel_names = a.p_channel_names;
207  p_map = a.p_map;
208  copy_features(a);
209 }
210 
211 void EST_Track::resize(int new_num_frames, int new_num_channels, bool set)
212 {
213  int old_num_frames = num_frames();
214 
215  if (new_num_frames<0)
216  new_num_frames = num_frames();
217 
218  if (new_num_channels<0)
219  new_num_channels = num_channels();
220 
221  p_channel_names.resize(new_num_channels);
222 
223  // this ensures the new channels have a default name
224  if (new_num_channels > num_channels())
225  for (int i = num_channels(); i < new_num_channels; ++i)
226  set_channel_name("track_" + itoString(i), i);
227 
228  p_values.resize(new_num_frames, new_num_channels, set);
229  p_times.resize(new_num_frames, set);
230  p_is_val.resize(new_num_frames, set);
231 
232  p_aux.resize(new_num_frames, num_aux_channels(), set);
233 
234  // Its important that any new vals get set to 0
235  for (int i = old_num_frames; i < num_frames(); ++i)
236  p_is_val.a_no_check(i) = 0;
237 
238 }
239 
240 static void map_to_channels(EST_StrList &channel_map,
241  EST_StrList &channel_names)
242 {
243  EST_Litem *p;
244  EST_String b, type, first, last;
245  int n_f, n_l;
246 
247  for (p = channel_map.head(); p; p = p->next())
248  {
249  b = channel_map(p);
250  if (b.matches("$", 0))
251  {
252  // do this backwards as types may have "_" in them
253  b = b.after("$");
254  if (!b.contains("-"))
255  {
256  cerr<<"Ill formed coefficient range in map: " << b << "\n";
257  return;
258  }
259  type = b.before("-");
260  first = b.after("-");
261 
262  if (!first.contains("+"))
263  {
264  cerr<<"Ill formed coefficient range in map: "<<first<<"\n";
265  return;
266  }
267 
268  last = first.after("+");
269  first = first.before("+");
270 
271  n_f = Stringtoi(first);
272  n_l = Stringtoi(last);
273 
274  for (int i = n_f; i < n_l; ++i)
275  channel_names.append(type + "_" + itoString(i));
276  channel_names.append(type + "_N");
277  }
278  else
279  channel_names.append(b);
280  }
281 }
282 
283 void EST_Track::resize(int new_num_frames, EST_StrList &new_channels, bool set)
284 {
285  EST_StrList x;
286  map_to_channels(new_channels, x);
287  int i;
288  EST_Litem *p;
289 
290  int new_num_channels;
291  new_num_channels = x.length();
292 
293  if (new_num_frames<0)
294  new_num_frames = num_frames();
295 
296 
297  p_channel_names.resize(new_num_channels);
298  // this ensures the new channels have a default name
299 
300  for (i = 0, p = x.head(); p ; p = p->next(), ++i)
301  set_channel_name(x(p), i);
302 
303  p_values.resize(new_num_frames, new_num_channels, set);
304  p_times.resize(new_num_frames, set);
305  p_is_val.resize(new_num_frames, set);
306 
307 // for (int i = 0; i < new_num_frames; ++i)
308 // p_is_val.a_no_check(i) = 1;
309 }
310 
311 void EST_Track::resize_aux(EST_StrList &new_aux_channels, bool set)
312 {
313  int i;
314  EST_Litem *p;
315 
316  int new_num_channels;
317  new_num_channels = new_aux_channels.length();
318 
319  p_aux_names.resize(new_num_channels);
320 
321  // this ensures the new channels have a default name
322  for (i = 0, p = new_aux_channels.head(); p ; p = p->next(), ++i)
323  set_aux_channel_name(new_aux_channels(p), i);
324 
325  p_aux.resize(num_frames(), new_num_channels, set);
326 }
327 
328 EST_Track& EST_Track::operator+=(const EST_Track &a) // add to existing track
329 {
330  int i, j, k;
331 
332  if (num_frames() == 0) // i.e. no existing EST_Track to add to
333  {
334  *this = a;
335  return *this;
336  }
337 
338  if (a.num_channels() != num_channels())
339  {
340  cerr << "Error: Tried to add " << a.num_channels() <<
341  " channel EST_Track to "<<num_channels() << " channel EST_Track\n";
342  return *this;
343  }
344 
345  int old_num = num_frames();
346  float old_end = end();
347  this->resize(a.num_frames()+ this->num_frames(), this->num_channels());
348  for (i = 0, j = old_num; i < a.num_frames(); ++i, ++j)
349  {
350  for (k = 0; k < num_channels(); ++k)
351  p_values.a_no_check(j, k) = a(i, k);
352  p_times[j] = old_end + a.t(i);
353  p_is_val[j] = a.p_is_val(i);
354  }
355 
356  return *this;
357 }
358 
359 EST_Track& EST_Track::operator|=(const EST_Track &a)
360 { // add to existing track in parallel
361  int i, j, k;
362 
363  if (num_channels() == 0) // i.e. no existing EST_Track to add to
364  {
365  *this = a;
366  return *this;
367  }
368 
369  if (a.num_frames() != num_frames())
370  {
371  cerr << "Error: Tried to add " << a.num_frames() <<
372  " channel EST_Track to "<<num_frames()<< " channel EST_Track\n";
373  return *this;
374  }
375 
376  int old_num = num_channels();
377  this->resize(a.num_frames(), this->num_channels() + a.num_channels());
378  for (i = 0, j = old_num; i < a.num_channels(); ++i, ++j)
379  for (k = 0; k < num_frames(); ++k)
380  p_values.a_no_check(k, j) = a(k, i);
381 
382  return *this;
383 }
384 
385 EST_Track &EST_Track::operator=(const EST_Track& a)
386 {
387  copy(a);
388  return *this;
389 }
390 
391 
392 int EST_Track::channel_position(const char *name, int offset) const
393 {
394  int c;
395 
396  for (c=0; c<num_channels(); c++)
397  if (channel_name(c) == name)
398  return c+offset;
399 
400  return -1;
401 }
402 
403 float &EST_Track::a(int i, const char *name, int offset)
404 {
405  int c;
406 
407  for (c=0; c<num_channels(); c++)
408  if (channel_name(c) == name)
409  return p_values.a_no_check(i, c+offset);
410 
411  cerr << "no channel '" << name << "'\n";
412  return *(p_values.error_return);
413 }
414 
415 EST_Val &EST_Track::aux(int i, const char *name)
416 {
417  for (int c = 0; c < num_aux_channels(); c++)
418  if (aux_channel_name(c) == name)
419  return p_aux.a_no_check(i, c);
420 
421  cerr << "no auxiliary channel '" << name << "' found\n";
422  return *(p_aux.error_return);
423 }
424 
425 EST_Val &EST_Track::aux(int i, int c)
426 {
427  return p_aux(i, c);
428 }
429 
430 EST_Val &EST_Track::aux(int i, int c) const
431 {
432  return ((EST_Track *)this)->aux(i,c);
433 }
434 
435 #define EPSILON (0.0001)
436 
437 float &EST_Track::a(float t, int c, EST_InterpType interp)
438 {
439  static float ia = 0.0;
440 
441  if (interp == it_nearest)
442  return p_values.a_no_check(index(t), c);
443  else if (interp == it_linear)
444  {
445  int i = index_below(t);
446  if (i < 0)
447  return a(0,c);
448 
449  float n = a(i,c), n1 = a(i+1,c);
450  float tn = p_times(i), tn1 = p_times(i+1);
451  ia = n + (n1-n)*(t-tn)/(tn1-tn);
452  return ia;
453  }
454  else if (interp == it_linear_nz)
455  {
456  int i = index_below(t);
457  if (i < 0)
458  return a(0,c);
459 
460  float n = a(i,c), n1 = a(i+1,c);
461  if (fabs(n) < EPSILON || fabs(n1) < EPSILON)
462  return p_values.a_no_check(index(t), c);
463  float tn = p_times(i), tn1 = p_times(i+1);
464  ia = n + (n1-n)*(t-tn)/(tn1-tn);
465  return ia;
466  }
467  return ia;
468 }
469 
470 int EST_Track::index(float x) const
471 {
472  if (equal_space())
473  {
474  float s = shift();
475  int f = (int)( (x-t(0))/s+0.5 ); //don't assume track starts at t=0.0
476  if (f<0)
477  f=0;
478  else if (f>= num_frames())
479  f=num_frames()-1;
480  return f;
481  }
482  else if (num_frames() > 1) //if single frame, return that index (0)
483  {
484  int bst, bmid, bend;
485  bst = 1;
486  bend = num_frames();
487  if (x < p_times.a_no_check(bst))
488  bmid=bst;
489  if (x >= p_times.a_no_check(bend-1))
490  bmid=bend-1;
491  else
492  {
493  while (1)
494  {
495  bmid = bst + (bend-bst)/2;
496  if (bst == bmid)
497  break;
498  else if (x < p_times.a_no_check(bmid))
499  {
500  if (x >= p_times.a_no_check(bmid-1))
501  break;
502  bend = bmid;
503  }
504  else
505  bst = bmid;
506  }
507  }
508  if (fabs(x - p_times.a_no_check(bmid)) <
509  fabs(x - p_times.a_no_check(bmid-1)))
510  return bmid;
511  else
512  return bmid - 1;
513  }
514 
515  return num_frames() -1;
516 }
517 
518 int EST_Track::index_below(float x) const
519 {
520  if (equal_space())
521  {
522  float s = shift();
523  int f = (int)(x/s);
524  if (f<0)
525  f=0;
526  else if (f>= num_frames())
527  f=num_frames()-1;
528  return f;
529  }
530  else
531  {
532  for (int i = 1; i < num_frames(); ++i)
533  if (x <= p_times.a_no_check(i))
534  return i - 1;
535  return num_frames()-1;
536  }
537 }
538 
539 int EST_Track::val(int i) const
540 {
541  return !p_is_val(i);
542 }
543 /*
544  "p_equal_space" indicates whether the x-axis values are evenly spaced
545  (FIXED) or spaced arbitrarily (VARI).
546 
547  "p_single_break" describes the break format. F0 contours are seldom
548  continuous - often breaks occur due to unvoicing etc. These are a
549  marked in the data arrays by break values, "i_break" for ints
550  and "f_break" for floats. The "p_single_break" channel specifies whether
551  a break is represented by a single break value, or as a break
552  value for every frame. eg
553  (SINGLE)
554  800 100
555  810 105
556  BREAK BREAK
557  850 130
558  860 135
559  or
560  (MANY)
561  800 100
562  810 105
563  820 BREAK
564  830 BREAK
565  840 BREAK
566  850 130
567  860 135
568 
569  In the MANY case, only the y value is specified as a break, in the
570  SINGLE case the x value may or may not be specified as a break. For
571  this reason, when checking for breaks, it is useful to only rely
572  on the y value being set to the i_break value. Not that if the single_break
573  is MANY and the equal_space is FIXED, you dont really need x-axis
574  values.
575 
576  Different functions naturally work better on different representations
577  and that is why all these different types are supported. A
578  general function mod_cont() is supplied to change from one
579  type to another. Not all conversions are currently
580  supported however.
581 
582  */
583 
584 float EST_Track::end() const
585 {
586  if (num_frames() == 0)
587  return 0.0;
588  else
589  return (p_times(prev_non_break(num_frames())));
590 }
591 float EST_Track::start() const
592 {
593  if (num_frames() == 0)
594  return 0.0;
595  else
596  return (track_break(0) ? p_times(next_non_break(0)) : p_times(0));
597 }
598 
599 float EST_Track::shift() const
600 {
601  int j1 = 0;
602  int j2 = 0;
603 
604  if (!p_equal_space)
605  EST_error("Tried to take shift from non-fixed contour\n");
606 
607  do
608  {
609  j1 = next_non_break(++j1);
610  j2 = next_non_break(j1);
611  // cout << "j1:" << j1 << " j2:" << j2 << endl;
612  }
613  while ((j2 != 0) && (j2 != (j1 +1)));
614 
615  if (j2 == 0)
616  {
617  if (num_frames() > 1)
618  return p_times(1) - p_times(0);
619  else
620  EST_error("Couldn't determine shift size\n");
621 
622  }
623  return (p_times(j2) - p_times(j1));
624 }
625 
626 /* tries to find the next value that isnt a break. Dont really
627  know what to do on a fail, so just return 0 */
628 
630 {
631  int i = j;
632  for (++i; i < num_frames(); ++i)
633  {
634  // cout << "i: " << i << " " << value[i] << endl;
635  if (!track_break(i))
636  return i;
637  }
638 
639  return 0;
640 }
641 
642 /* give the current point, returns the previous non-break */
643 
645 {
646  int i = j;
647  for (--i; i >= 0 ; --i)
648  if (!track_break(i))
649  return i;
650  return 0;
651 }
652 
653 void EST_Track::change_type(float nshift, bool single_break)
654 {
655  if (nshift != 0.0)
656  {
657  if (!p_equal_space || nshift != shift())
658  sample(nshift);
659  p_equal_space = TRUE;
660  }
661 
662  if (single_break != p_single_break)
663  {
664  if (!p_single_break)
665  pad_breaks();
666  else
668  }
669 }
670 
671 void EST_Track::sample(float f_interval)
672 {
673  EST_FVector new_times;
674  EST_FMatrix new_values;
675  EST_CVector new_is_break;
676  int i, j, n;
677 
678  n = (int) rint(((end())/ f_interval));
679 
680  new_times.resize(n);
681  new_values.resize(n, num_channels());
682  new_is_break.resize(n);
683 
684  // REORG - can this be replaced with fill_time()?
685  for (i = 0; i < n; ++i)
686  new_times[i] = (float) ((i + 1) * f_interval);
687 
688  for (i = 0; i < n; ++i)
689  {
690  new_is_break[i] = !interp_value(new_times(i), f_interval);
691  for (j = 0; j < num_channels(); ++j)
692  new_values(i, j) = !new_is_break(i) ? interp_amp(new_times(i), j, f_interval): 0.0;
693  }
694 
695  p_times = new_times;
696  p_values = new_values;
697  p_is_val = new_is_break;
698  p_single_break = FALSE;
699  p_equal_space = TRUE;
700 }
701 
702 float EST_Track::interp_amp(float x, int c, float fl)
703 {
704  int i;
705  float x1, x2, y1, y2, m;
706 
707  for (i = 0; i < num_frames(); ++i)
708  if ((p_times(i) + (fl / 2.0))> x)
709  break;
710 
711  if (i == num_frames())
712  return p_values.a_no_check(i - 1,c);
713  if (i == 0)
714  return p_values.a_no_check(0, c);
715 
716  if (track_break(i) && track_break(i - 1))
717  return 0.0;
718 
719  if (track_break(i))
720  return p_values.a_no_check(i - 1, c);
721 
722  else if (track_break(i - 1))
723  return p_values.a_no_check(i, c);
724 
725  x1 = p_times(i - 1);
726  y1 = p_values.a_no_check(i - 1, c);
727  x2 = p_times(i);
728  y2 = p_values.a_no_check(i, c);
729 
730  m = (y2 - y1) / (x2 -x1);
731  return ((x - x1) * m) + y1;
732 }
733 
734 int EST_Track::interp_value(float x, float fl)
735 {
736  int i;
737  int p, n;
738  float cf;
739 
740  if (p_equal_space)
741  cf = shift();
742  else
743  cf = estimate_shift(x);
744 
745  for (i = 0; i < num_frames(); ++i)
746  if ((p_times(i) + (fl / 2.0))> x)
747  break;
748  // This was:
749  // for (i = 0; i < num_frames(); ++i)
750  // if (p_times[i] > x)
751  // break;
752 
753  if (i == 0) // must be a break for the first value. (can't have i -1).
754  return FALSE;
755 
756  if ((!track_break(i)) && (!track_break(i -1)))
757  return TRUE;
758 
759  p = prev_non_break(i);
760  n = next_non_break(i);
761 
762  if ((x < p_times(p) + (cf / 2.0)) || (x > p_times(n) - (cf / 2.0)))
763  return TRUE; // rounding at edges
764 
765  return FALSE;
766 }
767 
768 float EST_Track::estimate_shift(float x)
769 {
770  int i, j;
771  for (j = 0; j < num_frames(); ++j)
772  if (p_times(j) > x)
773  break;
774 
775  for (i = j; i > 0; --i)
776  if ((!track_break(i)) && (!track_break(i - 1)))
777  return p_times(i) - p_times(i - 1);
778 
779  for (i = j; i < num_frames() - 1; ++i)
780  if ((!track_break(i)) && (!track_break(i + 1)))
781  return p_times(i + 1) - p_times(i);
782 
783  return 5.0; // default value
784 }
785 
786 void EST_Track::fill_time( float t, int start )
787 {
788  unsigned int nframes = num_frames();
789 
790  for( unsigned int i=0; i<nframes; ++i )
791  p_times.a_no_check(i) = t * (float) (i + start);
792 }
793 
794 void EST_Track::fill_time( float t, float startt )
795 {
796  unsigned int nframes = num_frames();
797 
798  for( unsigned int i=0; i<nframes; ++i )
799  p_times.a_no_check(i) = startt + (t * (float)i);
800 }
801 
803 {
804  unsigned int nframes = num_frames();
805 
806  for( unsigned int i=0; i<nframes; ++i )
807  p_times.a_no_check(i) = t.t(i);
808 }
809 
811 {
812  int i, j, k;
813  EST_FVector new_times;
814  EST_CVector new_is_break;
815  EST_FMatrix new_values;
816 
817  new_values.resize(num_channels(), num_frames());
818  new_times.resize(num_frames());
819  new_is_break.resize(num_frames());
820 
821  for (i = 0; track_break(i); ++i); //rm leading breaks
822 
823  for (j = 0; i < num_frames(); ++i, ++j)
824  {
825  for (k = 0; k < num_channels(); ++k)
826  new_values(j, k) = p_values.a_no_check(i, k);
827  new_times[j] = p_times(i);
828  new_is_break[j] = p_is_val(i);
829  while ((!new_is_break(j)) && (!val(i + 1)))
830  ++i;
831  }
832  p_times = new_times;
833  p_values = new_values;
834  p_is_val = new_is_break;
835  for (--j; track_break(j); --j) // "rm" trailing breaks
836  ;
837  p_times.resize(num_frames());
838  p_values.resize(num_frames(), num_channels());
839  p_is_val.resize(num_frames());
840 
841  p_single_break = TRUE;
842 }
843 
844 void EST_Track::rm_trailing_breaks()
845 {
846  if (num_frames() <=0 )
847  return;
848  int start, end;
849 
850  for (start = 0; start < num_frames(); ++start)
851  if (!track_break(start))
852  break;
853 
854  for(end=num_frames(); end>0; end--)
855  if (!track_break(end-1))
856  break;
857 
858  if (start==0 && end==num_frames())
859  return;
860 
861  for (int i=start, j = 0; i < end; ++i, ++j)
862  {
863  p_times[j] = p_times(i);
864  for (int k = 0; k < num_channels(); k++)
865  a_no_check(j, k) = a_no_check(i, k);
866  p_is_val[j] = p_is_val(i);
867  }
868 
869  p_values.resize(end-start, EST_CURRENT, 1);
870 
871  p_times.resize(num_frames());
872  p_is_val.resize(num_frames());
873 }
874 
875 void EST_Track::add_trailing_breaks()
876 {
877  int i, j, k;
878  EST_FVector new_times;
879  EST_FMatrix new_values;
880  int new_num = num_frames();
881 
882  if (!track_break(0))
883  new_num++;
884  if (!track_break(num_frames() - 1))
885  new_num++;
886 
887  if (new_num == num_frames()) /*ie trailing breaks already there */
888  return;
889 
890  new_times.resize(new_num);
891  new_values.resize(num_channels(), new_num);
892 
893  j = 0;
894  if (!track_break(j))
895  set_break(j);
896 
897  for (i = 0; i < num_frames(); ++i, ++j)
898  {
899  new_times[j] = p_times(i);
900  for (k = 0; k < num_channels(); ++k)
901  new_values(j, k) = p_values.a_no_check(i, k);
902  }
903 
904  if (!track_break(num_frames() - 1))
905  set_break(j);
906 
907  p_times = new_times;
908  p_values = new_values;
909  p_times.resize(num_frames());
910  p_values.resize(num_frames(), num_channels());
911 }
912 
913 void EST_Track::pad_breaks()
914 {
915  if (!p_single_break)
916  return;
917 
918  if (!p_equal_space)
919  EST_error("pad_breaks: Can only operate on fixed data\n");
920 
921  EST_FVector new_times;
922  EST_FMatrix new_values;
923  EST_CVector new_is_break;
924  int i, j, k, n;
925 
926  n = (int)(((end())/ shift()) + 1.0);
927  int s = int(start()/ shift());
928 
929  for (i = 0; i < n; ++i)
930  {
931  new_times[i] = (float) (i * shift());
932  for (k = 0; k < num_channels(); ++k)
933  new_values(k, i) = 0.0;
934  new_is_break[i] = 0;
935  }
936 
937  for (i = 0, j = s; j < n; ++i, ++j)
938  {
939  if (track_break(i))
940  {
941  for (; new_times(j) < p_times(i + 1); ++j);
942  --j;
943  }
944  else
945  {
946  new_is_break[j] = 1;
947  for (k = 0; k < num_channels(); ++k)
948  new_values(j, k) = p_values.a_no_check(i, k);
949  }
950  }
951  new_is_break[j] = 1;
952  for (k = 0; k < num_channels(); ++k)
953  new_values(j, k) = p_values.a_no_check(i, k);
954 
955  p_times = new_times;
956  p_values = new_values;
957  p_is_val = new_is_break;
958 
959  p_times.resize(num_frames());
960  p_is_val.resize(num_frames());
961  p_values.resize(num_frames(), num_channels());
962 
963  p_single_break = FALSE;
964 }
965 
966 static bool bounds_check(const EST_Track &t, int f, int c, int set)
967 {
968  const char *what = set? "set" : "access";
969 
970  if (f<0 || f >= t.num_frames())
971  {
972  cerr << "Attempt to " << what << " frame " << f << " of " << t.num_frames() << " frame track\n";
973  return FALSE;
974  }
975  if (c<0 || c >= t.num_channels())
976  {
977  cerr << "Attempt to " << what << " channel " << c << " of " << t.num_channels() << " channel track\n";
978  return FALSE;
979  }
980 
981 return TRUE;
982 }
983 
984 static bool bounds_check(const EST_Track &t,
985  int f, int nf,
986  int c, int nc,
987  int set)
988 {
989  const char *what = set? "set" : "access";
990 
991  if (nf>0)
992  {
993  if (f<0 || f >= t.num_frames())
994  {
995  cerr << "Attempt to " << what << " frame " << f << " of " << t.num_frames() << " frame track\n";
996  return FALSE;
997  }
998  if (f+nf-1 >= t.num_frames())
999  {
1000  cerr << "Attempt to " << what << " frame " << f+nf-1 << " of " << t.num_frames() << " frame track\n";
1001  return FALSE;
1002  }
1003  }
1004 
1005  if (nc>0)
1006  {
1007  if (c<0 || c >= t.num_channels())
1008  {
1009  cerr << "Attempt to " << what << " channel " << c << " of " << t.num_channels() << " channel track\n";
1010  return FALSE;
1011  }
1012  if (c+nc-1 >= t.num_channels())
1013  {
1014  cerr << "Attempt to " << what << " channel " << c+nc-1 << " of " << t.num_channels() << " channel track\n";
1015  return FALSE;
1016  }
1017  }
1018 
1019 return TRUE;
1020 }
1021 
1022 float &EST_Track::a(int i, int c)
1023 {
1024  if (!bounds_check(*this, i,c,0))
1025  return *(p_values.error_return);
1026 
1027  return p_values.a_no_check(i,c);
1028 }
1029 
1030 float EST_Track::a(int i, int c) const
1031 {
1032  return ((EST_Track *)this)->a(i,c);
1033 }
1034 
1035 int EST_Track::empty() const
1036 {
1037  int i, num;
1038 
1039  for (i = num = 0; i < num_frames(); ++i)
1040  if (val(i))
1041  return 0; // i.e. false
1042 
1043  return 1; // i.e. true
1044 }
1045 
1046 void EST_Track::channel(EST_FVector &cv, const char * name, int startf, int nf)
1047 {
1048  int n;
1049  if ((n = channel_position(name)) == -1)
1050  {
1051  cerr << "No such channel " << name << endl;
1052  return;
1053  }
1054  channel(cv, n, startf, nf);
1055 }
1056 
1058  int start_frame, int nframes,
1059  const EST_String &start_chan_name, int nchans)
1060 {
1061  int start_chan;
1062  if (start_chan_name == "")
1063  start_chan = 0;
1064 
1065  if ((start_chan = channel_position(start_chan_name)) == -1)
1066  EST_error("sub_track: No such channel %s\n",
1067  (const char *)start_chan_name);
1068 
1069  sub_track(st, start_frame, nframes, start_chan, nchans);
1070 }
1071 
1073  int start_frame, int nframes,
1074  const EST_String &start_chan_name,
1075  const EST_String &end_chan_name)
1076 {
1077  int start_chan, end_chan, nchans=0;
1078 
1079  if ((start_chan = channel_position(start_chan_name)) == -1)
1080  EST_error("sub_track: No such channel %s\n",
1081  (const char *)start_chan_name);
1082 
1083  if (end_chan_name == "")
1084  nchans = EST_ALL;
1085  else
1086  {
1087  if ((end_chan = channel_position(end_chan_name)) == -1)
1088  EST_error("sub_track: No such channel %s\n",
1089  (const char*)end_chan_name);
1090  else
1091  nchans = end_chan - start_chan + 1;
1092  }
1093 
1094  sub_track(st, start_frame, nframes, start_chan, nchans);
1095 }
1096 
1098  int start_frame, int nframes,
1099  int start_chan, int nchans)
1100 {
1101  if (nframes <0)
1102  nframes = num_frames() - start_frame;
1103  if (nchans <0)
1104  nchans = num_channels() - start_chan;
1105 
1106  if (!bounds_check(*this, start_frame, nframes, start_chan, nchans, 0))
1107  return;
1108 
1109  p_values.sub_matrix(st.p_values, start_frame, nframes, start_chan, nchans);
1110 
1111  p_times.sub_vector(st.p_times, start_frame, nframes);
1112 
1113  p_is_val.sub_vector(st.p_is_val, start_frame, nframes);
1114 
1115  p_channel_names.sub_vector(st.p_channel_names, start_chan, nchans);
1116 
1117  // All auxiliary information is included. These are effectively
1118  // pointer statements
1119 
1120  p_aux.sub_matrix(st.p_aux, start_frame, nframes, 0, EST_ALL);
1121  p_aux_names.sub_vector(st.p_aux_names, 0, EST_ALL);
1122 
1123  st.p_t_offset = p_t_offset;
1124 
1125  st.p_equal_space = p_equal_space;
1126  st.p_single_break = p_single_break;
1127  st.copy_features(*this);
1128 
1129  if (p_map!=0)
1130  st.p_map = new EST_TrackMap(p_map, start_chan, EST_TM_REFCOUNTED);
1131  else
1132  st.p_map = NULL;
1133 }
1134 
1135 
1137  int start_frame, int nframes,
1138  int start_chan, int nchans) const
1139 {
1140  if (nframes <0)
1141  nframes = num_frames() - start_frame;
1142  if (nchans <0)
1143  nchans = num_channels() - start_chan;
1144 
1145  if (!bounds_check(*this, start_frame, nframes, start_chan, nchans, 0))
1146  return;
1147 
1148  st.resize(nframes, nchans);
1149 
1150  for (int ff=0; ff<nframes; ff++)
1151  {
1152  st.p_times.a(ff) = p_times.a(ff+start_frame);
1153  st.p_is_val.a(ff) = p_is_val.a(ff+start_frame);
1154  for (int c=0; c<nchans; c++)
1155  st.p_values.a(ff,c) = p_values.a(ff+start_frame,c+start_chan);
1156  }
1157 
1158  for (int c=0; c<nchans; c++)
1159  st.p_channel_names.a(c) = p_channel_names.a(c+start_chan);
1160 
1161  st.p_aux = p_aux;
1162  st.p_aux_names = p_aux_names;
1163 
1164  st.p_equal_space = p_equal_space;
1165  st.p_single_break = p_single_break;
1166 
1167  st.copy_features(*this);
1168 
1169  if (p_map!=0)
1170  st.p_map = new EST_TrackMap(p_map, start_chan, EST_TM_REFCOUNTED);
1171  else
1172  st.p_map = NULL;
1173 }
1174 
1175 void EST_Track::copy_sub_track_out( EST_Track &st, const EST_FVector& frame_times ) const
1176 {
1177  int f_len = frame_times.length();
1178  int nchans = num_channels();
1179  st.resize( f_len, nchans );
1180 
1181  for( int i=0; i<f_len; ++i ){
1182 
1183  int source_index = index(frame_times(i));
1184 
1185  st.p_times.a(i) = p_times.a( source_index );
1186  st.p_is_val.a(i) = p_is_val.a( source_index );
1187 
1188  for( int c=0; c<nchans; c++ )
1189  st.p_values.a(i,c) = p_values.a(source_index,c);
1190  }
1191 
1192  st.copy_setup( *this );
1193  st.set_equal_space( false ); //might not be true, but it's a better default
1194 
1195  // st.p_aux = p_aux;
1196  // st.p_aux_names = p_aux_names;
1197 }
1198 
1199 void EST_Track::copy_sub_track_out( EST_Track &st, const EST_IVector& frame_indices ) const
1200 {
1201  int f_len = frame_indices.length();
1202  int nchans = num_channels();
1203  st.resize( f_len, nchans );
1204 
1205  int last_index = num_frames()-1;
1206 
1207  for( int i=0; i<f_len; ++i ){
1208 
1209  int source_index = frame_indices(i);
1210 
1211  if( source_index <= last_index ){
1212 
1213  st.p_times.a(i) = p_times.a( source_index );
1214  st.p_is_val.a(i) = p_is_val.a( source_index );
1215 
1216  for( int c=0; c<nchans; c++ )
1217  st.p_values.a(i,c) = p_values.a(source_index,c);
1218  }
1219  }
1220 
1221  st.copy_setup( *this );
1222  st.set_equal_space( false ); //might not be true, but it's a better default
1223 
1224  // st.p_aux = p_aux;
1225  // st.p_aux_names = p_aux_names;
1226 }
1227 
1228 
1229 
1230 EST_write_status EST_Track::save(const EST_String filename,
1231  const EST_String type)
1232 {
1233  EST_String save_type = (type == "") ? DEF_FILE_TYPE : type;
1234 
1235  EST_TrackFileType t = EST_TrackFile::map.token(save_type);
1236 
1237  if (t == tff_none)
1238  {
1239  cerr << "Unknown Track file type " << save_type << endl;
1240  return write_fail;
1241  }
1242 
1243  EST_TrackFile::Save_File * s_fun = EST_TrackFile::map.info(t).save;
1244 
1245  if (s_fun == NULL)
1246  {
1247  cerr << "Can't save tracks to files type " << save_type << endl;
1248  return write_fail;
1249  }
1250 
1251  return (*s_fun)(filename, *this);
1252 }
1253 
1254 EST_write_status EST_Track::save(FILE *fp, const EST_String type)
1255 {
1256  EST_TrackFileType t = EST_TrackFile::ts_map.token(type);
1257 
1258  if (t == tff_none)
1259  {
1260  cerr << "Unknown Track file type " << type << endl;
1261  return write_fail;
1262  }
1263 
1264  EST_TrackFile::Save_TokenStream * s_fun =
1265  EST_TrackFile::ts_map.info(t).save;
1266 
1267  if (s_fun == NULL)
1268  {
1269  cerr << "Can't save tracks to files type " << type << endl;
1270  return write_fail;
1271  }
1272  return (*s_fun)(fp, *this);
1273 }
1274 
1275 EST_read_status EST_Track::load(EST_TokenStream &ts, float ishift, float startt)
1276 {
1277  EST_read_status stat = read_error;
1278 
1279  for (int n = 0; n < EST_TrackFile::ts_map.n(); n++)
1280  {
1281  EST_TrackFileType t = EST_TrackFile::ts_map.token(n);
1282 
1283  if (t == tff_none)
1284  continue;
1285 
1286  EST_TrackFile::TS_Info *info = &(EST_TrackFile::ts_map.info(t));
1287 
1288  if (! info->recognise)
1289  continue;
1290 
1291  EST_TrackFile::Load_TokenStream * l_fun =info->load;
1292 
1293  if (l_fun == NULL)
1294  continue;
1295 
1296  stat = (*l_fun)(ts, *this, ishift, startt);
1297 
1298  if (stat != read_format_error)
1299  {
1300  if (stat == read_ok)
1301  set_file_type(t);
1302  break;
1303  }
1304  }
1305 
1306  return stat;
1307 }
1308 
1309 EST_read_status EST_Track::load(const EST_String filename, float ishift, float startt)
1310 {
1311  EST_read_status stat = read_error;
1312 
1313  for(int n=0; n< EST_TrackFile::map.n() ; n++)
1314  {
1315  EST_TrackFileType t = EST_TrackFile::map.token(n);
1316 
1317  if (t == tff_none)
1318  continue;
1319 
1320 
1321  EST_TrackFile::Info *info = &(EST_TrackFile::map.info(t));
1322 
1323  if (! info->recognise)
1324  continue;
1325 
1326  EST_TrackFile::Load_File * l_fun =info->load;
1327 
1328  if (l_fun == NULL)
1329  continue;
1330 
1331  stat = (*l_fun)(filename, *this, ishift, startt);
1332 
1333  if (stat == read_ok)
1334  {
1335  set_file_type(t);
1336  break;
1337  }
1338  else if (stat == read_error)
1339  break;
1340  }
1341 
1342  return stat;
1343 }
1344 
1345 EST_read_status EST_Track::load(const EST_String filename, const EST_String type, float ishift, float startt)
1346 {
1347  EST_TrackFileType t = EST_TrackFile::map.token(type);
1348 
1349  if (t == tff_none)
1350  {
1351  cerr << "Unknown Track file type " << type << endl;
1352  return read_error;
1353  }
1354 
1355  EST_TrackFile::Load_File * l_fun = EST_TrackFile::map.info(t).load;
1356 
1357  if (l_fun == NULL)
1358  {
1359  cerr << "Can't load tracks from file type" << type << endl;
1360  return read_error;
1361  }
1362 
1363  set_file_type(t);
1364  return (*l_fun)(filename, *this, ishift, startt);
1365 }
1366 
1367 EST_write_status EST_Track::save_channel_names(const EST_String filename)
1368 {
1369  FILE *file;
1370 
1371  if ((file=fopen(filename, "wb"))==NULL)
1372  return write_fail;
1373 
1374  for(int c=0; c<num_channels(); c++)
1375  fprintf(file, "%s\n", (const char *)channel_name(c));
1376 
1377  fclose(file);
1378 
1379  return write_ok;
1380 }
1381 
1382 EST_read_status EST_Track::load_channel_names(const EST_String filename)
1383 {
1384  FILE *file;
1385  static const int buffer_length = 100;
1386  char buffer[buffer_length];
1387 
1388  if ((file=fopen(filename, "rb"))==NULL)
1389  return misc_read_error;
1390 
1391  for(int c=0; c<num_channels(); c++)
1392  {
1393  if (!fgets(buffer, buffer_length, file))
1394  break;
1395 
1396  buffer[strlen(buffer)-1] = '\0';
1397  set_channel_name(buffer, c);
1398  }
1399 
1400 
1401  fclose(file);
1402 
1403  return format_ok;
1404 }
1405 
1406 /* code from here down should be deleted once tracp mapping is modified */
1407 
1408 
1409 float &EST_Track::a(float t, EST_ChannelType type, EST_InterpType interp)
1410 {
1411  short c = NO_SUCH_CHANNEL;
1412 
1413  if (p_map!=0 && (c = p_map->get(type)) != NO_SUCH_CHANNEL)
1414  return a(t, c, interp);
1415  else
1416  {
1417  cerr << "no channel '" << EST_default_channel_names.name(type) << "' = " << (int)type << "\n";
1418  }
1419  return *(p_values.error_return);
1420 }
1421 
1422 
1423 void EST_Track::assign_map(EST_TrackMap::P map)
1424 {
1425  p_map = map;
1426 }
1427 
1428 void EST_Track::create_map(EST_ChannelNameMap &names)
1429 {
1430  EST_TrackMap::P map = new EST_TrackMap(EST_TM_REFCOUNTED);
1431 
1432  for (int i = 0; i < num_channels(); i++)
1433  {
1434  EST_ChannelType type = names.token(p_channel_names(i));
1435 
1436  if (type != channel_unknown)
1437  map->set(type, i);
1438  }
1439 
1440  assign_map(map);
1441 }
1442 
1443 
1444 void EST_Track::resize(int new_num_frames, EST_TrackMap &map)
1445 {
1446  resize(new_num_frames, map.last_channel()+1);
1447  assign_map(map);
1448 }
1449 
1450 
1451 
1452 int EST_Track::channel_position(EST_ChannelType type, int offset) const
1453 {
1454  if (p_map!=0)
1455  {
1456  int p = (*p_map)(type);
1457  return (p!= NO_SUCH_CHANNEL)?(p+offset): NO_SUCH_CHANNEL;
1458  }
1459  return channel_position(EST_default_channel_names.name(type), offset);
1460 }
1461 
1462 float &EST_Track::a(int i, EST_ChannelType type, int offset)
1463 {
1464  short c = NO_SUCH_CHANNEL;
1465 
1466  if (p_map!=0 && ((c = p_map->get(type)) != NO_SUCH_CHANNEL))
1467  return p_values.a_no_check(i, c+offset);
1468  else
1469  {
1470  cerr << "no channel '" << EST_default_channel_names.name(type) << "' = " << (int)type << "\n";
1471  }
1472 
1473  return *(p_values.error_return);
1474 }
1475 
1476 EST_Track::IPointer_f::IPointer_f()
1477 {
1478  frame = new EST_Track();
1479 }
1480 
1481 EST_Track::IPointer_f::IPointer_f(const IPointer_f &p)
1482 {
1483  frame=new EST_Track(*(p.frame));
1484 }
1485 
1486 EST_Track::IPointer_f::~IPointer_f()
1487 {
1488  if (frame != NULL)
1489  {
1490  delete frame;
1491  frame=NULL;
1492  }
1493 }
1494 
1495 
1496 #if defined(INSTANTIATE_TEMPLATES)
1497 
1498 Instantiate_TIterator_T(EST_Track, EST_Track::IPointer_f, EST_Track, Track_itt)
1499 
1500 #endif