"Fossies" - the Fresh Open Source Software Archive

Member "speech_tools/speech_class/esps_utils.cc" (4 Sep 2017, 34616 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 "esps_utils.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) 1994,1995,1996                        */
    6 /*                        All Rights Reserved.                           */
    7 /*                                                                       */
    8 /*  Permission is hereby granted, free of charge, to use and distribute  */
    9 /*  this software and its documentation without restriction, including   */
   10 /*  without limitation the rights to use, copy, modify, merge, publish,  */
   11 /*  distribute, sublicense, and/or sell copies of this work, and to      */
   12 /*  permit persons to whom this work is furnished to do so, subject to   */
   13 /*  the following conditions:                                            */
   14 /*   1. The code must retain the above copyright notice, this list of    */
   15 /*      conditions and the following disclaimer.                         */
   16 /*   2. Any modifications must be clearly marked as such.                */
   17 /*   3. Original authors' names are not deleted.                         */
   18 /*   4. The authors' names are not used to endorse or promote products   */
   19 /*      derived from this software without specific prior written        */
   20 /*      permission.                                                      */
   21 /*                                                                       */
   22 /*  THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK        */
   23 /*  DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING      */
   24 /*  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT   */
   25 /*  SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE     */
   26 /*  FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES    */
   27 /*  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN   */
   28 /*  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,          */
   29 /*  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF       */
   30 /*  THIS SOFTWARE.                                                       */
   31 /*                                                                       */
   32 /*************************************************************************/
   33 /*                    Author :  Alan W Black (and Paul Taylor)           */
   34 /*                    Date   :  June 1996                                */
   35 /*-----------------------------------------------------------------------*/
   36 /*  These routines form a basis for reading and writing Entropic's ESPS  */
   37 /*  headered files.  The reason we wrote them was to avoid including     */
   38 /*  Entropic's own (large and cumbersome) code into all our programs.    */
   39 /*  No Entropic proprietary code is included in this code which means    */
   40 /*  you do not needs an Entropic licence to use it.                      */
   41 /*                                                                       */
   42 /*  However this should not be seen as anti-Entropic in anyway it is for */
   43 /*  our and your convenience.  We would like to specifically thank       */
   44 /*  Rodney Johnson of Entropic for giving us help and confirming to us   */
   45 /*  the header format is in fact more complex than one can imagine,      */
   46 /*  mostly for very bad reasons, (backward compatibility cripples all    */
   47 /*  software in the long run).  Hence this code is almost definitely     */
   48 /*  incomplete and is not guaranteed to read or create all ESPS files    */
   49 /*  properly but it is adequate for many tasks.                          */
   50 /*                                                                       */
   51 /*  Also thanks go to Peter Kabal from McGill University whose AF code   */
   52 /*  showed me this might be worth attempting, his code gave me something */
   53 /*  to look at to start with.                                            */
   54 /*                                                                       */
   55 /*  I should add, this wasn't easy to write, though I'm much better at   */
   56 /*  octal and hex dumps now.                                             */
   57 /*=======================================================================*/
   58 
   59 #include <cstdio>
   60 #include <cstdlib>
   61 #include "EST_unix.h"
   62 #include <cstring>
   63 #include <time.h>
   64 #include "EST_wave_utils.h"
   65 #include "esps_utils.h"
   66 
   67 /* First you must realise there is in fact a number of very similar but */
   68 /* subtly different header formats that appear on ESPS files.           */
   69 /* ESPS_FEA and ESPS_SD (others for filters, spectrograms, etc)         */
   70 /* The basic format is                                                  */
   71 /*     preamble                                                         */
   72 /*     fixed header                                                     */
   73 /*     variable header                                                  */
   74 /*        field descriptions (type and dimensions)                      */
   75 /*        field names                                                   */
   76 /*        header FEAs (maybe with values)                               */
   77 /*        old and foreign headers (mostly ignored here)                 */
   78 /*     data records themselves                                          */
   79 
   80 /* esps_fea contain a name and possibly a value.  They appear in the    */
   81 /* variable part of the header                                          */
   82 esps_fea new_esps_fea()
   83 {
   84     esps_fea r = walloc(struct ESPS_FEA_struct,1);
   85     r->type = 0;
   86     r->clength = 0;
   87     r->name = NULL;
   88     r->dtype = 0;
   89     r->count = 0;
   90     r->v.ival = NULL;
   91     return r;
   92 }
   93 
   94 void delete_esps_fea(esps_fea r)
   95 {
   96     esps_fea t,u;
   97 
   98     for (t=r; t != NULL; t=u)
   99     {
  100     if (t->clength != 0)
  101         wfree(t->name);
  102     if (t->count != 0) /* this wont work if fields in v aren't aligned */
  103         wfree(t->v.ival);
  104     u = t->next;
  105     wfree(t);
  106     }
  107 }
  108 
  109 void print_esps_fea(esps_fea r)
  110 {
  111     /* Print out the information in the FEA record */
  112     int i;
  113     
  114     fprintf(stdout,"type:  %d\n",r->type);
  115     fprintf(stdout,"name:  %s\n",r->name);
  116     fprintf(stdout,"size:  %d\n",r->count);
  117     fprintf(stdout,"dtype: %d\n",r->dtype);
  118     for (i=0; i<r->count; i++)
  119     switch (r->dtype)
  120     {
  121       case ESPS_DOUBLE:
  122         fprintf(stdout," %d: %g\n",i,r->v.dval[i]); break;
  123       case ESPS_FLOAT:
  124         fprintf(stdout," %d: %f\n",i,r->v.fval[i]); break;
  125       case ESPS_INT:
  126         fprintf(stdout," %d: %d\n",i,r->v.ival[i]); break;
  127       case ESPS_SHORT:
  128         fprintf(stdout," %d: %d\n",i,r->v.sval[i]); break;
  129       case ESPS_CHAR:
  130         fprintf(stdout," %d: %d\n",i,r->v.cval[i]); break;
  131       default:
  132         fprintf(stdout," %d: unknown\n",i);
  133     }
  134 }
  135 
  136 void add_field(esps_hdr hdr, const char *name, int type, int dimension)
  137 {
  138     /* Add a new field to the record */
  139     char **names = hdr->field_name;
  140     short *types = hdr->field_type;
  141     int *dims = hdr->field_dimension;
  142     int i;
  143 
  144     hdr->field_name = walloc(char *,hdr->num_fields+1);
  145     hdr->field_type = walloc(short,hdr->num_fields+1);
  146     hdr->field_dimension = walloc(int,hdr->num_fields+1);
  147     for (i=0; i < hdr->num_fields; i++)
  148     {
  149     hdr->field_name[i] = names[i];
  150     hdr->field_type[i] = types[i];
  151     hdr->field_dimension[i] = dims[i];
  152     }
  153     wfree(names);
  154     wfree(types);
  155     wfree(dims);
  156     hdr->field_name[hdr->num_fields] = wstrdup(name);
  157     hdr->field_type[hdr->num_fields] = type;
  158     hdr->field_dimension[hdr->num_fields] = dimension;
  159     hdr->num_fields++;
  160 
  161     return;
  162 
  163 }
  164 
  165 void add_fea_d(esps_hdr hdr,const char *name, int pos, double d)
  166 {
  167     /* Add a double FEA field to the header */
  168     esps_fea t = new_esps_fea();
  169     int i;
  170 
  171     t->type = 13;  /* must be lucky for some !! */
  172     t->clength = strlen(name);
  173     t->name = wstrdup(name);
  174     if (t->count < pos+1)
  175     {
  176     double *dval = t->v.dval;
  177     t->v.dval = walloc(double,pos+1);
  178     for (i=0; i<t->count; i++)
  179         t->v.dval[i] = dval[i];
  180     for (; i < pos+1; i++)
  181         t->v.dval[i] = 0.0;
  182     wfree(dval);
  183     t->count = pos+1;
  184     }
  185     t->dtype = ESPS_DOUBLE;
  186     t->v.dval[pos] = d;
  187 
  188     t->next = hdr->fea;
  189     hdr->fea = t;
  190 
  191     return;
  192 }
  193 
  194 void add_fea_f(esps_hdr hdr,const char *name, int pos, float d)
  195 {
  196     /* Add a float FEA field to the header */
  197     esps_fea t = new_esps_fea();
  198     int i;
  199 
  200     t->type = 13;
  201     t->clength = strlen(name);
  202     t->name = wstrdup(name);
  203     if (t->count < pos+1)
  204     {
  205     float *fval = t->v.fval;
  206     t->v.fval = walloc(float,pos+1);
  207     for (i=0; i<t->count; i++)
  208         t->v.fval[i] = fval[i];
  209     for (; i < pos+1; i++)
  210         t->v.fval[i] = 0.0;
  211     wfree(fval);
  212     t->count = pos+1;
  213     }
  214     t->dtype = ESPS_FLOAT;
  215     t->v.fval[pos] = d;
  216 
  217     t->next = hdr->fea;
  218     hdr->fea = t;
  219 
  220     return;
  221 }
  222 
  223 void add_fea_i(esps_hdr hdr,const char *name, int pos, int d)
  224 {
  225     /* Add an int FEA field to the header */
  226     esps_fea t = new_esps_fea();
  227     int i;
  228 
  229     t->type = 13;
  230     t->clength = strlen(name);
  231     t->name = wstrdup(name);
  232     if (t->count < pos+1)
  233     {
  234     int *ival = t->v.ival;
  235     t->v.ival = walloc(int,pos+1);
  236     for (i=0; i<t->count; i++)
  237         t->v.ival[i] = ival[i];
  238     for (; i < pos+1; i++)
  239         t->v.ival[i] = 0;
  240     wfree(ival);
  241     t->count = pos+1;
  242     }
  243     t->dtype = ESPS_INT;
  244     t->v.ival[pos] = d;
  245 
  246     t->next = hdr->fea;
  247     hdr->fea = t;
  248 
  249     return;
  250 }
  251 
  252 void add_fea_s(esps_hdr hdr,const char *name, int pos, short d)
  253 {
  254     /* Add a short FEA field to the header */
  255     esps_fea t = new_esps_fea();
  256     int i;
  257 
  258     t->type = 13;
  259     t->clength = strlen(name);
  260     t->name = wstrdup(name);
  261     if (t->count < pos+1)
  262     {
  263     short *sval = t->v.sval;
  264     t->v.sval = walloc(short,pos+1);
  265     for (i=0; i<t->count; i++)
  266         t->v.sval[i] = sval[i];
  267     for (; i < pos+1; i++)
  268         t->v.sval[i] = (short)0;
  269     wfree(sval);
  270     t->count = pos+1;
  271     }
  272     t->dtype = ESPS_SHORT;
  273     t->v.sval[pos] = d;
  274 
  275     t->next = hdr->fea;
  276     hdr->fea = t;
  277 
  278     return;
  279 }
  280 
  281 void add_fea_c(esps_hdr hdr,const char *name, int pos, char d)
  282 {
  283     /* Add a char FEA field to the header */
  284     esps_fea t = new_esps_fea();
  285     int i;
  286 
  287     t->type = 13;
  288     t->clength = strlen(name);
  289     t->name = wstrdup(name);
  290     if (t->count < pos+1)
  291     {
  292     char *cval = t->v.cval;
  293     t->v.cval = walloc(char,pos+1);
  294     for (i=0; i<t->count; i++)
  295         t->v.cval[i] = cval[i];
  296     for (; i < pos+1; i++)
  297         t->v.cval[i] = (char)0;
  298     wfree(cval);
  299     t->count = pos+1;
  300     }
  301     t->dtype = ESPS_CHAR;
  302     t->v.cval[pos] = d;
  303 
  304     t->next = hdr->fea;
  305     hdr->fea = t;
  306 
  307     return;
  308 }
  309 
  310 void add_fea_special(esps_hdr hdr,int type,const char *name)
  311 {
  312     /* Add a special FEA field to the header */
  313     esps_fea t = new_esps_fea();
  314 
  315     t->type = type;
  316     t->clength = strlen(name);
  317     t->name = wstrdup(name);
  318     t->count = 0;
  319     
  320     t->next = hdr->fea;
  321     hdr->fea = t;
  322 
  323     return;
  324 }
  325 
  326 int fea_value_d(const char *name,int pos,esps_hdr hdr, double *d)
  327 {
  328     /* Get value of double FEA */
  329     esps_fea t;
  330     
  331     for (t=hdr->fea; t != NULL; t=t->next)
  332     if (streq(name,t->name))
  333     {
  334         if (t->dtype != ESPS_DOUBLE)
  335         {
  336         fprintf(stderr,"ESPS hdr: access non-double field \"%s\" as double\n",
  337             name);
  338         return -1;
  339         }
  340         *d = t->v.dval[pos];
  341         return 0;
  342     }
  343 
  344     return -1;  /* failed to find it */
  345 }
  346 
  347 int fea_value_f(const char *name,int pos,esps_hdr hdr, float *d)
  348 {
  349     /* Get value of float FEA */
  350     esps_fea t;
  351     
  352     for (t=hdr->fea; t != NULL; t=t->next)
  353     if (streq(name,t->name))
  354     {
  355         if (t->dtype != ESPS_FLOAT)
  356         {
  357         fprintf(stderr,"ESPS hdr: access non-float field \"%s\" as float\n",
  358             name);
  359         return -1;
  360         }
  361         *d = t->v.fval[pos];
  362         return 0;
  363     }
  364 
  365     return -1;  /* failed to find it */
  366 }
  367 
  368 int fea_value_s(const char *name,int pos,esps_hdr hdr, short *d)
  369 {
  370     /* Get value of short FEA */
  371     esps_fea t;
  372     
  373     for (t=hdr->fea; t != NULL; t=t->next)
  374     if (streq(name,t->name))
  375     {
  376         if (t->dtype != ESPS_SHORT)
  377         {
  378         fprintf(stderr,"ESPS hdr: access non-short field \"%s\" as short\n",
  379             name);
  380         return -1;
  381         }
  382         *d = t->v.sval[pos];
  383         return 0;
  384     }
  385 
  386     return -1;  /* failed to find it */
  387 }
  388 
  389 int fea_value_i(const char *name,int pos,esps_hdr hdr, int *d)
  390 {
  391     /* Get value of int FEA */
  392     esps_fea t;
  393     
  394     for (t=hdr->fea; t != NULL; t=t->next)
  395     if (streq(name,t->name))
  396     {
  397         if (t->dtype != ESPS_INT)
  398         {
  399         fprintf(stderr,"ESPS hdr: access non-int field \"%s\" as int\n",
  400             name);
  401         return -1;
  402         }
  403         *d = t->v.ival[pos];
  404         return 0;
  405     }
  406 
  407     return -1;  /* failed to find it */
  408 }
  409 
  410 int fea_value_c(const char *name,int pos,esps_hdr hdr, char *d)
  411 {
  412     /* Get value of int FEA */
  413     esps_fea t;
  414     
  415     for (t=hdr->fea; t != NULL; t=t->next)
  416     if (streq(name,t->name))
  417     {
  418         if (t->dtype != ESPS_CHAR)
  419         {
  420         fprintf(stderr,"ESPS hdr: access non-char field \"%s\" as char\n",
  421             name);
  422         return -1;
  423         }
  424         *d = t->v.cval[pos];
  425         return 0;
  426     }
  427 
  428     return -1;  /* failed to find it */
  429 }
  430 
  431 static int esps_alloc_fea(esps_fea r)
  432 {
  433     switch (r->dtype)
  434     {
  435       case 0: /* nothing */
  436     break;
  437       case ESPS_DOUBLE:
  438     r->v.dval = walloc(double,r->count); break;
  439       case ESPS_FLOAT:
  440     r->v.fval = walloc(float,r->count); break;
  441       case ESPS_INT:
  442     r->v.ival = walloc(int,r->count); break;
  443       case ESPS_SHORT:
  444     r->v.sval = walloc(short,r->count); break;
  445       case ESPS_CHAR:
  446     r->v.cval = walloc(char,r->count); break;
  447       default:
  448     fprintf(stderr,"ESPS file: unsupported FEA dtype\n");
  449     return -1;
  450     }
  451 
  452     return 0;
  453 }
  454 
  455 void write_esps_fea(FILE *fd, esps_fea t,esps_hdr hdr)
  456 {
  457     /* write out this fea */
  458     (void)hdr;
  459     short clength;
  460     char *nspace;
  461     int i;
  462 
  463     fwrite(&t->type,2,1,fd);
  464     clength = (strlen(t->name)+3)/4;
  465     fwrite(&clength,2,1,fd);
  466     nspace = walloc(char, clength*4);
  467     memset(nspace,0,clength*4);
  468     memmove(nspace,t->name,strlen(t->name));
  469     fwrite(nspace,1,clength*4,fd);
  470     wfree(nspace);
  471     if ((t->type == 11) ||
  472     (t->type == 1) ||
  473     (t->type == 15))
  474     return;
  475     fwrite(&t->count,4,1,fd);
  476     fwrite(&t->dtype,2,1,fd);
  477     
  478     for (i=0; i<t->count; i++)
  479     {
  480     switch(t->dtype)
  481     {
  482       case ESPS_DOUBLE: 
  483         fwrite(&t->v.dval[i],8,1,fd); break;
  484       case ESPS_FLOAT: 
  485         fwrite(&t->v.fval[i],4,1,fd); break;
  486       case ESPS_INT: 
  487         fwrite(&t->v.ival[i],4,1,fd); break;
  488       case ESPS_SHORT: 
  489         fwrite(&t->v.sval[i],2,1,fd); break;
  490       case ESPS_CHAR: 
  491         fwrite(&t->v.cval[i],1,1,fd); break;
  492       default:
  493         fprintf(stderr,"ESPS write_hdr: unsupported FEA dtype %d\n",
  494             t->dtype);
  495     }
  496     }
  497     return;
  498 }
  499 
  500 int write_esps_rec(esps_rec r, esps_hdr h, FILE *fd)
  501 {
  502     /* will have to worry about swap someday */
  503     (void)h;
  504     int i;
  505 
  506     for (i=0; i < r->num_fields; i++)
  507     {
  508     switch(r->field[i]->type)
  509     {
  510       case ESPS_DOUBLE:
  511         fwrite(r->field[i]->v.dval,8,r->field[i]->dimension,fd);
  512         break;
  513       case ESPS_FLOAT:
  514         fwrite(r->field[i]->v.fval,4,r->field[i]->dimension,fd);
  515         break;
  516       case ESPS_INT:
  517         fwrite(r->field[i]->v.ival,4,r->field[i]->dimension,fd);
  518         break;
  519       case ESPS_SHORT:
  520         fwrite(r->field[i]->v.sval,2,r->field[i]->dimension,fd);
  521         break;
  522       case ESPS_CHAR:
  523         fwrite(r->field[i]->v.cval,1,r->field[i]->dimension,fd);
  524         break;
  525       case ESPS_CODED:
  526         fwrite(r->field[i]->v.sval,2,r->field[i]->dimension,fd);
  527         break;
  528 
  529       default:
  530         fprintf(stderr,"ESPS file: unsupported field type %d\n",
  531             r->field[i]->type);
  532     }
  533     }
  534     return 0;
  535 }
  536 
  537 esps_fea read_esps_fea(FILE *fd, esps_hdr hdr)
  538 {
  539     /* read next FEA record at point */
  540     esps_fea r = new_esps_fea();
  541     short sdata;
  542     int i;
  543     int idata;
  544     float fdata;
  545     double ddata;
  546     char cdata;
  547 
  548     fread(&sdata,2,1,fd);
  549     if (hdr->swapped) sdata = SWAPSHORT(sdata);
  550     r->type = sdata;
  551     if (r->type == 0)              /* a field name */
  552     {   /* next short is the size in bytes */
  553     fread(&sdata,2,1,fd);
  554     if (hdr->swapped) sdata = SWAPSHORT(sdata);
  555     r->clength = sdata;
  556     }
  557     else if ((r->type == 13) ||   /* a feature and value */
  558              (r->type == 11) ||   /* a single string (comment ?) */
  559              (r->type == 1)  ||   /* a filename */
  560              (r->type == 4)  ||   /* a filename */
  561          (r->type == 15))     /* directory name */
  562     {                 
  563     fread(&sdata,2,1,fd);
  564     if (hdr->swapped) sdata = SWAPSHORT(sdata);
  565     r->clength = sdata * 4;
  566     }
  567     else
  568     {
  569     fprintf(stderr,"ESPS: fea record unknown type\n");
  570     wfree(r);
  571     return NULL;
  572     }
  573     r->name = walloc(char,r->clength+1);
  574     fread(r->name,1,r->clength,fd);
  575     r->name[r->clength] = '\0';
  576     if ((r->type == 11) ||       /* a single string */
  577     (r->type == 1)  ||       /* a filename */
  578     (r->type == 15))         /* directory name */
  579     return r;  
  580     fread(&idata,4,1,fd);
  581     if (hdr->swapped) idata = SWAPINT(idata);
  582     r->count = idata;
  583     fread(&sdata,2,1,fd);
  584     if (hdr->swapped) sdata = SWAPSHORT(sdata);
  585     r->dtype = sdata;
  586     if (esps_alloc_fea(r) == -1)
  587     return NULL;
  588     for (i=0; i<r->count; i++)
  589     {
  590     switch (r->dtype)
  591     {
  592       case ESPS_DOUBLE:
  593         fread(&ddata,8,1,fd);
  594         if (hdr->swapped) swapdouble(&ddata);
  595         r->v.dval[i] = ddata;
  596         break;
  597       case ESPS_FLOAT:
  598         fread(&fdata,4,1,fd);
  599         if (hdr->swapped) swapfloat(&fdata);
  600         r->v.fval[i] = fdata;
  601         break;
  602       case ESPS_INT:
  603         fread(&idata,4,1,fd);
  604         if (hdr->swapped) idata = SWAPINT(idata);
  605         r->v.ival[i] = idata;
  606         break;
  607       case ESPS_SHORT:
  608         fread(&sdata,2,1,fd);
  609         if (hdr->swapped) sdata = SWAPSHORT(sdata);
  610         r->v.sval[i] = sdata;
  611         break;
  612       case ESPS_CHAR:
  613         fread(&cdata,1,1,fd);
  614         r->v.cval[i] = cdata;
  615         break;
  616       default:
  617         fprintf(stderr,"ESPS read_hdr: unsupported FEA dtype %d\n",r->dtype);
  618         wfree(r);
  619         return NULL;
  620     }
  621     }
  622 
  623     return r;
  624 }    
  625 
  626 static char *esps_get_field_name(FILE *fd, esps_hdr hdr, int expect_source)
  627 {
  628     /* read the next field name */
  629   short size=0;  /* bet its really a short */
  630   char *name;
  631   
  632   if (fread(&size,2,1,fd) != 1)
  633     {
  634       fputs("error reading field name size\n", stderr);
  635       return wstrdup("ERROR");
  636     }
  637   if (hdr->swapped) size = SWAPSHORT(size);
  638   name = walloc(char,size+1);
  639   if (fread(name,1,size,fd) != (unsigned)size)
  640     {
  641       fputs("error reading field name\n", stderr);
  642       strncpy(name, "ERROR", size);
  643     }
  644   name[size] = '\0';
  645   if (hdr->file_type == ESPS_SD || expect_source)
  646     fseek(fd,6,SEEK_CUR);  /* skip some zeroes */
  647   else
  648     fseek(fd,2,SEEK_CUR);
  649 
  650   if (expect_source)
  651     {
  652       fread(&size,2,1,fd);
  653       if (hdr->swapped) size = SWAPSHORT(size);
  654       fseek(fd,size,SEEK_CUR);
  655     }
  656 
  657   return name;
  658 }
  659 
  660 static void esps_put_field_name(char *name,FILE *fd, esps_hdr hdr)
  661 {
  662     /* write the next field name */
  663     short size = strlen(name);
  664     short shortdata;
  665 
  666     shortdata = 0;
  667     fwrite(&shortdata,2,1,fd);
  668     fwrite(&size,2,1,fd);
  669     fwrite(name,1,size,fd);
  670     if (hdr->file_type == ESPS_SD)
  671     {
  672     shortdata = 0;
  673     fwrite(&shortdata,2,1,fd);
  674     fwrite(&shortdata,2,1,fd);
  675     fwrite(&shortdata,2,1,fd);
  676     }
  677     return;
  678 }
  679 
  680 esps_hdr new_esps_hdr(void)
  681 {
  682     esps_hdr h = walloc(struct ESPS_HDR_struct,1);
  683     h->file_type = ESPS_FEA;
  684     h->swapped = FALSE;
  685     h->num_records = 0;
  686     h->num_fields = 0;
  687     h->field_name = NULL;
  688     h->field_type = NULL;
  689     h->field_dimension = NULL;
  690     h->fea = NULL;
  691     return h;
  692 }
  693 
  694 void delete_esps_hdr(esps_hdr h)
  695 {
  696     int i;
  697     if (h != NULL)
  698     {
  699     if (h->field_name != NULL)
  700     {
  701         for (i=0; i < h->num_fields; i++)
  702         wfree(h->field_name[i]);
  703         wfree(h->field_name);
  704     }
  705     delete_esps_fea(h->fea);
  706     }
  707 }
  708 
  709 esps_rec new_esps_rec(esps_hdr hdr)
  710 {
  711     /* New esps record */
  712     esps_rec r = walloc(struct ESPS_REC_struct,1);
  713     int i,size;
  714 
  715     r->field = walloc(esps_field,hdr->num_fields);
  716     for (size=0,i=0; i < hdr->num_fields; i++)
  717     {
  718     r->field[i]=walloc(struct ESPS_FIELD_struct,1);
  719     r->field[i]->type = hdr->field_type[i];
  720     r->field[i]->dimension = hdr->field_dimension[i];
  721     switch(r->field[i]->type)
  722     {
  723       case ESPS_DOUBLE:
  724         r->field[i]->v.dval = walloc(double,r->field[i]->dimension);
  725         size += 8;
  726         break;
  727       case ESPS_FLOAT:
  728         r->field[i]->v.fval = walloc(float,r->field[i]->dimension);
  729         size += 4;
  730         break;
  731       case ESPS_INT:
  732         r->field[i]->v.ival = walloc(int,r->field[i]->dimension);
  733         size += 4;
  734         break;
  735       case ESPS_SHORT:
  736         r->field[i]->v.sval = walloc(short,r->field[i]->dimension);
  737         size += 2;
  738         break;
  739       case ESPS_CHAR:
  740         r->field[i]->v.cval = walloc(char,r->field[i]->dimension);
  741         size += 1;
  742         break;
  743       case ESPS_CODED:
  744         r->field[i]->v.sval = walloc(short,r->field[i]->dimension);
  745         size += 2;
  746         break;
  747       default:
  748         fprintf(stderr,"ESPS file: unsupported field type %d\n",
  749             r->field[i]->type);
  750     }
  751     }
  752     r->num_fields = hdr->num_fields;
  753     r->size = size;
  754     return r;
  755 
  756 }
  757 
  758 void delete_esps_rec(esps_rec r)
  759 {
  760     int i;
  761 
  762     for (i=0; i<r->num_fields; i++)
  763     {
  764     wfree(r->field[i]->v.ival);
  765     wfree(r->field[i]);
  766     }
  767     wfree(r->field);
  768     return;
  769 }
  770 
  771 int read_esps_rec(esps_rec r, esps_hdr hdr, FILE *fd)
  772 {
  773     /* read the next record at point */
  774     int i,j;
  775     double doubledata;
  776     float floatdata;
  777     int intdata;
  778     short shortdata;
  779     
  780     for (i=0; i< r->num_fields; i++)
  781     {
  782     switch (r->field[i]->type)
  783     {
  784       case ESPS_DOUBLE:
  785         for(j=0; j < r->field[i]->dimension; j++)
  786         {
  787         if (fread(&doubledata,8,1,fd) == 0) return EOF;
  788         if (hdr->swapped) swapdouble(&doubledata);
  789         r->field[i]->v.dval[j] = doubledata;
  790         }
  791         break;
  792       case ESPS_FLOAT:
  793         for(j=0; j < r->field[i]->dimension; j++)
  794         {
  795         if (fread(&floatdata,4,1,fd) == 0) return EOF;
  796         if (hdr->swapped) swapfloat(&floatdata);
  797         r->field[i]->v.fval[j] = floatdata;
  798         }
  799         break;
  800       case ESPS_INT:
  801         for(j=0; j < r->field[i]->dimension; j++)
  802         {
  803         if (fread(&intdata,4,1,fd) == 0) return EOF;
  804         if (hdr->swapped) intdata = SWAPINT(intdata);
  805         r->field[i]->v.ival[j] = intdata;
  806         }
  807         break;
  808       case ESPS_SHORT:
  809         for(j=0; j < r->field[i]->dimension; j++)
  810         {
  811         if (fread(&shortdata,2,1,fd) == 0) return EOF;
  812         if (hdr->swapped) shortdata = SWAPSHORT(shortdata);
  813         r->field[i]->v.sval[j] = shortdata;
  814         }
  815         break;
  816       case ESPS_CHAR:
  817         if (fread(r->field[i]->v.cval,1,r->field[i]->dimension,fd) !=
  818         (unsigned)r->field[i]->dimension) return EOF;
  819         break;
  820       case ESPS_CODED:
  821         for(j=0; j < r->field[i]->dimension; j++)
  822         {
  823         if (fread(&shortdata,2,1,fd) == 0) return EOF;
  824         if (hdr->swapped) shortdata = SWAPSHORT(shortdata);
  825         r->field[i]->v.sval[j] = shortdata;
  826         }
  827         break;
  828       default:
  829         fprintf(stderr,"ESPS file: unsupported field type %d\n",
  830             r->field[i]->type);
  831         return EOF;
  832     }
  833 
  834     }
  835     
  836     return 0;
  837 
  838 }
  839 
  840 double get_field_d(esps_rec r, int field, int pos)
  841 {
  842     return r->field[field]->v.dval[pos];
  843 }
  844 float get_field_f(esps_rec r, int field, int pos)
  845 {
  846     return r->field[field]->v.fval[pos];
  847 }
  848 int get_field_i(esps_rec r, int field, int pos)
  849 {
  850     return r->field[field]->v.ival[pos];
  851 }
  852 short get_field_s(esps_rec r, int field, int pos)
  853 {
  854     return r->field[field]->v.sval[pos];
  855 }
  856 char get_field_c(esps_rec r, int field, int pos)
  857 {
  858     return r->field[field]->v.cval[pos];
  859 }
  860 void set_field_d(esps_rec r, int field, int pos, double d)
  861 {
  862     r->field[field]->v.dval[pos] = d;
  863 }
  864 void set_field_f(esps_rec r, int field, int pos, float d)
  865 {
  866     r->field[field]->v.fval[pos] = d;
  867 }
  868 void set_field_i(esps_rec r, int field, int pos, int d)
  869 {
  870     r->field[field]->v.ival[pos] = d;
  871 }
  872 void set_field_s(esps_rec r, int field, int pos, short d)
  873 {
  874     r->field[field]->v.sval[pos] = d;
  875 }
  876 void set_field_c(esps_rec r, int field, int pos, char d)
  877 {
  878     r->field[field]->v.cval[pos] = d;
  879 }
  880 
  881 int esps_record_size(esps_hdr hdr)
  882 {
  883     /* works out the number of bytes in a record */
  884     esps_rec r = new_esps_rec(hdr);
  885     int size = r->size;
  886     delete_esps_rec(r);
  887 
  888     return size;
  889 }
  890 
  891 static int esps_num_of_type(int type,esps_hdr hdr)
  892 {
  893     /* counts up the number of occurrences of fields of type in a record */
  894     int i;
  895     int sum;
  896 
  897     for (sum=i=0; i < hdr->num_fields; i++)
  898     if (hdr->field_type[i] == type)
  899         sum++;
  900     return sum;
  901 }    
  902 
  903 
  904 esps_hdr make_esps_sd_hdr(void)
  905 {
  906     /* returns a basic header for an ESPS_SD file */
  907     esps_hdr hdr = new_esps_hdr();
  908     hdr->file_type = ESPS_SD;
  909     return hdr;
  910 
  911 }
  912 
  913 esps_hdr make_esps_hdr(void)
  914 {
  915     /* returns a basic header for an ESPS_SD file */
  916     esps_hdr hdr = new_esps_hdr();
  917     hdr->file_type = ESPS_FEA;
  918     return hdr;
  919 
  920 }
  921 
  922 enum EST_read_status read_esps_hdr(esps_hdr *uhdr,FILE *fd)
  923 {
  924     /* reads an ESPS header from fd at point (should be position 0) */
  925     /* leaves point at start of data (immediately after header)     */
  926     struct ESPS_PREAMBLE preamble;
  927     struct ESPS_FIXED_HDR fhdr;
  928     esps_hdr hdr;
  929     int end,pos,intdata,i;
  930     short shortdata;
  931     double sd_sample_rate;
  932     int typematch;
  933     int swap;
  934     short name_flag;
  935 
  936     fread(&preamble,sizeof(preamble),1,fd);
  937     if (preamble.check == ESPS_MAGIC)
  938     swap = FALSE;
  939     else if (preamble.check == SWAPINT(ESPS_MAGIC))
  940     swap = TRUE;
  941     else
  942     return wrong_format;
  943 
  944     hdr = new_esps_hdr();
  945     hdr->swapped = swap;
  946     fread(&fhdr,sizeof(fhdr),1,fd);
  947     if (hdr->swapped) 
  948     {
  949     preamble.data_offset = SWAPINT(preamble.data_offset);
  950     preamble.record_size = SWAPINT(preamble.record_size);
  951     fhdr.num_samples = SWAPINT(fhdr.num_samples);
  952     fhdr.num_doubles = SWAPINT(fhdr.num_doubles);
  953     fhdr.num_floats = SWAPINT(fhdr.num_floats);
  954     fhdr.num_ints = SWAPINT(fhdr.num_ints);
  955     fhdr.num_shorts = SWAPINT(fhdr.num_shorts);
  956     fhdr.num_chars = SWAPINT(fhdr.num_chars);
  957     fhdr.fea_type = SWAPSHORT(fhdr.fea_type);
  958     fhdr.num_fields = SWAPSHORT(fhdr.num_fields);
  959     }
  960     pos = ftell(fd);
  961     if (fhdr.num_samples == 0)  /* has to be derived from the file size */
  962     {
  963     pos = ftell(fd);
  964     fseek(fd,0,SEEK_END);
  965     end = ftell(fd);
  966     fseek(fd,pos,SEEK_SET);
  967     fhdr.num_samples = (end - preamble.data_offset)/preamble.record_size;
  968     }
  969     hdr->num_records = fhdr.num_samples;
  970     hdr->num_fields = fhdr.num_fields;
  971     hdr->hdr_size = preamble.data_offset;
  972     if (fhdr.thirteen == 9)
  973     {   /* esps identifies such files are as Sample Data Files */
  974     hdr->file_type = ESPS_SD;
  975     /* fake the rest to make it appear like other SD files */
  976     hdr->num_fields = 1;
  977     hdr->field_dimension = walloc(int,hdr->num_fields);
  978     hdr->field_dimension[0] = 1;
  979     hdr->field_type = walloc(short,hdr->num_fields);
  980     hdr->field_type[0] = ESPS_SHORT;
  981     hdr->field_name = walloc(char *,1);
  982     hdr->field_name[0] = wstrdup("samples");
  983     fseek(fd,hdr->hdr_size,SEEK_SET);
  984     /* In this cases its just in the header as a float */
  985     sd_sample_rate = *((float *)(void *)&fhdr.fil4[0]);
  986     add_fea_d(hdr,"record_freq",0,(double)sd_sample_rate);
  987     *uhdr = hdr;
  988     return format_ok;
  989     }
  990     else if ((fhdr.fea_type == 8) &&
  991          (hdr->num_fields == 1) &&
  992          ((fhdr.num_shorts*2) == preamble.record_size))
  993     hdr->file_type = ESPS_SD;  /* this is a heuristic */
  994     else
  995     hdr->file_type = ESPS_FEA;
  996     /* Now we have the field descriptions */
  997     
  998     /* 0000 0001 dimensions */
  999     hdr->field_dimension = walloc(int,hdr->num_fields);
 1000     for (i=0; i<hdr->num_fields; i++)                   
 1001     {
 1002     fread(&intdata,4,1,fd);                         /* dimensions */
 1003     if (hdr->swapped) intdata = SWAPINT(intdata);
 1004     hdr->field_dimension[i] = intdata;
 1005     }
 1006     /* 0 -> num_fields-1 -- probably ordering information */
 1007     fseek(fd,hdr->num_fields*4,SEEK_CUR);               /* ordering info */
 1008     fseek(fd,hdr->num_fields*2,SEEK_CUR);               /* zeros */
 1009     hdr->field_type = walloc(short,hdr->num_fields);    
 1010     for (i=0; i<hdr->num_fields; i++)
 1011     {
 1012     fread(&shortdata,2,1,fd);                       /* field types */  
 1013     if (hdr->swapped) shortdata = SWAPSHORT(shortdata);
 1014     hdr->field_type[i] = shortdata;
 1015     }
 1016     typematch = TRUE;
 1017     fread(&intdata,4,1,fd);                             /* number of doubles */
 1018     if (hdr->swapped) intdata = SWAPINT(intdata);
 1019     if (fhdr.num_doubles != intdata) typematch = FALSE;
 1020     fread(&intdata,4,1,fd);                             /* number of floats */
 1021     if (hdr->swapped) intdata = SWAPINT(intdata);
 1022     if (fhdr.num_floats != intdata) typematch = FALSE;
 1023     fread(&intdata,4,1,fd);                             /* number of ints */
 1024     if (hdr->swapped) intdata = SWAPINT(intdata);
 1025     if (fhdr.num_ints != intdata) typematch = FALSE;
 1026     fread(&intdata,4,1,fd);                             /* number of shorts */
 1027     if (hdr->swapped) intdata = SWAPINT(intdata);
 1028     if (fhdr.num_shorts != intdata) typematch = FALSE;
 1029     fread(&intdata,4,1,fd);                             /* number of chars */
 1030     if (hdr->swapped) intdata = SWAPINT(intdata);
 1031     if (fhdr.num_chars != intdata) typematch = FALSE;
 1032     if ((hdr->file_type != ESPS_SD) && (typematch == FALSE))
 1033     {
 1034     fprintf(stderr,"ESPS hdr: got lost in the header (record description)\n");
 1035     delete_esps_hdr(hdr);
 1036     return misc_read_error;
 1037     }
 1038     /* other types ... */
 1039     fseek(fd,9*2,SEEK_CUR);                             /* other types */
 1040     fseek(fd,hdr->num_fields*2,SEEK_CUR);               /* zeros */
 1041     /* Now we can read the field names */
 1042     hdr->field_name = walloc(char *,hdr->num_fields);
 1043 
 1044     fread(&name_flag, 2, 1, fd);
 1045     if (hdr->swapped) name_flag = SWAPSHORT(name_flag);
 1046 
 1047     for (i=0; i < hdr->num_fields; i++)
 1048     hdr->field_name[i] = esps_get_field_name(fd,hdr,name_flag); /* field names */
 1049     if (hdr->file_type == ESPS_SD)
 1050     {   /* Only one field 'samples' */
 1051     if (!streq(hdr->field_name[0],"samples"))
 1052     {
 1053         fprintf(stderr,"ESPS hdr: guessed wrong about FEA_SD file (no 'samples' field)\n");
 1054         delete_esps_hdr(hdr);
 1055         return misc_read_error;
 1056     }
 1057     }
 1058 
 1059     /* Now fea, feature and value -- but how many are there ? */
 1060     while (ftell(fd) < preamble.data_offset-4)
 1061     {
 1062     esps_fea r = read_esps_fea(fd,hdr);              /* feas */
 1063     if (r == NULL) break;
 1064 /*  print_esps_fea(r); */
 1065     r->next = hdr->fea;
 1066     hdr->fea = r;
 1067     if (r->type == 1) 
 1068         break; /* I think this (filename) is last FEA */
 1069     }
 1070     /* There's other gunk after this but I think I've done enough */
 1071     /* The rest seems to be mostly previous headers               */
 1072 
 1073     fseek(fd,hdr->hdr_size,SEEK_SET); /* skip the rest of the header */
 1074     *uhdr = hdr;
 1075     
 1076     return format_ok;
 1077 }
 1078 
 1079 
 1080 enum EST_write_status write_esps_hdr(esps_hdr hdr,FILE *fd)
 1081 {
 1082     /* well here's the scary part, try to write a valid file hdr to */
 1083     /* the file                                                     */
 1084     struct ESPS_PREAMBLE preamble;
 1085     struct ESPS_FIXED_HDR fhdr;
 1086     time_t tx = time(0);
 1087     esps_fea t;
 1088     int i,intdata;
 1089     short shortdata;
 1090 
 1091     memset(&preamble,0,sizeof(preamble));
 1092     memset(&fhdr,0,sizeof(fhdr));
 1093     /* I can't really make the machine code work properly, so I'll  */
 1094     /* just fix it for the two major byte orders to Sun and Suni386 */
 1095     if (EST_NATIVE_BO == bo_big)
 1096     preamble.machine_code = 4;  /* a sun */
 1097     else
 1098     preamble.machine_code = 6;  /* a suni386 */
 1099     preamble.check_code  = 3000;  /* ? */
 1100     preamble.data_offset = 0;  /* will come back and fix this later */
 1101     preamble.record_size = esps_record_size(hdr);
 1102     preamble.check = ESPS_MAGIC;
 1103     preamble.edr = 0;
 1104     preamble.fil1 = 0;
 1105     preamble.foreign_hd = 0; /* docs say it should be -1, but its always 0 */
 1106 
 1107     fhdr.thirteen = 13;      /* must be for luck */
 1108     fhdr.sdr_size = 0;
 1109     fhdr.magic = ESPS_MAGIC;
 1110     strncpy(fhdr.date,ctime(&tx),26);
 1111     sprintf(fhdr.version,"1.91");  /* that's what all the others have */
 1112     sprintf(fhdr.prog,"EDST");
 1113     sprintf(fhdr.vers,"0.1");
 1114     strncpy(fhdr.progcompdate,ctime(&tx),26);
 1115     fhdr.num_samples = hdr->num_records;
 1116     fhdr.filler = 0;
 1117     /* in each record */
 1118     fhdr.num_doubles = esps_num_of_type(ESPS_DOUBLE,hdr);
 1119     fhdr.num_floats  = esps_num_of_type(ESPS_FLOAT,hdr);
 1120     fhdr.num_ints    = esps_num_of_type(ESPS_INT,hdr);
 1121     fhdr.num_shorts  = esps_num_of_type(ESPS_SHORT,hdr);
 1122     fhdr.num_chars   = esps_num_of_type(ESPS_CHAR,hdr);
 1123     fhdr.fsize = 40;
 1124     fhdr.hsize = 0;    /* given value below on second shot */
 1125     if (hdr->file_type == ESPS_SD)
 1126     fhdr.fea_type = 8;
 1127     else
 1128     fhdr.fea_type = 0;
 1129     fhdr.num_fields = hdr->num_fields;
 1130 
 1131     fwrite(&preamble,sizeof(preamble),1,fd);
 1132     fwrite(&fhdr,sizeof(fhdr),1,fd);
 1133     /* The following cover dimensions, type and ordering info */
 1134     for (i=0; i < hdr->num_fields; i++)
 1135     {   /* Dimensions (i.e. number of channels) */
 1136     intdata = 1;
 1137     fwrite(&intdata,4,1,fd);                        /* dimensions */
 1138     }
 1139     for (i=0; i < hdr->num_fields; i++)                 /* ordering info (?) */
 1140     fwrite(&i,4,1,fd);
 1141     if (hdr->file_type == ESPS_SD)  /* zeros hmm should be zeroes only */
 1142     shortdata = 1;              /* is FEA case, 1 in ESPS_SD case  */
 1143     else                            /* fixed 24/7/98                   */
 1144     shortdata = 0;
 1145     for (i=0; i < hdr->num_fields; i++)
 1146     fwrite(&shortdata,2,1,fd);     
 1147     for (i=0; i < hdr->num_fields; i++)    
 1148     {
 1149     shortdata = hdr->field_type[0];                 /* field types */
 1150     fwrite(&shortdata,2,1,fd);
 1151     }
 1152     intdata = fhdr.num_doubles;                        /* number of doubles */
 1153     fwrite(&intdata,4,1,fd);
 1154     intdata = fhdr.num_floats;                         /* number of floats */
 1155     fwrite(&intdata,4,1,fd);
 1156     intdata = fhdr.num_ints;                           /* number of ints */
 1157     fwrite(&intdata,4,1,fd);
 1158     intdata = fhdr.num_shorts;                         /* number of shorts */
 1159     fwrite(&intdata,4,1,fd);
 1160     intdata = fhdr.num_chars;                          /* number of chars */
 1161     fwrite(&intdata,4,1,fd);
 1162     shortdata = 0;
 1163     for (i=0; i < 9; i++)
 1164     fwrite(&shortdata,2,1,fd);                      /* other types */
 1165     for (i=0; i < hdr->num_fields; i++)
 1166     fwrite(&shortdata,2,1,fd);                      /* zeros */
 1167     /* Now dump the filednames */
 1168     for (i=0; i < hdr->num_fields; i++)
 1169     esps_put_field_name(hdr->field_name[i],fd,hdr); /* field names */
 1170     if (hdr->file_type != ESPS_SD)
 1171     fwrite(&shortdata,2,1,fd);   /* another 0 */
 1172     /* Now the feas */
 1173     for (t=hdr->fea; t != NULL; t=t->next)
 1174     write_esps_fea(fd,t,hdr);                       /* feas */
 1175     /* now have to go back and fix the header size */
 1176     intdata = 0;
 1177     fwrite(&intdata,4,1,fd);
 1178     preamble.data_offset = ftell(fd);
 1179     fhdr.hsize = (preamble.data_offset-249)/2;
 1180     if (fseek(fd,0,SEEK_SET) == -1)
 1181     {
 1182     fprintf(stderr,"esps write header: can't fseek to start of file\n");
 1183     return misc_write_error;
 1184     }
 1185     fwrite(&preamble,sizeof(preamble),1,fd);
 1186     fwrite(&fhdr,sizeof(fhdr),1,fd);
 1187     fseek(fd,preamble.data_offset,SEEK_SET);
 1188     
 1189     return write_ok;
 1190 }