Edinburgh Speech Tools 2.4-release
 
Loading...
Searching...
No Matches
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
50const int EST_Track::default_sample_rate=16000; // occasionally needed for xmg files
51const float EST_Track::default_frame_shift=0.005; // default frame spacing.
52
53const EST_String DEF_FILE_TYPE = "est";
54
56{
57 default_vals();
58}
59
61{
62 default_vals();
63 copy(a);
64}
65
66EST_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
81EST_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
100void 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
106void 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
122void 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
131void EST_Track::set_value(int i) // make location i hold a value
132{
133 p_is_val[i] = 0;
134}
135
136const 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
145const 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
176ostream& 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
191void 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
211void 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
240static 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
283void 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
311void 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
328EST_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
359EST_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
385EST_Track &EST_Track::operator=(const EST_Track& a)
386{
387 copy(a);
388 return *this;
389}
390
391
392int 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
403float &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
415EST_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
425EST_Val &EST_Track::aux(int i, int c)
426{
427 return p_aux(i, c);
428}
429
430EST_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
437float &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
470int 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
518int 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
539int 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
584float 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}
591float 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
599float 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
653void 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
671void 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
702float 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
734int 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
768float 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
786void 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
794void 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
844void 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
875void 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
913void 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
966static 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
981return TRUE;
982}
983
984static 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
1019return TRUE;
1020}
1021
1022float &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
1030float EST_Track::a(int i, int c) const
1031{
1032 return ((EST_Track *)this)->a(i,c);
1033}
1034
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
1046void 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
1175void 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
1199void 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
1230EST_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
1254EST_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
1275EST_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
1309EST_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
1345EST_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
1367EST_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
1382EST_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
1409float &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
1423void EST_Track::assign_map(EST_TrackMap::P map)
1424{
1425 p_map = map;
1426}
1427
1428void 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
1444void 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
1452int 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
1462float &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
1476EST_Track::IPointer_f::IPointer_f()
1477{
1478 frame = new EST_Track();
1479}
1480
1481EST_Track::IPointer_f::IPointer_f(const IPointer_f &p)
1482{
1483 frame=new EST_Track(*(p.frame));
1484}
1485
1486EST_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
1498Instantiate_TIterator_T(EST_Track, EST_Track::IPointer_f, EST_Track, Track_itt)
1499
1500#endif
EST_String before(int pos, int len=0) const
Part before position.
Definition EST_String.h:286
int contains(const char *s, int pos=-1) const
Does it contain this substring?
Definition EST_String.h:375
EST_String after(int pos, int len=1) const
Part after pos+len.
Definition EST_String.h:318
int matches(const char *e, int pos=0) const
Exactly match this string?
void append(const T &item)
add item onto end of list
Definition EST_TList.h:191
INLINE const T & a_no_check(int row, int col) const
const access with no bounds check, care recommend
void sub_matrix(EST_TMatrix< T > &sm, int r=0, int numr=EST_ALL, int c=0, int numc=EST_ALL)
Make the matrix {\tt sm} a window into this matrix.
void resize(int rows, int cols, int set=1)
void resize(int rows, int cols, int set=1)
resize matrix
void resize(int n, int set=1)
resize vector
void resize(int n, int set=1)
INLINE int length() const
number of items in vector.
static T * error_return
void sub_vector(EST_TVector< T > &sv, int start_c=0, int len=-1)
Create a sub vector.
void fill(const T &v)
Fill entire array will value <parameter>v</parameter>.
INLINE const T & a_no_check(int n) const
read-only const access operator: without bounds checking
short last_channel(void) const
Returns the index of the last known channel.
short get(EST_ChannelType type) const
Get the position of a channel.
void set(EST_ChannelType type, short pos)
Record the position of a channel.
void copy_sub_track(EST_Track &st, int start_frame=0, int nframes=EST_ALL, int start_chan=0, int nchans=EST_ALL) const
int channel_position(const char *name, int offset=0) const
Definition EST_Track.cc:392
void set_channel_name(const EST_String &name, int channel)
set the name of the channel.
Definition EST_Track.cc:166
EST_read_status load(const EST_String name, float ishift=0.0, float startt=0.0)
int track_break(int i) const
return true if frame i is a break
Definition EST_Track.h:633
float & t(int i=0)
return time position of frame i
Definition EST_Track.h:477
int val(int i) const
return true if frame i is a value
Definition EST_Track.cc:539
EST_write_status save(const EST_String name, const EST_String EST_filetype="")
float & a(int i, int c=0)
int num_aux_channels() const
return number of auxiliary channels in track
Definition EST_Track.h:659
int next_non_break(int i) const
Definition EST_Track.cc:629
void copy_setup(const EST_Track &a)
copy everything but data
Definition EST_Track.cc:202
~EST_Track()
default destructor
Definition EST_Track.cc:95
int index_below(float x) const
return the frame index before time t
Definition EST_Track.cc:518
void sub_track(EST_Track &st, int start_frame=0, int nframes=EST_ALL, int start_chan=0, int nchans=EST_ALL)
EST_Track()
Default constructor.
Definition EST_Track.cc:55
int empty() const
returns true if no values are set in the frame
bool equal_space() const
return true if track has equal (i.e. fixed) frame spacing *‍/
Definition EST_Track.h:669
float start() const
return time of first value in track
Definition EST_Track.cc:591
void set_value(int i)
set frame i to be a value
Definition EST_Track.cc:131
void resize_aux(EST_StrList &map, bool preserve=1)
Definition EST_Track.cc:311
int num_channels() const
return number of channels in track
Definition EST_Track.h:656
int num_frames() const
return number of frames in track
Definition EST_Track.h:650
float end() const
return time of last value in track
Definition EST_Track.cc:584
int index(float t) const
return the frame index nearest time t
Definition EST_Track.cc:470
float & a_no_check(int i, int c=0)
Definition EST_Track.h:419
void channel(EST_FVector &cv, int n, int startf=0, int nf=EST_ALL)
Definition EST_Track.h:214
void change_type(float nshift, bool single_break)
REDO.
Definition EST_Track.cc:653
void sample(float shift)
Definition EST_Track.cc:671
void resize(int num_frames, int num_channels, bool preserve=1)
Definition EST_Track.cc:211
float & a(float t, int c=0, EST_InterpType interp=it_nearest)
Definition EST_Track.cc:437
EST_String name() const
name of track - redundant use access to features
Definition EST_Track.h:195
void fill_time(float t, int start=1)
Definition EST_Track.cc:786
void set_aux_channel_name(const EST_String &name, int channel)
set the name of the auxiliary channel.
Definition EST_Track.cc:171
float shift() const
Definition EST_Track.cc:599
int prev_non_break(int i) const
Definition EST_Track.cc:644
void frame(EST_FVector &fv, int n, int startf=0, int nf=EST_ALL)
Definition EST_Track.h:209
void rm_excess_breaks()
Definition EST_Track.cc:810
void set_break(int i)
set frame i to be a break
Definition EST_Track.cc:122
bool single_break() const
Definition EST_Track.h:672