"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:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "EST_TrackFile.cc" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.4-release_vs_2.5.0-release.

    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