"Fossies" - the Fresh Open Source Software Archive 
Member "speech_tools/speech_class/EST_TrackFile.cc" (11 Sep 2017, 58936 Bytes) of package /linux/misc/speech_tools-2.5.0-release.tar.gz:
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 /* File I/O functions for EST_Track class */
37 /* */
38 /*=======================================================================*/
39 #include <fstream>
40 #include <iostream>
41 #include <cstdlib>
42 #include <cmath>
43 #include <time.h>
44 #include "EST_unix.h"
45 #include "EST_types.h"
46 #include "EST_Track.h"
47 #include "EST_track_aux.h"
48 #include "EST_TrackMap.h"
49 #include "EST_cutils.h"
50 #include "EST_Token.h"
51 #include "EST_TList.h"
52 #include "EST_string_aux.h"
53 #include "EST_walloc.h"
54 #include "EST_TrackFile.h"
55 #include "EST_FileType.h"
56 #include "EST_WaveFile.h"
57 #include "EST_wave_utils.h"
58
59 // size of locally allocated buffer. If more channels than this we have to
60 // call new
61
62 #define NEARLY_ZERO 0.00001
63
64 #define REASONABLE_FRAME_SIZE (20)
65 #define UNREASONABLE_FRAME_SIZE (80)
66
67 #if 0
68 static const char *NIST_SIG = "NIST_1A\n 1024\n";
69 static const char *NIST_END_SIG = "end_head\n";
70 #define NIST_HDR_SIZE 1024
71 // default for tracks is the standard EMA sample rate
72 static int def_load_sample_rate = 500;
73
74 #endif
75
76 // some functions written for reading NIST headered waveform files,
77 // but useful here.
78 int nist_get_param_int(char *hdr, char *field, int def_val);
79 char *nist_get_param_str(char *hdr, char *field, char *def_val);
80 const char *sample_type_to_nist(enum EST_sample_type_t sample_type);
81 enum EST_sample_type_t nist_to_sample_type(char *type);
82
83 EST_read_status read_est_header(EST_TokenStream &ts, EST_Features &hinfo,
84 bool &ascii, EST_EstFileType &t);
85
86 EST_read_status EST_TrackFile::load_esps(const EST_String filename, EST_Track &tr, float ishift, float startt)
87 {
88 (void)ishift;
89 (void)startt;
90
91 float **tt;
92 float fsize;
93 char **fields;
94 int num_points, num_fields, num_values;
95 int i,j;
96 EST_read_status r_val;
97 short fixed;
98 int first_channel=0;
99
100 r_val = get_track_esps(filename, &fields, &tt, &fsize, &num_points,
101 &num_values, &fixed);
102 if (r_val == misc_read_error)
103 {
104 cerr << "Error reading ESPS file " << filename << endl;
105 return misc_read_error;
106 }
107 else if (r_val == wrong_format)
108 return wrong_format;
109
110 num_fields = num_values;
111 if (!fixed)
112 {
113 --num_fields;
114 ++first_channel;
115 }
116
117 tr.resize(num_points,num_fields);
118 tr.fill_time(fsize);
119
120 for (i = 0; i < num_points; ++i)
121 {
122 for (j = 0; j < num_fields; ++j)
123 tr.a(i, j) = tt[i][j+first_channel];
124 tr.set_value(i);
125 if (!fixed)
126 tr.t(i) = tt[i][0];
127 }
128
129 for (i = 0; i < num_fields; ++i)
130 tr.set_channel_name(fields[i+first_channel], i);
131
132
133 // REORG not sure what these should be -- awb
134 tr.set_single_break(false);
135 tr.set_equal_space(true);
136
137 // get_track_esps allocs all the memory, we therefore need to release it
138 for (i = 0; i < num_values; ++i)
139 wfree(fields[i]);
140 wfree(fields);
141 for (i = 0; i < num_values; ++i)
142 wfree(tt[i]);
143 wfree(tt);
144
145 tr.set_file_type(tff_esps);
146 tr.set_name(filename);
147
148 if (tr.channel_name(0) == "F0")
149 espsf0_to_track(tr);
150
151 return format_ok;
152 }
153
154 EST_read_status EST_TrackFile::load_ascii(const EST_String filename, EST_Track &tr, float ishift, float startt)
155 {
156 (void)startt;
157
158 EST_TokenStream ts, tt;
159 EST_StrList sl;
160
161 int i, j, n_rows, n_cols=0;
162 EST_String t;
163 EST_Litem *p;
164
165 if (((filename == "-") ? ts.open(cin) : ts.open(filename)) != 0)
166 {
167 cerr << "Can't open track file " << filename << endl;
168 return misc_read_error;
169 }
170 // set up the character constant values for this stream
171 ts.set_SingleCharSymbols(";");
172
173 if (ishift < NEARLY_ZERO)
174 {
175 cerr<<
176 "Error: Frame spacing must be specified (or apparent frame shift nearly zero)\n";
177 return misc_read_error;
178 }
179
180 // first read in as list
181
182 for (n_rows = 0; !ts.eof(); ++n_rows)
183 sl.append(ts.get_upto_eoln().string());
184
185 if (n_rows > 0)
186 {
187 tt.open_string(sl.first());
188 for (n_cols = 0; !tt.eof(); ++n_cols)
189 tt.get().string();
190 }
191
192 // resize track and copy values in
193 tr.resize(n_rows, n_cols);
194
195 for (p = sl.head(), i = 0; p != 0; ++i, p = p->next())
196 {
197 bool ok;
198 tt.open_string(sl(p));
199 for (j = 0; !tt.eof(); ++j)
200 tr.a(i, j) = tt.get().Float(ok);
201 if (j != n_cols)
202 {
203 cerr << "Wrong number of points in row " << i << endl;
204 cerr << "Expected " << n_cols << " got " << j << endl;
205 return misc_read_error;
206 }
207 }
208
209 tr.fill_time(ishift);
210 tr.set_single_break(FALSE);
211 tr.set_equal_space(TRUE);
212 tr.set_file_type(tff_ascii);
213 tr.set_name(filename);
214
215 return format_ok;
216 }
217
218 EST_read_status EST_TrackFile::load_xgraph(const EST_String filename, EST_Track &tr, float ishift, float startt)
219 {
220 (void)ishift;
221 (void)startt;
222
223 EST_TokenStream ts, tt;
224 EST_StrList sl;
225 // const float NEARLY_ZERO = 0.001;
226 int i, j, n_rows, n_cols;
227 EST_String t;
228 EST_Litem *p;
229
230 if (((filename == "-") ? ts.open(cin) : ts.open(filename)) != 0)
231 {
232 cerr << "Can't open track file " << filename << endl;
233 return misc_read_error;
234 }
235 // set up the character constant values for this stream
236 ts.set_SingleCharSymbols(";");
237
238 // first read in as list
239
240 for (n_rows = 0; !ts.eof(); ++n_rows)
241 sl.append(ts.get_upto_eoln().string());
242
243 tt.open_string(sl.first());
244 for (n_cols = 0; !tt.eof(); ++n_cols)
245 tt.get().string();
246
247 --n_cols; // first column is time marks
248
249 // resize track and copy values in
250 tr.resize(n_rows, n_cols);
251
252 for (p = sl.head(), i = 0; p != 0; ++i, p = p->next())
253 {
254 bool ok;
255 tt.open_string(sl(p));
256 tr.t(i) = tt.get().Float(ok);
257 for (j = 0; !tt.eof(); ++j)
258 tr.a(i, j) = tt.get().Float(ok);
259 if (j != n_cols)
260 {
261 cerr << "Wrong number of points in row " << i << endl;
262 cerr << "Expected " << n_cols << " got " << j << endl;
263 return misc_read_error;
264 }
265 }
266
267 tr.set_single_break(FALSE);
268 tr.set_equal_space(TRUE);
269 tr.set_file_type(tff_xgraph);
270 tr.set_name(filename);
271
272 return format_ok;
273 }
274
275 EST_read_status EST_TrackFile::load_xmg(const EST_String filename, EST_Track &tr, float ishift, float startt)
276 {
277 (void)ishift;
278 (void)startt;
279
280 EST_TokenStream ts;
281 EST_StrList sl;
282 int i, n;
283 EST_String t, k, v;
284 EST_Litem *p;
285
286 if (((filename == "-") ? ts.open(cin) : ts.open(filename)) != 0)
287 {
288 cerr << "Can't open track file " << filename << endl;
289 return misc_read_error;
290 }
291 // set up the character constant values for this stream
292 ts.set_SingleCharSymbols(";");
293
294 if (ts.peek().string() != "XAO1")
295 return wrong_format;
296
297 ts.get().string();
298
299 while ((!ts.eof()) && (ts.peek().string() != "\014"))
300 {
301 k = ts.get().string();
302 v = ts.get().string();
303 #if 0
304 /* Tracks don't represent these explicitly */
305 if (k == "Freq")
306 sr = v.Int() * 1000;
307 else if (k == "YMin")
308 /* tr.amin = atof(v) */;
309 else if (k == "YMax")
310 /*tr.amax = atof(v) */;
311 #endif
312 }
313
314 if (ts.eof())
315 {
316 cerr << "Unexpected end of file in reading xmg header\n";
317 return misc_read_error;
318 }
319 ts.get().string(); // read control L
320 ts.get_upto_eoln().string(); // read until end of header
321
322 // read in lines to a list
323 for (n = 0; !ts.eof(); ++n)
324 sl.append(ts.get_upto_eoln().string());
325
326 // note the track size is total number of points *and* breaks
327 tr.resize(n, 1 ); // REORG - fix this for multi channel work
328
329 for (p = sl.head(), i = 0; p != 0; ++i, p = p->next())
330 {
331 bool ok;
332 ts.open_string(sl(p));
333 if (ts.peek().string() != "=")
334 {
335 tr.t(i) = ts.get().Float(ok) / 1000.0;
336 tr.a(i) = ts.get().Float(ok);
337 }
338 else
339 {
340 ts.get().string();
341 tr.set_break(i);
342 }
343 }
344
345 tr.set_single_break(TRUE);
346 tr.set_equal_space(FALSE);
347 tr.set_file_type(tff_xmg);
348 tr.set_name(filename);
349
350 return format_ok;
351 }
352
353 EST_read_status EST_TrackFile::load_est(const EST_String filename,
354 EST_Track &tr, float ishift, float startt)
355 {
356 EST_TokenStream ts;
357 EST_read_status r;
358
359 if (((filename == "-") ? ts.open(cin) : ts.open(filename)) != 0)
360 {
361 cerr << "Can't open track file " << filename << endl;
362 return misc_read_error;
363 }
364 // set up the character constant values for this stream
365 ts.set_SingleCharSymbols(";");
366 tr.set_name(filename);
367 r = load_est_ts(ts, tr, ishift, startt);
368
369 if ((r == format_ok) && (!ts.eof()))
370 {
371 cerr << "Not end of file, but expected it\n";
372 return misc_read_error;
373 }
374 else
375 return r;
376 }
377
378 static float get_float(EST_TokenStream &ts,int swap)
379 {
380 float f;
381 ts.fread(&f,4,1);
382 if (swap) swapfloat(&f);
383 return f;
384 }
385
386 EST_read_status EST_TrackFile::load_est_ts(EST_TokenStream &ts,
387 EST_Track &tr, float ishift, float startt)
388 {
389 (void)ishift;
390 (void)startt;
391 int i, j;
392 int num_frames, num_channels;
393 EST_Features hinfo;
394 EST_EstFileType t;
395 EST_String v;
396 bool ascii;
397 bool breaks;
398 bool eq_space;
399 EST_read_status r;
400 int swap;
401
402 if ((r = read_est_header(ts, hinfo, ascii, t)) != format_ok)
403 return r;
404 if (t != est_file_track)
405 return misc_read_error;
406
407 breaks = hinfo.present("BreaksPresent") ? true : false;
408 eq_space = false;
409 if ((hinfo.present("EqualSpace")) &&
410 ((hinfo.S("EqualSpace") == "true") ||
411 (hinfo.S("EqualSpace") == "1")))
412 eq_space = true;
413
414 num_frames = hinfo.I("NumFrames");
415 num_channels = hinfo.I("NumChannels");
416 tr.resize(num_frames, num_channels);
417
418 hinfo.remove("NumFrames");
419 hinfo.remove("EqualSpace");
420 hinfo.remove("NumChannels");
421 hinfo.remove("BreaksPresent");
422 hinfo.remove("DataType");
423
424 EST_String strn, cname;
425
426 EST_Features::Entries p, c;
427 EST_StrList ch_map;
428
429 for (p.begin(hinfo); p;)
430 {
431 c = p++;
432
433 if (c->k.contains("Channel_"))
434 {
435 tr.set_channel_name(c->v.String(),
436 c->k.after("Channel_").Int());
437 hinfo.remove(c->k);
438 }
439 }
440
441 tr.resize_aux(ch_map);
442
443 // tr.create_map();
444
445 // if (((hinfo.S("ByteOrder", "") == "01") ? bo_little : bo_big)
446
447 if (!hinfo.present("ByteOrder"))
448 swap = FALSE; // ascii or not there for some reason
449 else if (((hinfo.S("ByteOrder") == "01") ? bo_little : bo_big)
450 != EST_NATIVE_BO)
451 swap = TRUE;
452 else
453 swap = FALSE;
454
455 const int BINARY_CHANNEL_BUFFER_SIZE=1024;
456 float *frame=0;
457 float frame_buffer[BINARY_CHANNEL_BUFFER_SIZE];
458 if( !ascii )
459 {
460 if( num_channels > BINARY_CHANNEL_BUFFER_SIZE )
461 frame = new float[num_channels];
462 else
463 frame = frame_buffer;
464 }
465
466 // there are too many ifs here
467 for (i = 0; i < num_frames; ++i)
468 {
469 bool ok;
470
471 // Read Times
472 if (ascii)
473 {
474 if (ts.eof())
475 {
476 cerr << "unexpected end of file when looking for " << num_frames-i << " more frame(s)" << endl;
477 return misc_read_error;
478 }
479 tr.t(i) = ts.get().Float(ok);
480 if (!ok)
481 return misc_read_error;
482 }
483 else
484 tr.t(i) = get_float(ts,swap);
485
486 // Read Breaks
487 if (breaks)
488 {
489 if (ascii)
490 {
491 v = ts.get().string();
492 if (v == "0")
493 tr.set_break(i);
494 else
495 tr.set_value(i);
496 }
497 else
498 {
499 if (get_float(ts,swap) == 0.0)
500 tr.set_break(i);
501 else
502 tr.set_value(i);
503 }
504 }
505 else
506 tr.set_value(i);
507
508 // Read Channels
509 // for (j = 0; j < num_channels; ++j)
510 // {
511 // if(ascii)
512 // {
513 // tr.a(i, j) = ts.get().Float(ok);
514 // if (!ok)
515 // return misc_read_error;
516 // }
517 // else
518 // tr.a(i,j) = get_float(ts,swap);
519 // }
520
521 if( ascii ){
522 for (j = 0; j < num_channels; ++j){
523 tr.a(i, j) = ts.get().Float(ok);
524 if (!ok)
525 return misc_read_error;
526 }
527 }
528 else{
529 ts.fread( frame, sizeof(float), num_channels );
530 if( swap )
531 for( j=0; j<num_channels; ++j ){
532 swapfloat( &frame[j] );
533 tr.a(i,j) = frame[j];
534 }
535 else
536 for( j=0; j<num_channels; ++j )
537 tr.a(i,j) = frame[j];
538 }
539
540
541 // Read aux Channels
542 for (j = 0; j < tr.num_aux_channels(); ++j)
543 {
544 if (ascii)
545 {
546 tr.aux(i, j) = ts.get().string();
547 if (!ok)
548 return misc_read_error;
549 }
550 else
551 {
552 cerr << "Warning: Aux Channel reading not yet implemented";
553 cerr << "for binary tracks\n";
554 }
555 }
556 }
557
558 if( !ascii )
559 if( frame != frame_buffer )
560 delete [] frame;
561
562 // copy header info into track
563 tr.f_set(hinfo);
564
565 tr.set_single_break(FALSE);
566 tr.set_equal_space(eq_space);
567
568 if(ascii)
569 tr.set_file_type(tff_est_ascii);
570 else
571 tr.set_file_type(tff_est_binary);
572
573 return format_ok;
574 }
575
576 EST_read_status load_snns_res(const EST_String filename, EST_Track &tr,
577 float ishift, float startt)
578 {
579 (void)startt;
580
581 EST_TokenStream ts, str;
582 EST_StrList sl;
583 int i, j;
584 EST_String t, k, v;
585
586 if (ishift < NEARLY_ZERO)
587 {
588 cerr<<
589 "Error: Frame spacing must be specified (or apparent frame shift nearly zero)\n";
590 return misc_read_error;
591 }
592
593 if (((filename == "-") ? ts.open(cin) : ts.open(filename)) != 0)
594 {
595 cerr << "Can't open track file " << filename << endl;
596 return misc_read_error;
597 }
598
599 if (ts.get().string() != "SNNS")
600 return wrong_format;
601 if (ts.get().string() != "result")
602 return wrong_format;
603
604 ts.get_upto_eoln(); // SNNS bit
605 ts.get_upto_eoln(); // Time info
606
607 int num_frames=0, num_channels=0;
608 int teaching = 0;
609
610 while (1)
611 {
612 t = (EST_String)ts.get_upto_eoln();
613 // cout << "t=" << t << endl;
614 if (t.contains("teaching output included"))
615 teaching = 1;
616 if (!t.contains(":"))
617 break;
618 str.open_string(t);
619 k = (EST_String)str.get_upto(":");
620 v = (EST_String)str.get_upto_eoln();
621 if (k == "No. of output units")
622 num_channels = v.Int();
623 if (k == "No. of patterns")
624 num_frames = v.Int();
625
626 // cout << "key " << k << endl;
627 // cout << "val " << v << endl;
628 }
629
630 // cout << "num_frames = " << num_frames << endl;
631 // cout << "num_channels = " << num_channels << endl;
632 tr.resize(num_frames, num_channels);
633 // cout << "peek" << ts.peek().string() << endl;
634 // cout << "teaching " << teaching << endl;
635
636 for (i = 0; (!ts.eof()) && (i < num_frames);)
637 // for (i = 0; i < 10; ++i)
638 {
639 if (ts.peek().string().contains("#")) // comment
640 {
641 ts.get_upto_eoln();
642 continue;
643 }
644 if (teaching) // get rid of teaching patterns
645 for (j = 0; j < num_channels; ++j)
646 ts.get().string();
647
648 // cout << "i = " << i << " t = " << ts.peek().string() << endl;
649
650 bool ok;
651
652 for (j = 0; j < num_channels; ++j)
653 tr.a(i, j) = ts.get().Float(ok);
654
655 ++i;
656 }
657
658 tr.fill_time(ishift);
659 tr.set_single_break(FALSE);
660 tr.set_equal_space(TRUE);
661 tr.set_file_type(tff_snns);
662 tr.set_name(filename);
663
664 return format_ok;
665 }
666
667 EST_write_status EST_TrackFile::save_esps(const EST_String filename, EST_Track tr)
668 {
669 EST_write_status rc;
670 int i, j;
671 float shift;
672 bool include_time;
673 int extra_channels=0;
674
675 EST_Track &track_tosave = tr;
676
677 if (filename == "-")
678 {
679 cerr << "Output to stdout not available for ESPS file types:";
680 cerr << "no output written\n";
681 return write_fail;
682 }
683
684 if ((include_time = (track_tosave.equal_space() != TRUE)))
685 {
686 shift = EST_Track::default_frame_shift;
687 extra_channels++;
688 }
689 else
690 shift = track_tosave.shift();
691
692 track_tosave.change_type(0.0,FALSE);
693
694 float **a = new float*[track_tosave.num_frames()];
695 // pity we need to copy it
696 for (i=0; i < track_tosave.num_frames(); i++)
697 {
698 a[i] = new float[track_tosave.num_channels() + extra_channels];
699
700 if (include_time)
701 a[i][0] = track_tosave.t(i);
702
703 for (j=0; j < track_tosave.num_channels(); j++)
704 a[i][j + extra_channels] = track_tosave.a(i,j);
705 }
706
707 char **f_names = new char*[track_tosave.num_channels() + extra_channels];
708 for (i=0; i < track_tosave.num_channels(); i++)
709 {
710 // cout << "field " << i << "is '" << track_tosave.field_name(i) << "'\n";
711 f_names[i + extra_channels] = wstrdup(track_tosave.channel_name(i, esps_channel_names, 0));
712 }
713
714 if (include_time)
715 f_names[0] = wstrdup("EST_TIME");
716
717 rc = put_track_esps(filename, f_names,
718 a, shift, 1.0/shift,
719 track_tosave.num_channels() + extra_channels,
720 track_tosave.num_frames(),
721 !include_time);
722
723 for (i=0; i < track_tosave.num_frames(); i ++)
724 delete [] a[i];
725 delete [] a;
726 for (i=0; i < track_tosave.num_channels()+extra_channels; i++)
727 delete [] f_names[i];
728 delete [] f_names;
729
730 return rc;
731 }
732
733 EST_write_status EST_TrackFile::save_est_ts(FILE *fp, EST_Track tr)
734 {
735 int i, j;
736
737 fprintf(fp, "EST_File Track\n"); // EST header identifier.
738 fprintf(fp, "DataType ascii\n");
739 fprintf(fp, "NumFrames %d\n", tr.num_frames());
740 fprintf(fp, "NumChannels %d\n", tr.num_channels());
741 fprintf(fp, "NumAuxChannels %d\n", tr.num_aux_channels());
742 fprintf(fp, "EqualSpace %d\n",tr.equal_space());
743
744 fprintf(fp, "BreaksPresent true\n");
745 for (i = 0; i < tr.num_channels(); ++i)
746 fprintf(fp, "Channel_%d %s\n", i, (const char *)(tr.channel_name(i)));
747
748 for (i = 0; i < tr.num_aux_channels(); ++i)
749 fprintf(fp, "Aux_Channel_%d %s\n", i,
750 (const char *)(tr.aux_channel_name(i)));
751
752 EST_Featured::FeatEntries p;
753
754 for (p.begin(tr); p; ++p)
755 fprintf(fp, "%s %s\n", (const char *)p->k,
756 (const char *) p->v.String());
757
758 fprintf(fp, "EST_Header_End\n");
759
760 for (i = 0; i < tr.num_frames(); ++i)
761 {
762 fprintf(fp, "%f\t", tr.t(i));
763 fprintf(fp, "%s\t", (char *)(tr.val(i) ? "1 " : "0 "));
764 for (j = 0; j < tr.num_channels(); ++j)
765 fprintf(fp, "%g ", tr.a_no_check(i, j));
766 for (j = 0; j < tr.num_aux_channels(); ++j)
767 fprintf(fp, "%s ", (const char *)tr.aux(i, j).string());
768 fprintf(fp, "\n");
769 }
770 return write_ok;
771 }
772
773 EST_write_status EST_TrackFile::save_est_ascii(const EST_String filename,
774 EST_Track tr)
775 {
776 FILE *fd;
777 EST_write_status r;
778
779 if (filename == "-")
780 fd = stdout;
781 else if ((fd = fopen(filename,"wb")) == NULL)
782 return write_fail;
783
784 r = save_est_ts(fd,tr);
785
786 if (fd != stdout)
787 fclose(fd);
788 return r;
789 }
790
791 EST_write_status EST_TrackFile::save_est_binary(const EST_String filename, EST_Track tr)
792 {
793 FILE *fd;
794 EST_write_status r;
795
796 if (filename == "-")
797 fd = stdout;
798 else if ((fd = fopen(filename,"wb")) == NULL)
799 return write_fail;
800
801 r = save_est_binary_ts(fd,tr);
802
803 if (fd != stdout)
804 fclose(fd);
805 return r;
806
807 }
808
809 EST_write_status EST_TrackFile::save_est_binary_ts(FILE *fp, EST_Track tr)
810 {
811 int i,j;
812
813 // This should be made optional
814 bool breaks = TRUE;
815
816 fprintf(fp, "EST_File Track\n");
817 fprintf(fp, "DataType binary\n");
818 fprintf(fp, "ByteOrder %s\n", ((EST_NATIVE_BO == bo_big) ? "10" : "01"));
819 fprintf(fp, "NumFrames %d\n", tr.num_frames());
820 fprintf(fp, "NumChannels %d\n",tr.num_channels());
821 fprintf(fp, "EqualSpace %d\n",tr.equal_space());
822 if(breaks)
823 fprintf(fp, "BreaksPresent true\n");
824 fprintf(fp, "CommentChar ;\n\n");
825 for (i = 0; i < tr.num_channels(); ++i)
826 fprintf(fp, "Channel_%d %s\n",i,tr.channel_name(i).str());
827 fprintf(fp, "EST_Header_End\n");
828
829 for (i = 0; i < tr.num_frames(); ++i)
830 {
831 // time
832 if((int)fwrite(&tr.t(i),4,1,fp) != 1)
833 return misc_write_error;
834
835 // break marker
836 if (breaks)
837 {
838 float bm = (tr.val(i) ? 1 : 0);
839 if((int)fwrite(&bm,4,1,fp) != 1)
840 return misc_write_error;
841 }
842 // data - restricted to floats at this time
843 for (j = 0; j < tr.num_channels(); ++j)
844 if((int)fwrite(&tr.a_no_check(i, j),4,1,fp) != 1)
845 return misc_write_error;
846
847 }
848 return write_ok;
849 }
850
851 EST_write_status EST_TrackFile::save_ascii(const EST_String filename, EST_Track tr)
852 {
853 /* We want to print these "nice" but not lose precision for
854 various precisioned numbers. so we're going to use %g to do this */
855 char fbuf[100];
856
857 if (tr.equal_space() == TRUE)
858 tr.change_type(0.0, FALSE);
859
860 ostream *outf;
861 if (filename == "-")
862 outf = &cout;
863 else
864 outf = new ofstream(filename);
865
866 if (!(*outf))
867 return write_fail;
868
869 outf->precision(5);
870 outf->setf(ios::fixed, ios::floatfield);
871 outf->width(8);
872
873 for (int i = 0; i < tr.num_frames(); ++i)
874 {
875 for (int j = 0; j < tr.num_channels(); ++j)
876 {
877 snprintf(fbuf,sizeof(fbuf),"%g",tr.a(i, j));
878 *outf << fbuf << " ";
879 }
880 *outf << endl;
881 }
882
883 if (outf != &cout)
884 delete outf;
885
886 return write_ok;
887 }
888
889 EST_write_status EST_TrackFile::save_xgraph(const EST_String filename, EST_Track tr)
890 {
891
892 ostream *outf;
893
894 if (filename == "-")
895 outf = &cout;
896 else
897 outf = new ofstream(filename);
898
899 if (!(*outf))
900 return write_fail;
901
902 tr.change_type(0.0, TRUE);
903
904 for (int j = 0; j < tr.num_channels(); ++j)
905 {
906 *outf << "\""<< tr.channel_name(j) << "\"\n";
907 for (int i = 0; i < tr.num_frames(); ++i)
908 if (tr.val(i))
909 *outf << tr.t(i) << "\t" << tr.a(i, j) << endl;
910 else
911 *outf << "move ";
912 }
913 if (outf != &cout)
914 delete outf;
915
916 return write_ok;
917 }
918
919 EST_write_status save_snns_pat(const EST_String filename,
920 EST_TrackList &inpat, EST_TrackList &outpat)
921 {
922 ostream *outf;
923 int num_inputs, num_outputs, num_pats, i;
924 EST_Litem *pi, *po;
925
926 if (filename == "-")
927 outf = &cout;
928 else
929 outf = new ofstream(filename);
930
931 if (!(*outf))
932 return write_fail;
933
934 num_pats = 0;
935 for (pi = inpat.head(); pi ; pi = pi->next())
936 num_pats += inpat(pi).num_frames();
937
938 *outf << "SNNS pattern definition file V3.2\n";
939
940 time_t thetime = time(0);
941 char *date = ctime(&thetime);
942
943 *outf << date;
944 *outf << endl;
945
946 num_inputs = inpat.first().num_channels();
947 num_outputs = outpat.first().num_channels();
948
949 *outf << "No. of patterns : " << num_pats << endl;
950 *outf << "No. of input units : "<< num_inputs << endl;
951 *outf << "No. of output units : "<< num_outputs << endl;
952 *outf << endl << endl;
953
954 for (pi = inpat.head(), po = outpat.head(); pi ;
955 pi = pi->next(), po = po->next())
956 {
957 if (inpat(pi).num_frames() != outpat(pi).num_frames())
958 {
959 cerr << "Error: Input pattern has " << inpat(pi).num_frames()
960 << " output pattern has " << outpat(pi).num_frames() << endl;
961 if (outf != &cout)
962 delete outf;
963 return misc_write_error;
964 }
965 for (i = 0; i < inpat(pi).num_frames(); ++i)
966 {
967 int j;
968 *outf << "#Input pattern " << (i + 1) << ":\n";
969 for (j = 0; j < inpat(pi).num_channels(); ++j)
970 *outf << inpat(pi).a(i, j) << " ";
971 *outf << endl;
972 *outf << "#Output pattern " << (i + 1) << ":\n";
973 for (j = 0; j < outpat(po).num_channels(); ++j)
974 *outf << outpat(po).a(i, j) << " ";
975 *outf << endl;
976 }
977 }
978 if (outf != &cout)
979 delete outf;
980
981 return write_ok;
982 }
983
984 /*
985 EST_write_status EST_TrackFile::save_snns_pat(const EST_String filename,
986 EST_TrackList &trlist)
987 {
988 ostream *outf;
989 int num_inputs, num_outputs, i;
990 EST_Litem *p;
991
992 if (filename == "-")
993 outf = &cout;
994 else
995 outf = new ofstream(filename);
996
997 if (!(*outf))
998 return write_fail;
999
1000 *outf << "SNNS pattern definition file V3.2\n";
1001
1002 char *date;
1003 date = ctime(clock());
1004
1005 *cout << date << endl;
1006
1007 *cout << endl << endl;
1008
1009 num_inputs = tr.first.num_channels();
1010 num_outputs = tr.first.num_channels();
1011
1012 *cout << "No. of patterns : " << tr.size() << endl;
1013 *cout << "No. of input units : "<< num_inputs << endl;
1014 *cout << "No. of output units : "<< num_outputs << endl;
1015
1016 for (i = 0, p = trlist.head(); p ; p = p->next(), ++i)
1017 {
1018 *outf << "#Input pattern " << i << ":\n";
1019 for (int j = 0; j < num_inputs; ++j)
1020 *outf << << trlist(p)._name(j) << "\"\n";
1021 for (int i = 0; i < tr.num_frames(); ++i)
1022 if (tr.val(i))
1023 *outf << tr.t(i) << "\t" << tr.a(i, j) << endl;
1024 else
1025 *outf << "move ";
1026 }
1027 if (outf != &cout)
1028 delete outf;
1029
1030 return write_ok;
1031 }
1032 */
1033
1034 EST_write_status EST_TrackFile::save_xmg(const EST_String filename, EST_Track tr)
1035 {
1036 ostream *outf;
1037 int i, j;
1038 // float min, max;
1039 int sr = 16000; // REORG - fixed sample rate until xmg is fixed
1040
1041 // this takes care of rescaling
1042 tr.change_type(0.0, TRUE);
1043
1044 if (filename == "-")
1045 outf = &cout;
1046 else
1047 outf = new ofstream(filename);
1048
1049 if (!(*outf))
1050 return write_fail;
1051
1052 outf->precision(5);
1053 outf->setf(ios::fixed, ios::floatfield);
1054 outf->width(8);
1055
1056 /* min = max = tr.a(0);
1057 for (i = 0; i < tr.num_frames(); ++i)
1058 {
1059 if (tr.a(i) > max) max = tr.a(i);
1060 if (tr.a(i) < min) min = tr.a(i);
1061 }
1062 */
1063 *outf << "XAO1\n\n"; // xmg header identifier.
1064 *outf << "LineType segments \n";
1065 *outf << "LineStyle solid \n";
1066 *outf << "LineWidth 0 \n";
1067 *outf << "Freq " << sr / 1000 << endl; // a REAL pain!
1068 *outf << "Format Binary \n";
1069 // *outf << "YMin " << ((tr.amin != 0.0) ? tr.amin : min) << endl;
1070 // *outf << "YMax " << ((tr.amax != 0.0) ? tr.amax : max) << endl;
1071 /* if (tr.color != "")
1072 *outf << "LineColor " << tr.color << endl;
1073 */
1074 *outf << char(12) << "\n"; // control L character
1075
1076 // rm_excess_breaks();
1077 // rm_trailing_breaks();
1078 for (i = 0; i < tr.num_frames(); ++i)
1079 if (tr.val(i))
1080 {
1081 *outf << tr.ms_t(i) << "\t";
1082 for (j = 0; j < tr.num_channels(); ++j)
1083 *outf <<tr.a(i, j) << " ";
1084 *outf << endl;
1085 }
1086 else
1087 *outf << "=\n";
1088 if (outf != &cout)
1089 delete outf;
1090
1091 return write_ok;
1092 }
1093
1094 static EST_write_status save_htk_as(const EST_String filename,
1095 EST_Track &orig,
1096 int use_type)
1097 {
1098 // file format is a 12 byte header
1099 // followed by data
1100
1101 // the data is generally floats, except for DISCRETE
1102 // where it is 2 byte ints
1103
1104 float s;
1105
1106 EST_Track track;
1107 int type;
1108 int file_num_channels = orig.num_channels();
1109
1110 if (orig.f_String("contour_type","none") == "ct_lpc")
1111 type = track_to_htk_lpc(orig, track);
1112 else
1113 {
1114 track = orig;
1115 type = use_type;
1116 }
1117
1118 if (track.equal_space() != TRUE)
1119 {
1120 track.change_type(0.0, FALSE);
1121 s = rint((HTK_UNITS_PER_SECOND * EST_Track::default_frame_shift/1000.0)/10.0) * 10.0;
1122 type |= HTK_EST_PS;
1123 file_num_channels += 1;
1124 }
1125 else
1126 {
1127 track.change_type(0.0, FALSE);
1128 s = rint((HTK_UNITS_PER_SECOND * track.shift())/10.0) * 10.0;
1129 }
1130
1131 // hkt files need to be big_endian irrespective of hardware. The
1132 // code here was obviously only ever ran on a Sun. I've tried to
1133 // fix this and it seems to work with floats, don't have data to
1134 // check with shorts though. (Rob, March 2004)
1135
1136 struct htk_header header;
1137
1138 header.num_samps = (EST_BIG_ENDIAN ? track.num_frames()
1139 : SWAPINT(track.num_frames()));
1140
1141
1142 header.samp_period = (EST_BIG_ENDIAN ? (long) s : SWAPINT((long) s));
1143 if(use_type == HTK_DISCRETE)
1144 header.samp_size = (EST_BIG_ENDIAN ? sizeof(short) :
1145 SWAPSHORT(sizeof(short)));
1146 else
1147 header.samp_size = (EST_BIG_ENDIAN ? (sizeof(float) * file_num_channels) :
1148 SWAPSHORT((sizeof(float) * file_num_channels)));
1149
1150 header.samp_type = EST_BIG_ENDIAN ? type : SWAPSHORT(type);
1151
1152 int i, j;
1153 FILE *outf;
1154 if (filename == "-")
1155 outf = stdout;
1156 else if ((outf = fopen(filename,"wb")) == NULL)
1157 {
1158 cerr << "save_htk: cannot open file \"" << filename <<
1159 "\" for writing." << endl;
1160 return misc_write_error;
1161 }
1162
1163 // write the header
1164 fwrite((char*)&(header.num_samps), 1, sizeof(header.num_samps), outf);
1165 fwrite((char*)&(header.samp_period), 1, sizeof(header.samp_period), outf);
1166 fwrite((char*)&(header.samp_size), 1, sizeof(header.samp_size), outf);
1167 fwrite((char*)&(header.samp_type), 1, sizeof(header.samp_type), outf);
1168
1169 // write the data
1170 if(use_type == HTK_DISCRETE)
1171 {
1172 if(track.num_channels() < 1)
1173 {
1174 cerr << "No data to write as HTK_DISCRETE !" << endl;
1175 }
1176 else
1177 {
1178 if(track.num_channels() > 1)
1179 {
1180 cerr << "Warning: multiple channel track being written" << endl;
1181 cerr << " as discrete will only save channel 0 !" << endl;
1182 }
1183 for (i = 0; i < track.num_frames(); ++i)
1184 {
1185 short tempshort = (EST_BIG_ENDIAN ? (short)(track.a(i, 0)) :
1186 SWAPSHORT((short)(track.a(i, 0)))) ;
1187 fwrite((unsigned char*) &tempshort, 1, sizeof(short), outf);
1188 }
1189 }
1190 }
1191 else // not HTK_DISCRETE
1192 for (i = 0; i < track.num_frames(); ++i)
1193 {
1194 if ((type & HTK_EST_PS) != 0)
1195 {
1196 if(!EST_BIG_ENDIAN)
1197 swapfloat(&(track.t(i)));
1198 fwrite((unsigned char*) &(track.t(i)), 1, sizeof(float), outf);
1199 }
1200 for (j = 0; j < track.num_channels(); ++j)
1201 {
1202 if(!EST_BIG_ENDIAN)
1203 swapfloat(&(track.a(i,j)));
1204 fwrite((unsigned char*) &(track.a(i, j)), 1, sizeof(float), outf);
1205 }
1206 }
1207
1208 if (outf != stdout)
1209 fclose(outf);
1210
1211 return write_ok;
1212 }
1213
1214 static int htk_sane_header(htk_header *htk)
1215 {
1216 return htk->num_samps > 0 &&
1217 htk->samp_period > 0 &&
1218 htk->samp_size > 0 &&
1219 htk->samp_size < (short)(UNREASONABLE_FRAME_SIZE * sizeof(float));
1220 }
1221
1222 static int htk_swapped_header(htk_header *header)
1223 {
1224 // Tries to guess if the header is swapped. If so it
1225 // swaps the contents and returns TRUE, other returns FALSE
1226 // HTK doesn't have a magic number so we need heuristics to
1227 // guess when its byte swapped
1228
1229 if (htk_sane_header(header))
1230 return 0;
1231
1232 header->num_samps = SWAPINT(header->num_samps);
1233 header->samp_period = SWAPINT(header->samp_period);
1234 header->samp_size = SWAPSHORT(header->samp_size);
1235 header->samp_type = SWAPSHORT(header->samp_type);
1236
1237 if (htk_sane_header(header))
1238 return 1;
1239
1240 return -1;
1241
1242 }
1243
1244 EST_write_status EST_TrackFile::save_htk(const EST_String filename, EST_Track tmp)
1245 {
1246 return save_htk_as(filename, tmp, HTK_FBANK);
1247 }
1248
1249 EST_write_status EST_TrackFile::save_htk_fbank(const EST_String filename, EST_Track tmp)
1250 {
1251 return save_htk_as(filename, tmp, HTK_FBANK);
1252 }
1253
1254 EST_write_status EST_TrackFile::save_htk_mfcc(const EST_String filename, EST_Track tmp)
1255 {
1256 return save_htk_as(filename, tmp, HTK_MFCC);
1257 }
1258
1259 EST_write_status EST_TrackFile::save_htk_mfcc_e(const EST_String filename, EST_Track tmp)
1260 {
1261 return save_htk_as(filename, tmp, HTK_MFCC | HTK_ENERGY);
1262 }
1263
1264 EST_write_status EST_TrackFile::save_htk_user(const EST_String filename, EST_Track tmp)
1265 {
1266 return save_htk_as(filename, tmp, HTK_USER);
1267 }
1268
1269 EST_write_status EST_TrackFile::save_htk_discrete(const EST_String filename, EST_Track tmp)
1270 {
1271 return save_htk_as(filename, tmp, HTK_DISCRETE);
1272 }
1273
1274
1275 static EST_read_status load_ema_internal(const EST_String filename, EST_Track &tmp, float ishift, float startt, bool swap)
1276 {
1277 (void)ishift;
1278 (void)startt;
1279
1280 int i, j, k, nframes, new_order;
1281 EST_TVector<short> file_data;
1282 int sample_width, data_length;
1283 float shift;
1284 FILE *fp;
1285
1286 if ((fp = fopen(filename, "rb")) == NULL)
1287 {
1288 cerr << "EST_Track load: couldn't open EST_Track input file" << endl;
1289 return misc_read_error;
1290 }
1291
1292 fseek(fp, 0, SEEK_END);
1293 sample_width = 2;
1294 data_length = ftell(fp)/sample_width;
1295 new_order = 10;
1296 nframes = data_length /new_order;
1297 shift = 0.002;
1298
1299 cout << "d length: " << data_length << " nfr " << nframes << endl;
1300
1301 tmp.resize(nframes, new_order);
1302 tmp.fill_time(shift);
1303 tmp.set_equal_space(TRUE);
1304
1305 file_data.resize(data_length);
1306
1307 fseek(fp, 0, SEEK_SET);
1308
1309 if ((int)fread(file_data.memory(), sample_width, data_length, fp) != data_length)
1310 {
1311 fclose(fp);
1312 return misc_read_error;
1313 }
1314
1315 if (swap)
1316 swap_bytes_short(file_data.memory(), data_length);
1317
1318 for (i = k = 0; i < nframes; ++i)
1319 for (j = 0; j < new_order; ++j, ++k)
1320 tmp.a(i, j) = (float)file_data.a_no_check(k);
1321
1322 // name the fields
1323 EST_String t;
1324 // the first 'order' fields are always called c1,c2...
1325 // AWB bug -- the following corrupts memory
1326 /* for (i = 0; i < order; i++)
1327 {
1328 EST_String t2;
1329 t2 = EST_String("c") + itoString(i+1);
1330 tmp.set_field_name(t2, i);
1331 }
1332 i=order;
1333 */
1334 cout << "here \n";
1335
1336 tmp.set_name(filename);
1337 tmp.set_file_type(tff_ema);
1338
1339 fclose(fp);
1340 return format_ok;
1341 }
1342
1343 EST_read_status EST_TrackFile::load_ema(const EST_String filename, EST_Track &tmp, float ishift, float startt)
1344 {
1345 return load_ema_internal(filename, tmp, ishift, startt, FALSE);
1346 }
1347
1348
1349 EST_read_status EST_TrackFile::load_ema_swapped(const EST_String filename, EST_Track &tmp, float ishift, float startt)
1350 {
1351 return load_ema_internal(filename, tmp, ishift, startt, TRUE);
1352 }
1353
1354 #if 0
1355 EST_read_status EST_TrackFile::load_NIST(const EST_String filename, EST_Track &tmp, float ishift, float startt)
1356 {
1357 (void)ishift; // what does this do ?
1358 (void)startt;
1359
1360 char header[NIST_HDR_SIZE];
1361 int samps,sample_width,data_length,actual_bo;
1362 unsigned char *file_data;
1363 enum EST_sample_type_t actual_sample_type;
1364 char *byte_order, *sample_coding;
1365 int n,i,j,k;
1366 int current_pos;
1367 int offset=0;
1368
1369 EST_TokenStream ts;
1370 if (((filename == "-") ? ts.open(cin) : ts.open(filename)) != 0)
1371 {
1372 cerr << "Can't open track file " << filename << endl;
1373 return misc_read_error;
1374 }
1375
1376 current_pos = ts.tell();
1377 if (ts.fread(header,NIST_HDR_SIZE,1) != 1)
1378 return misc_read_error;
1379
1380 if (strncmp(header,NIST_SIG,sizeof(NIST_SIG)) != 0)
1381 return wrong_format;
1382
1383 samps = nist_get_param_int(header,"sample_count",-1);
1384 int num_channels = nist_get_param_int(header,"channel_count",1);
1385 sample_width = nist_get_param_int(header,"sample_n_bytes",2);
1386 int sample_rate =
1387 nist_get_param_int(header,"sample_rate",def_load_sample_rate);
1388 byte_order = nist_get_param_str(header,"sample_byte_format",
1389 (EST_BIG_ENDIAN ? "10" : "01"));
1390 sample_coding = nist_get_param_str(header,"sample_coding","pcm");
1391
1392 data_length = (samps - offset)*num_channels;
1393 file_data = walloc(unsigned char,sample_width * data_length);
1394
1395 ts.seek(current_pos+NIST_HDR_SIZE+(sample_width*offset*(num_channels)));
1396
1397 n = ts.fread(file_data,sample_width,data_length);
1398
1399 if ((n < 1) && (n != data_length))
1400 {
1401 wfree(file_data);
1402 wfree(sample_coding);
1403 wfree(byte_order);
1404 return misc_read_error;
1405 }
1406 else if ((n < data_length) && (data_length/num_channels == n))
1407 {
1408 fprintf(stderr,"TRACK read: nist header is (probably) non-standard\n");
1409 fprintf(stderr,"TRACK read: assuming different num_channel interpretation\n");
1410 data_length = n; /* wrongly headered file */
1411 }
1412 else if (n < data_length)
1413 {
1414 fprintf(stderr,"TRACK read: short file %s\n",
1415 (const char *)ts.filename());
1416 fprintf(stderr,"WAVE read: at %d got %d instead of %d samples\n",
1417 offset,n,data_length);
1418 data_length = n;
1419 }
1420
1421 actual_sample_type = nist_to_sample_type(sample_coding);
1422 actual_bo = ((strcmp(byte_order,"10") == 0) ? bo_big : bo_little);
1423
1424 short *data;
1425 data = convert_raw_data(file_data,data_length,
1426 actual_sample_type,actual_bo);
1427
1428 // copy into the Track
1429 int num_samples = data_length/num_channels;
1430 tmp.resize(num_samples, num_channels);
1431 tmp.set_equal_space(TRUE);
1432 tmp.fill_time(1/(float)sample_rate);
1433
1434 cerr << "shift " << 1/(float)sample_rate << endl;
1435
1436 k=0;
1437 for (i=0; i<num_samples; i++)
1438 {
1439 for (j = 0; j < num_channels; ++j)
1440 tmp.a(i, j) = data[k++]; // channels are simply interleaved
1441 tmp.set_value(i);
1442 }
1443 for (j = 0; j < num_channels; ++j)
1444 tmp.set_channel_name("name", j);
1445
1446
1447
1448 /*
1449 *sample_type = st_short;
1450 *bo = EST_NATIVE_BO;
1451 *word_size = 2;
1452 */
1453
1454 //cerr << "NIST OK" << endl;
1455
1456 return format_ok;
1457 }
1458
1459 EST_write_status EST_TrackFile::save_NIST(const EST_String filename, EST_Track tr)
1460 {
1461 FILE *fd;
1462 int i,j,k=0;
1463 if (filename == "-")
1464 fd = stdout;
1465 else if ((fd = fopen(filename,"wb")) == NULL)
1466 return write_fail;
1467
1468 // create header
1469 char header[NIST_HDR_SIZE], p[1024];;
1470 const char *t;
1471
1472 memset(header,0,1024);
1473 strcat(header, NIST_SIG);
1474 sprintf(p, "channel_count -i %d\n", tr.num_channels());
1475 strcat(header, p);
1476 sprintf(p, "sample_count -i %d\n", tr.num_frames());
1477 strcat(header, p);
1478 int sr = (int)(rint(1/(float)tr.shift()));
1479 sprintf(p, "sample_rate -i %d\n", sr);
1480 strcat(header, p);
1481 t = sample_type_to_nist(st_short);
1482 sprintf(p, "sample_coding -s%d %s\n", (signed)strlen(t), t);
1483 strcat(header, p);
1484
1485 strcat(header, NIST_END_SIG);
1486 /*makes it nice to read */
1487 strcat(header, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
1488
1489 // write header
1490 if (fwrite(&header, 1024, 1, fd) != 1)
1491 return misc_write_error;
1492
1493 // data
1494 short data[tr.num_frames() * tr.num_channels()];
1495
1496
1497 for (i = 0; i < tr.num_frames(); ++i)
1498 // restricted to shorts at this time
1499 for (j = 0; j < tr.num_channels(); ++j)
1500 data[k++] = (short)(tr.a_no_check(i, j));
1501
1502 // byte swapping of output not supported - only write native bo
1503 int bo = str_to_bo("native");
1504 return save_raw_data(fd,data,0,tr.num_frames(),tr.num_channels(),
1505 st_short,bo);
1506
1507 if (fd != stdout)
1508 fclose(fd);
1509 return write_ok;
1510
1511 }
1512 #endif
1513
1514
1515 EST_read_status EST_TrackFile::load_htk(const EST_String filename, EST_Track &tmp, float ishift, float startt)
1516 {
1517 (void)ishift;
1518
1519 // num_values is total number of fields in file
1520 // num_channels is number of fields in resultant track
1521 // order is order of LPC etc. analysis
1522 // e.g. if order is 12 and we have energy and delta then num_values = (12 + 1) * 2 = 26
1523
1524 int i,j, order, new_frames, num_values, num_channels;
1525
1526 EST_String pname;
1527 int swap;
1528 int time_included;
1529
1530 FILE *fp;
1531 struct htk_header header;
1532 int header_sz = sizeof(header);
1533
1534 // numbers A and B for decompression of generally compressed files
1535 float *compressA=NULL, compressA_Buffer[REASONABLE_FRAME_SIZE];
1536 float *compressB=NULL, compressB_Buffer[REASONABLE_FRAME_SIZE];
1537 bool fileIsCompressed=false;
1538
1539 unsigned short samp_type, base_samp_type;
1540
1541 if ((fp = fopen(filename, "rb")) == NULL){
1542 cerr << "EST_Track load: couldn't open EST_Track input file" << endl;
1543 return misc_read_error;
1544 }
1545
1546 // try and read the header
1547 if (fread(&header, header_sz, 1, fp) != 1){
1548 fclose(fp);
1549 return wrong_format;
1550 }
1551
1552 swap = htk_swapped_header(&header); // this is regrettable
1553
1554 if( swap<0 ){
1555 fclose(fp);
1556 return read_format_error;
1557 }
1558
1559 samp_type = header.samp_type;
1560 base_samp_type = samp_type & HTK_MASK;
1561
1562 time_included = (samp_type & HTK_EST_PS) != 0;
1563
1564 switch(base_samp_type){
1565 case HTK_WAVE:
1566 cerr << "Can't read HTK WAVEFORM format file into track" << endl;
1567 return misc_read_error;
1568 break;
1569
1570 case HTK_LPC:
1571 pname = "ct_lpc";
1572 break;
1573
1574 case HTK_LPCREFC:
1575 case HTK_IREFC:
1576 EST_warning( "reading HTK_IREFC and HTK_LPREC parameter types is unsupported" );
1577 fclose( fp );
1578 return read_format_error;
1579 break;
1580
1581 case HTK_LPCCEP:
1582 pname = "ct_cepstrum";
1583 break;
1584
1585 case HTK_LPDELCEP:
1586 // equivalent to HTK_LPCCEP + DELTA
1587 base_samp_type = HTK_LPCCEP;
1588 samp_type = HTK_LPCCEP | HTK_DELTA; // set delta bit
1589 pname = "ct_cepstrum";
1590 break;
1591
1592 case HTK_MFCC:
1593 pname = "ct_other";
1594 break;
1595
1596 case HTK_FBANK:
1597 case HTK_USER:
1598 pname = "ct_other";
1599 break;
1600
1601 case HTK_DISCRETE:
1602 cerr << "Can't read HTK DISCRETE format file into track" << endl;
1603 return misc_read_error;
1604 break;
1605
1606 case HTK_MELSPEC:
1607 pname = "ct_other";
1608 break;
1609
1610 default:
1611 fclose(fp);
1612 return wrong_format;
1613 break;
1614 }
1615
1616 // if we get this far we have decided this is a HTK format file
1617
1618 // handle compressed/uncompressed files differently
1619 if( header.samp_type & HTK_COMP ){
1620
1621 fileIsCompressed = true;
1622
1623 num_channels = num_values = header.samp_size / sizeof(short int);
1624
1625 // get compression numbers A and B
1626 if (num_channels > REASONABLE_FRAME_SIZE){
1627 compressA = new float[num_values];
1628 compressB = new float[num_values];
1629 }
1630 else{
1631 compressA = compressA_Buffer;
1632 compressB = compressB_Buffer;
1633 }
1634
1635 if( (fread( compressA, sizeof(float), num_values, fp )) != static_cast<size_t>(num_values) ){
1636 fclose( fp );
1637 return read_format_error;
1638 }
1639
1640 if( (fread( compressB, sizeof(float), num_values, fp )) != static_cast<size_t>(num_values) ){
1641 fclose( fp );
1642 return read_format_error;
1643 }
1644
1645 if (swap){
1646 swap_bytes_float( compressA, num_values );
1647 swap_bytes_float( compressB, num_values );
1648 }
1649
1650 // subtract extra frames to account for the two vectors of floats
1651 // used for decompression.
1652 new_frames = header.num_samps - (2*(sizeof(float)-sizeof(short int)));
1653 }
1654 else{
1655 num_channels = num_values = header.samp_size / sizeof(float);
1656 new_frames = header.num_samps;
1657 }
1658
1659 if (num_values > UNREASONABLE_FRAME_SIZE){
1660 fclose(fp);
1661 return read_format_error;
1662 }
1663
1664 if (time_included)
1665 num_channels -= 1;
1666
1667 float shift = ((float)header.samp_period/ (float)HTK_UNITS_PER_SECOND);
1668
1669 tmp.resize(new_frames, num_channels);
1670
1671 if ((startt > 0) && (startt < NEARLY_ZERO ))
1672 EST_warning( "setting htk file start to %f", startt );
1673
1674 tmp.fill_time(shift, startt);
1675
1676 tmp.set_equal_space(!time_included);
1677
1678 // check length of file is as expected from header info
1679 long dataBeginPosition = ftell(fp);
1680 if( dataBeginPosition == -1 ){
1681 fclose(fp);
1682 return wrong_format;
1683 }
1684
1685 if (fseek(fp,0,SEEK_END)){
1686 fclose(fp);
1687 return wrong_format;
1688 }
1689
1690 long file_length;
1691 if ((file_length = ftell(fp)) == -1){
1692 fclose(fp);
1693 return wrong_format;
1694 }
1695
1696 long expected_vals;
1697 if( fileIsCompressed ){
1698 expected_vals = (file_length-dataBeginPosition) / sizeof(short int);
1699
1700 if( header.samp_type & HTK_CRC )
1701 expected_vals -= 1; // just ignore the appended cyclic redundancy checksum
1702 }
1703 else
1704 expected_vals = (file_length-dataBeginPosition) / sizeof(float);
1705
1706 /*
1707 printf( "%d %d %d %d %d %d\n",
1708 expected_vals, file_length, dataBeginPosition, sizeof(float), num_values, new_frames );
1709 */
1710
1711 if( expected_vals != (num_values * new_frames) ){
1712 // it probably isn't HTK format after all
1713 fclose(fp);
1714 return wrong_format;
1715 }
1716
1717 // work out the order of the analysis
1718 // Reorg -- surely you can't increase order
1719 order = num_channels;
1720 if( samp_type & HTK_NO_E )
1721 order++;
1722
1723 if( samp_type & HTK_AC )
1724 order /= 3;
1725 else if( samp_type & HTK_DELTA )
1726 order /= 2;
1727
1728 if( samp_type & HTK_ENERGY )
1729 order--;
1730
1731 // go to start of data
1732 if( fseek(fp, dataBeginPosition, SEEK_SET) == -1 ){
1733 cerr << "Couldn't position htk file at start of data" << endl;
1734 fclose(fp);
1735 return misc_read_error;
1736 }
1737
1738 if( fileIsCompressed ){
1739 short int *frame, frame_buffer[REASONABLE_FRAME_SIZE];
1740 if( num_values > REASONABLE_FRAME_SIZE )
1741 frame = new short int[num_values];
1742 else
1743 frame = frame_buffer;
1744
1745 int first_channel = time_included?1:0;
1746
1747 for( i=0; i<new_frames; i++ ){
1748 if( fread( frame, sizeof(short int), num_values, fp ) != (size_t) num_values ){
1749 cerr << "Could not read data from htk track file" << endl;
1750 fclose(fp);
1751
1752 if( frame != frame_buffer )
1753 delete [] frame;
1754 if( compressA != compressA_Buffer )
1755 delete [] compressA;
1756 if( compressB != compressB_Buffer )
1757 delete [] compressB;
1758
1759 return misc_read_error;
1760 }
1761
1762 if( swap )
1763 swap_bytes_short( frame, num_values );
1764
1765 if( time_included )
1766 tmp.t(i) = ((float)frame[0]+compressB[0])/compressA[0];
1767
1768 for( j=0; j<num_channels; ++j ){
1769 int index = j+first_channel;
1770 tmp.a(i,j) = ((float)frame[index]+compressB[index])/compressA[index];
1771 }
1772
1773 tmp.set_value(i);
1774 }
1775
1776 if( frame != frame_buffer )
1777 delete [] frame;
1778 if( compressA != compressA_Buffer )
1779 delete [] compressA;
1780 if( compressB != compressB_Buffer )
1781 delete [] compressB;
1782 }
1783 else{
1784 float *frame, frame_buffer[REASONABLE_FRAME_SIZE];
1785
1786 if (num_values > REASONABLE_FRAME_SIZE)
1787 frame = new float[num_values];
1788 else
1789 frame = frame_buffer;
1790
1791 int first_channel = time_included?1:0;
1792 for( i=0; i<new_frames; i++ ){
1793 if( fread( frame, sizeof(float), num_values, fp ) != (size_t) num_values ){
1794 cerr << "Could not read data from htk track file" << endl;
1795 fclose(fp);
1796 if (frame != frame_buffer)
1797 delete [] frame;
1798 return misc_read_error;
1799 }
1800 if( swap )
1801 swap_bytes_float( frame, num_values );
1802
1803 if( time_included )
1804 tmp.t(i) = frame[0];
1805
1806 for( j=0; j<num_channels; ++j )
1807 tmp.a(i, j) = frame[j+first_channel];
1808
1809 tmp.set_value(i);
1810 }
1811
1812 if( frame != frame_buffer )
1813 delete [] frame;
1814 }
1815
1816 // name the fields
1817 EST_String t;
1818 // the first 'order' fields are always called c1,c2...
1819 // AWB bug -- the following corrupts memory
1820 for (i=0;i<order;i++)
1821 {
1822 EST_String t2;
1823 t2 = EST_String("c") + itoString(i+1);
1824 tmp.set_channel_name(t2, i);
1825 }
1826 i=order;
1827
1828 // energy present and not suppressed
1829 if ( (samp_type & HTK_ENERGY) && !(samp_type & HTK_NO_E) )
1830 tmp.set_channel_name("E", i++);
1831
1832 // delta coeffs ?
1833 if (samp_type & HTK_DELTA){
1834 for (j = 0; j < order; j++){
1835 t = EST_String("c") + itoString(j+1) + "_d";
1836 tmp.set_channel_name(t, i++);
1837 }
1838
1839 // energy ?
1840 if (samp_type & HTK_ENERGY)
1841 tmp.set_channel_name("E_d", i++);
1842 }
1843
1844 // 'acceleration' coeffs ?
1845 if (samp_type & HTK_AC){
1846 for(j=0;j<order;j++){
1847 t = EST_String("ac")+ itoString(j+1)+ "_d_d";
1848 tmp.set_channel_name(t, i++);
1849 }
1850 // energy ?
1851 if (samp_type & HTK_ENERGY)
1852 tmp.set_channel_name("E_d_d", i++);
1853 }
1854
1855 // sanity check
1856 if (i != num_channels){
1857 cerr << "Something went horribly wrong - wanted " << num_values
1858 << " channels in track but got " << i << endl;
1859 fclose(fp);
1860 return wrong_format;
1861 }
1862 tmp.f_set("contour_type",pname);
1863 tmp.set_name(filename);
1864 tmp.set_file_type(tff_htk);
1865 fclose(fp);
1866 return format_ok;
1867 }
1868
1869 /************************************************************************/
1870 /* */
1871 /* Convert single f0 channel tracks into arbitrarily chosen esps FEA */
1872 /* subtype, reputedly to make waves happy. This is evil beyond all */
1873 /* understanding. */
1874 /* */
1875 /************************************************************************/
1876
1877 // format of the desired track.
1878 static struct EST_TrackMap::ChannelMappingElement espsf0_mapping[] =
1879 {
1880 { channel_f0, 0 },
1881 { channel_voiced, 1 },
1882 { channel_power, 2},
1883 { channel_peak, 3},
1884 { channel_unknown, 0}
1885 };
1886 static EST_TrackMap ESPSF0TrackMap(espsf0_mapping);
1887
1888 // It seems that the vital thing is to call the track "F0", and so
1889 // we only need 1 channel instead of the normal 5. This saves *lots* of
1890 // space. For the time being we use 2 channels as the prob_voicnug filed is
1891 // used by our input routine.
1892
1893 int track_to_espsf0(EST_Track &track, EST_Track &f0_track)
1894 {
1895 f0_track.resize(track.num_frames(), 2);
1896
1897 f0_track.assign_map(ESPSF0TrackMap);
1898
1899 // k1 is ratio of the first two cross-correlation values
1900 // f0_track.set_channel_name("k1", 4);
1901
1902 // copy data. Remaining channels zeroed by resize. This is of course stupid
1903 // as if k1 iz zero mathematics is in deep problems.
1904 for (int i = 0; i < track.num_frames(); ++i)
1905 {
1906 f0_track.a(i, channel_voiced) = track.track_break(i) ? 0.1 : 1.2;
1907 f0_track.a(i, channel_f0) = track.track_break(i) ? 0.0: track.a(i,0);
1908 }
1909
1910 f0_track.set_file_type(tff_esps);
1911 f0_track.fill_time(track.shift());
1912 track.set_name(track.name());
1913
1914 /* f0_track.resize(track.num_frames(), 5);
1915
1916 f0_track.assign_map(ESPSF0TrackMap);
1917
1918 // k1 is ratio of the first two cross-correlation values
1919 f0_track.set_channel_name("k1", 4);
1920
1921 // copy data. Remaining channels zeroed by resize. This is of course stupid
1922 // as if k1 iz zero mathematics is in deep problems.
1923 for (int i = 0; i < track.num_frames(); ++i)
1924 {
1925 f0_track.a(i, channel_voiced) = track.track_break(i) ? 0.1 : 1.2;
1926 f0_track.a(i, channel_f0) = track.a(i,0);
1927 }
1928
1929 f0_track.set_file_type("esps");
1930 f0_track.fill_time(track.shift());
1931 track.set_name(track.name());
1932 */
1933
1934 return 0;
1935 }
1936
1937 int espsf0_to_track(EST_Track &fz)
1938 {
1939 int f, p, i;
1940 f = p = -1;
1941
1942 // check to see if prob of voicing channel exists
1943 for (i = 0; i < fz.num_channels(); ++i)
1944 {
1945 if (fz.channel_name(i) == "prob_voice")
1946 p = i;
1947 }
1948 for (i = 0; i < fz.num_channels(); ++i)
1949 {
1950 if (fz.channel_name(i) == "F0")
1951 f = i;
1952 }
1953
1954 for (i = 0; i < fz.num_frames(); ++i)
1955 {
1956 if (p == -1) // if f0 val is < 1 make this a break
1957 {
1958 if (fz.a(i, f) < 1.0)
1959 fz.set_break(i);
1960 else
1961 fz.set_value(i);
1962 }
1963 else // use prob voicing
1964 {
1965 if (fz.a(i, p) < 0.5)
1966 {
1967 fz.a(i, f) = 0.0;
1968 fz.set_break(i);
1969 }
1970 else
1971 fz.set_value(i);
1972 }
1973 }
1974
1975 return 0;
1976 }
1977
1978 int track_to_htk_lpc(EST_Track &track, EST_Track &lpc)
1979 {
1980 int type = HTK_LPC;
1981 int ncoefs, nchannels;
1982
1983 if (track.has_channel(channel_lpc_N))
1984 ncoefs = track.channel_position(channel_lpc_N) - track.channel_position(channel_lpc_0)+1;
1985 else
1986 ncoefs = track.num_channels()-track.channel_position(channel_lpc_0);
1987
1988 nchannels = ncoefs;
1989
1990 if (track.has_channel(channel_power))
1991 {
1992 nchannels++;
1993 type |= HTK_ENERGY;
1994 }
1995
1996 lpc.resize(track.num_frames(), nchannels);
1997 lpc.set_equal_space(track.equal_space());
1998 lpc.set_single_break(track.single_break());
1999 lpc.set_single_break(track.single_break());
2000
2001 for(int i = 0; i< track.num_frames(); i++)
2002 for (int c = 0; c < ncoefs; c++)
2003 {
2004 lpc.a(i, c) = track.a(i, channel_lpc_0, c);
2005 lpc.t(i) = track.t(i);
2006 }
2007
2008
2009 if (track.has_channel(channel_power))
2010 {
2011 for(int ii = 0; ii< track.num_frames(); ii++)
2012 lpc.a(ii, ncoefs) = track.a(ii, channel_power);
2013 }
2014
2015 return type;
2016
2017 }
2018
2019 EST_write_status save_ind_TrackList(EST_TrackList &tlist, EST_String &otype)
2020 {
2021 for (EST_Litem *p = tlist.head(); p ; p = p->next())
2022 tlist(p).save(tlist(p).name(), otype);
2023
2024 return write_ok;
2025 }
2026
2027 EST_read_status read_TrackList(EST_TrackList &tlist, EST_StrList &files,
2028 EST_Option &al)
2029 {
2030 EST_Track s;
2031 EST_Litem *p, *plp;
2032
2033 for (p = files.head(); p; p = p->next())
2034 {
2035 tlist.append(s);
2036 plp = tlist.tail();
2037 if (read_track(tlist(plp), files(p), al) != format_ok)
2038 exit (-1);
2039
2040 tlist(plp).set_name(files(p));
2041 }
2042
2043 return format_ok;
2044 }
2045
2046 int read_track(EST_Track &tr, const EST_String &in_file, EST_Option &al)
2047 {
2048
2049 float ishift = 0;
2050 float startt = 0.0;
2051
2052 if( al.present("-startt") )
2053 startt = al.fval( "-startt" );
2054
2055 if (al.present("ishift"))
2056 ishift = al.fval("ishift");
2057 else if (al.present("-s"))
2058 ishift = al.fval("-s");
2059 else if (al.present("time_channel"))
2060 ishift = 1.0; // doesn't matter, will be reset by track
2061
2062 if (al.present("-itype"))
2063 {
2064 if (tr.load(in_file, al.val("-itype", 0), ishift, startt) != format_ok)
2065 return -1;
2066 }
2067 else
2068 {
2069 if (tr.load(in_file, ishift, startt ) != format_ok)
2070 return -1;
2071 }
2072
2073 // tr.create_map();
2074
2075 // cout << "f0 "<< tr.has_channel(channel_f0) << ".\n";
2076 // if (al.present("time_channel") && tr.has_channel(al.sval("time_channel")))
2077 // {
2078 // cout << " time from channel " << al.sval("time_channel") << "\n";
2079 // channel_to_time(tr, al.sval("time_channel"), al.fval("time_scale"));
2080 // }
2081
2082
2083 // cout << tr;
2084 return 0;
2085 }
2086
2087
2088 EST_String EST_TrackFile::options_short(void)
2089 {
2090 EST_String s("");
2091
2092 for(int n=0; n< EST_TrackFile::map.n() ; n++)
2093 {
2094 const char *nm = EST_TrackFile::map.name(EST_TrackFile::map.token(n));
2095
2096 if (s != "")
2097 s += ", ";
2098
2099 s += nm;
2100
2101 }
2102 return s;
2103 }
2104
2105 EST_String EST_TrackFile::options_supported(void)
2106 {
2107 EST_String s("AvailablE track file formats:\n");
2108
2109 for(int n=0; n< EST_TrackFile::map.n() ; n++)
2110 {
2111 const char *nm = EST_TrackFile::map.name(EST_TrackFile::map.token(n));
2112 const char *d = EST_TrackFile::map.info(EST_TrackFile::map.token(n)).description;
2113
2114 s += EST_String::cat(" ", nm, EST_String(" ")*(13-strlen(nm)), d, "\n");
2115 }
2116 return s;
2117 }
2118
2119 // note the order here defines the order in which loads are tried.
2120 static EST_TValuedEnumDefinition<EST_TrackFileType, const char *, EST_TrackFile::Info> trackfile_names[] =
2121 {
2122 { tff_none, { "none" },
2123 {FALSE, NULL, NULL,
2124 "unknown track file type"}},
2125 {tff_esps, { "esps" },
2126 {TRUE, EST_TrackFile::load_esps, EST_TrackFile::save_esps,
2127 "entropic sps file"}},
2128 {tff_est_ascii, { "est", "est_ascii" },
2129 {TRUE, EST_TrackFile::load_est, EST_TrackFile::save_est_ascii,
2130 "Edinburgh Speech Tools track file"}},
2131 {tff_est_binary, { "est_binary" },
2132 {TRUE, EST_TrackFile::load_est, EST_TrackFile::save_est_binary,
2133 "Edinburgh Speech Tools track file"}}
2134 ,
2135 {tff_htk, { "htk" },
2136 {TRUE, EST_TrackFile::load_htk, EST_TrackFile::save_htk,
2137 "htk file"}},
2138 //{tff_NIST, { "NIST" },
2139 //{TRUE, EST_TrackFile::load_NIST, EST_TrackFile::save_NIST,
2140 // "NIST"}},
2141 {tff_htk_fbank, { "htk_fbank" },
2142 {FALSE, EST_TrackFile::load_htk, EST_TrackFile::save_htk_fbank,
2143 "htk file (as FBANK)"}},
2144 {tff_htk_mfcc, { "htk_mfcc" },
2145 {FALSE, EST_TrackFile::load_htk, EST_TrackFile::save_htk_mfcc,
2146 "htk file (as MFCC)"}},
2147 {tff_htk_mfcc_e, { "htk_mfcc_e" },
2148 {FALSE, EST_TrackFile::load_htk, EST_TrackFile::save_htk_mfcc_e,
2149 "htk file (as MFCC_E)"}},
2150 {tff_htk_user, { "htk_user" },
2151 {FALSE, EST_TrackFile::load_htk, EST_TrackFile::save_htk_user,
2152 "htk file (as USER)"}},
2153 {tff_htk_discrete, { "htk_discrete" },
2154 {FALSE, EST_TrackFile::load_htk, EST_TrackFile::save_htk_discrete,
2155 "htk file (as DISCRETE)"}},
2156 {tff_ssff, {"ssff"},
2157 {TRUE, EST_TrackFile::load_ssff, EST_TrackFile::save_ssff,
2158 "Macquarie University's Simple Signal File Format"}},
2159 {tff_xmg, { "xmg" },
2160 {TRUE, EST_TrackFile::load_xmg, EST_TrackFile::save_xmg,
2161 "xmg file viewer"}},
2162 {tff_xgraph, { "xgraph" },
2163 {FALSE, EST_TrackFile::load_xgraph, EST_TrackFile::save_xgraph,
2164 "xgraph display program format"}},
2165 {tff_ema, { "ema" },
2166 {FALSE, EST_TrackFile::load_ema, NULL,
2167 "ema"}},
2168 {tff_ema_swapped, { "ema_swapped" },
2169 {FALSE, EST_TrackFile::load_ema_swapped, NULL,
2170 "ema, swapped"}},
2171 {tff_ascii, { "ascii" },
2172 {TRUE, EST_TrackFile::load_ascii, EST_TrackFile::save_ascii,
2173 "ascii decimal numbers"}},
2174 { tff_none, {"none"}, {FALSE, NULL, NULL, "unknown track file type"} }
2175 };
2176
2177 EST_TNamedEnumI<EST_TrackFileType, EST_TrackFile::Info> EST_TrackFile::map(trackfile_names);
2178
2179 static EST_TValuedEnumDefinition<EST_TrackFileType, const char *,
2180 EST_TrackFile::TS_Info> track_ts_names[] =
2181 {
2182 { tff_none, { "none" },
2183 {FALSE, NULL, NULL,
2184 "unknown track file type"}},
2185
2186 {tff_est_ascii, {"est"},
2187 {TRUE, EST_TrackFile::load_est_ts, EST_TrackFile::save_est_ts,
2188 "Edinburgh Speech Tools track file"}},
2189
2190 {tff_est_binary, {"est_binary"},
2191 {TRUE, EST_TrackFile::load_est_ts, EST_TrackFile::save_est_binary_ts,
2192 "Edinburgh Speech Tools track file"}},
2193
2194 {tff_ssff, {"ssff"},
2195 {TRUE, EST_TrackFile::load_ssff_ts, EST_TrackFile::save_ssff_ts,
2196 "Macquarie University's Simple Signal File Format"}},
2197
2198 { tff_none, { "none" },
2199 {FALSE, NULL, NULL,
2200 "unknown track file type"}}
2201 };
2202
2203 EST_TNamedEnumI<EST_TrackFileType, EST_TrackFile::TS_Info>
2204 EST_TrackFile::ts_map(track_ts_names);
2205
2206
2207 #if defined(INSTANTIATE_TEMPLATES)
2208
2209 #include "../base_class/EST_TNamedEnum.cc"
2210 template class EST_TNamedEnumI<EST_TrackFileType, EST_TrackFile::Info>;
2211 template class EST_TValuedEnumI<EST_TrackFileType,
2212 const char *, EST_TrackFile::Info>;
2213 template class EST_TNamedEnumI<EST_TrackFileType, EST_TrackFile::TS_Info>;
2214 template class EST_TValuedEnumI<EST_TrackFileType,
2215 const char *, EST_TrackFile::TS_Info>;
2216
2217 #endif
2218