/*************************************************************************/ /* */ /* Centre for Speech Technology Research */ /* University of Edinburgh, UK */ /* Copyright (c) 1994,1995,1996 */ /* All Rights Reserved. */ /* */ /* Permission is hereby granted, free of charge, to use and distribute */ /* this software and its documentation without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of this work, and to */ /* permit persons to whom this work is furnished to do so, subject to */ /* the following conditions: */ /* 1. The code must retain the above copyright notice, this list of */ /* conditions and the following disclaimer. */ /* 2. Any modifications must be clearly marked as such. */ /* 3. Original authors' names are not deleted. */ /* 4. The authors' names are not used to endorse or promote products */ /* derived from this software without specific prior written */ /* permission. */ /* */ /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */ /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */ /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */ /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */ /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */ /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */ /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */ /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */ /* THIS SOFTWARE. */ /* */ /*************************************************************************/ /* Author : Alan W Black (and Paul Taylor) */ /* Date : June 1996 */ /*-----------------------------------------------------------------------*/ /* These routines form a basis for reading and writing Entropic's ESPS */ /* headered files. The reason we wrote them was to avoid including */ /* Entropic's own (large and cumbersome) code into all our programs. */ /* No Entropic proprietary code is included in this code which means */ /* you do not needs an Entropic licence to use it. */ /* */ /* However this should not be seen as anti-Entropic in anyway it is for */ /* our and your convenience. We would like to specifically thank */ /* Rodney Johnson of Entropic for giving us help and confirming to us */ /* the header format is in fact more complex than one can imagine, */ /* mostly for very bad reasons, (backward compatibility cripples all */ /* software in the long run). Hence this code is almost definitely */ /* incomplete and is not guaranteed to read or create all ESPS files */ /* properly but it is adequate for many tasks. */ /* */ /* Also thanks go to Peter Kabal from McGill University whose AF code */ /* showed me this might be worth attempting, his code gave me something */ /* to look at to start with. */ /* */ /* I should add, this wasn't easy to write, though I'm much better at */ /* octal and hex dumps now. */ /*=======================================================================*/ #include #include #include "EST_unix.h" #include #include #include "EST_wave_utils.h" #include "esps_utils.h" /* First you must realise there is in fact a number of very similar but */ /* subtly different header formats that appear on ESPS files. */ /* ESPS_FEA and ESPS_SD (others for filters, spectrograms, etc) */ /* The basic format is */ /* preamble */ /* fixed header */ /* variable header */ /* field descriptions (type and dimensions) */ /* field names */ /* header FEAs (maybe with values) */ /* old and foreign headers (mostly ignored here) */ /* data records themselves */ /* esps_fea contain a name and possibly a value. They appear in the */ /* variable part of the header */ esps_fea new_esps_fea() { esps_fea r = walloc(struct ESPS_FEA_struct,1); r->type = 0; r->clength = 0; r->name = NULL; r->dtype = 0; r->count = 0; r->v.ival = NULL; return r; } void delete_esps_fea(esps_fea r) { esps_fea t,u; for (t=r; t != NULL; t=u) { if (t->clength != 0) wfree(t->name); if (t->count != 0) /* this wont work if fields in v aren't aligned */ wfree(t->v.ival); u = t->next; wfree(t); } } void print_esps_fea(esps_fea r) { /* Print out the information in the FEA record */ int i; fprintf(stdout,"type: %d\n",r->type); fprintf(stdout,"name: %s\n",r->name); fprintf(stdout,"size: %d\n",r->count); fprintf(stdout,"dtype: %d\n",r->dtype); for (i=0; icount; i++) switch (r->dtype) { case ESPS_DOUBLE: fprintf(stdout," %d: %g\n",i,r->v.dval[i]); break; case ESPS_FLOAT: fprintf(stdout," %d: %f\n",i,r->v.fval[i]); break; case ESPS_INT: fprintf(stdout," %d: %d\n",i,r->v.ival[i]); break; case ESPS_SHORT: fprintf(stdout," %d: %d\n",i,r->v.sval[i]); break; case ESPS_CHAR: fprintf(stdout," %d: %d\n",i,r->v.cval[i]); break; default: fprintf(stdout," %d: unknown\n",i); } } void add_field(esps_hdr hdr, const char *name, int type, int dimension) { /* Add a new field to the record */ char **names = hdr->field_name; short *types = hdr->field_type; int *dims = hdr->field_dimension; int i; hdr->field_name = walloc(char *,hdr->num_fields+1); hdr->field_type = walloc(short,hdr->num_fields+1); hdr->field_dimension = walloc(int,hdr->num_fields+1); for (i=0; i < hdr->num_fields; i++) { hdr->field_name[i] = names[i]; hdr->field_type[i] = types[i]; hdr->field_dimension[i] = dims[i]; } wfree(names); wfree(types); wfree(dims); hdr->field_name[hdr->num_fields] = wstrdup(name); hdr->field_type[hdr->num_fields] = type; hdr->field_dimension[hdr->num_fields] = dimension; hdr->num_fields++; return; } void add_fea_d(esps_hdr hdr,const char *name, int pos, double d) { /* Add a double FEA field to the header */ esps_fea t = new_esps_fea(); int i; t->type = 13; /* must be lucky for some !! */ t->clength = strlen(name); t->name = wstrdup(name); if (t->count < pos+1) { double *dval = t->v.dval; t->v.dval = walloc(double,pos+1); for (i=0; icount; i++) t->v.dval[i] = dval[i]; for (; i < pos+1; i++) t->v.dval[i] = 0.0; wfree(dval); t->count = pos+1; } t->dtype = ESPS_DOUBLE; t->v.dval[pos] = d; t->next = hdr->fea; hdr->fea = t; return; } void add_fea_f(esps_hdr hdr,const char *name, int pos, float d) { /* Add a float FEA field to the header */ esps_fea t = new_esps_fea(); int i; t->type = 13; t->clength = strlen(name); t->name = wstrdup(name); if (t->count < pos+1) { float *fval = t->v.fval; t->v.fval = walloc(float,pos+1); for (i=0; icount; i++) t->v.fval[i] = fval[i]; for (; i < pos+1; i++) t->v.fval[i] = 0.0; wfree(fval); t->count = pos+1; } t->dtype = ESPS_FLOAT; t->v.fval[pos] = d; t->next = hdr->fea; hdr->fea = t; return; } void add_fea_i(esps_hdr hdr,const char *name, int pos, int d) { /* Add an int FEA field to the header */ esps_fea t = new_esps_fea(); int i; t->type = 13; t->clength = strlen(name); t->name = wstrdup(name); if (t->count < pos+1) { int *ival = t->v.ival; t->v.ival = walloc(int,pos+1); for (i=0; icount; i++) t->v.ival[i] = ival[i]; for (; i < pos+1; i++) t->v.ival[i] = 0; wfree(ival); t->count = pos+1; } t->dtype = ESPS_INT; t->v.ival[pos] = d; t->next = hdr->fea; hdr->fea = t; return; } void add_fea_s(esps_hdr hdr,const char *name, int pos, short d) { /* Add a short FEA field to the header */ esps_fea t = new_esps_fea(); int i; t->type = 13; t->clength = strlen(name); t->name = wstrdup(name); if (t->count < pos+1) { short *sval = t->v.sval; t->v.sval = walloc(short,pos+1); for (i=0; icount; i++) t->v.sval[i] = sval[i]; for (; i < pos+1; i++) t->v.sval[i] = (short)0; wfree(sval); t->count = pos+1; } t->dtype = ESPS_SHORT; t->v.sval[pos] = d; t->next = hdr->fea; hdr->fea = t; return; } void add_fea_c(esps_hdr hdr,const char *name, int pos, char d) { /* Add a char FEA field to the header */ esps_fea t = new_esps_fea(); int i; t->type = 13; t->clength = strlen(name); t->name = wstrdup(name); if (t->count < pos+1) { char *cval = t->v.cval; t->v.cval = walloc(char,pos+1); for (i=0; icount; i++) t->v.cval[i] = cval[i]; for (; i < pos+1; i++) t->v.cval[i] = (char)0; wfree(cval); t->count = pos+1; } t->dtype = ESPS_CHAR; t->v.cval[pos] = d; t->next = hdr->fea; hdr->fea = t; return; } void add_fea_special(esps_hdr hdr,int type,const char *name) { /* Add a special FEA field to the header */ esps_fea t = new_esps_fea(); t->type = type; t->clength = strlen(name); t->name = wstrdup(name); t->count = 0; t->next = hdr->fea; hdr->fea = t; return; } int fea_value_d(const char *name,int pos,esps_hdr hdr, double *d) { /* Get value of double FEA */ esps_fea t; for (t=hdr->fea; t != NULL; t=t->next) if (streq(name,t->name)) { if (t->dtype != ESPS_DOUBLE) { fprintf(stderr,"ESPS hdr: access non-double field \"%s\" as double\n", name); return -1; } *d = t->v.dval[pos]; return 0; } return -1; /* failed to find it */ } int fea_value_f(const char *name,int pos,esps_hdr hdr, float *d) { /* Get value of float FEA */ esps_fea t; for (t=hdr->fea; t != NULL; t=t->next) if (streq(name,t->name)) { if (t->dtype != ESPS_FLOAT) { fprintf(stderr,"ESPS hdr: access non-float field \"%s\" as float\n", name); return -1; } *d = t->v.fval[pos]; return 0; } return -1; /* failed to find it */ } int fea_value_s(const char *name,int pos,esps_hdr hdr, short *d) { /* Get value of short FEA */ esps_fea t; for (t=hdr->fea; t != NULL; t=t->next) if (streq(name,t->name)) { if (t->dtype != ESPS_SHORT) { fprintf(stderr,"ESPS hdr: access non-short field \"%s\" as short\n", name); return -1; } *d = t->v.sval[pos]; return 0; } return -1; /* failed to find it */ } int fea_value_i(const char *name,int pos,esps_hdr hdr, int *d) { /* Get value of int FEA */ esps_fea t; for (t=hdr->fea; t != NULL; t=t->next) if (streq(name,t->name)) { if (t->dtype != ESPS_INT) { fprintf(stderr,"ESPS hdr: access non-int field \"%s\" as int\n", name); return -1; } *d = t->v.ival[pos]; return 0; } return -1; /* failed to find it */ } int fea_value_c(const char *name,int pos,esps_hdr hdr, char *d) { /* Get value of int FEA */ esps_fea t; for (t=hdr->fea; t != NULL; t=t->next) if (streq(name,t->name)) { if (t->dtype != ESPS_CHAR) { fprintf(stderr,"ESPS hdr: access non-char field \"%s\" as char\n", name); return -1; } *d = t->v.cval[pos]; return 0; } return -1; /* failed to find it */ } static int esps_alloc_fea(esps_fea r) { switch (r->dtype) { case 0: /* nothing */ break; case ESPS_DOUBLE: r->v.dval = walloc(double,r->count); break; case ESPS_FLOAT: r->v.fval = walloc(float,r->count); break; case ESPS_INT: r->v.ival = walloc(int,r->count); break; case ESPS_SHORT: r->v.sval = walloc(short,r->count); break; case ESPS_CHAR: r->v.cval = walloc(char,r->count); break; default: fprintf(stderr,"ESPS file: unsupported FEA dtype\n"); return -1; } return 0; } void write_esps_fea(FILE *fd, esps_fea t,esps_hdr hdr) { /* write out this fea */ (void)hdr; short clength; char *nspace; int i; fwrite(&t->type,2,1,fd); clength = (strlen(t->name)+3)/4; fwrite(&clength,2,1,fd); nspace = walloc(char, clength*4); memset(nspace,0,clength*4); memmove(nspace,t->name,strlen(t->name)); fwrite(nspace,1,clength*4,fd); wfree(nspace); if ((t->type == 11) || (t->type == 1) || (t->type == 15)) return; fwrite(&t->count,4,1,fd); fwrite(&t->dtype,2,1,fd); for (i=0; icount; i++) { switch(t->dtype) { case ESPS_DOUBLE: fwrite(&t->v.dval[i],8,1,fd); break; case ESPS_FLOAT: fwrite(&t->v.fval[i],4,1,fd); break; case ESPS_INT: fwrite(&t->v.ival[i],4,1,fd); break; case ESPS_SHORT: fwrite(&t->v.sval[i],2,1,fd); break; case ESPS_CHAR: fwrite(&t->v.cval[i],1,1,fd); break; default: fprintf(stderr,"ESPS write_hdr: unsupported FEA dtype %d\n", t->dtype); } } return; } int write_esps_rec(esps_rec r, esps_hdr h, FILE *fd) { /* will have to worry about swap someday */ (void)h; int i; for (i=0; i < r->num_fields; i++) { switch(r->field[i]->type) { case ESPS_DOUBLE: fwrite(r->field[i]->v.dval,8,r->field[i]->dimension,fd); break; case ESPS_FLOAT: fwrite(r->field[i]->v.fval,4,r->field[i]->dimension,fd); break; case ESPS_INT: fwrite(r->field[i]->v.ival,4,r->field[i]->dimension,fd); break; case ESPS_SHORT: fwrite(r->field[i]->v.sval,2,r->field[i]->dimension,fd); break; case ESPS_CHAR: fwrite(r->field[i]->v.cval,1,r->field[i]->dimension,fd); break; case ESPS_CODED: fwrite(r->field[i]->v.sval,2,r->field[i]->dimension,fd); break; default: fprintf(stderr,"ESPS file: unsupported field type %d\n", r->field[i]->type); } } return 0; } esps_fea read_esps_fea(FILE *fd, esps_hdr hdr) { /* read next FEA record at point */ esps_fea r = new_esps_fea(); short sdata; int i; int idata; float fdata; double ddata; char cdata; fread(&sdata,2,1,fd); if (hdr->swapped) sdata = SWAPSHORT(sdata); r->type = sdata; if (r->type == 0) /* a field name */ { /* next short is the size in bytes */ fread(&sdata,2,1,fd); if (hdr->swapped) sdata = SWAPSHORT(sdata); r->clength = sdata; } else if ((r->type == 13) || /* a feature and value */ (r->type == 11) || /* a single string (comment ?) */ (r->type == 1) || /* a filename */ (r->type == 4) || /* a filename */ (r->type == 15)) /* directory name */ { fread(&sdata,2,1,fd); if (hdr->swapped) sdata = SWAPSHORT(sdata); r->clength = sdata * 4; } else { fprintf(stderr,"ESPS: fea record unknown type\n"); wfree(r); return NULL; } r->name = walloc(char,r->clength+1); fread(r->name,1,r->clength,fd); r->name[r->clength] = '\0'; if ((r->type == 11) || /* a single string */ (r->type == 1) || /* a filename */ (r->type == 15)) /* directory name */ return r; fread(&idata,4,1,fd); if (hdr->swapped) idata = SWAPINT(idata); r->count = idata; fread(&sdata,2,1,fd); if (hdr->swapped) sdata = SWAPSHORT(sdata); r->dtype = sdata; if (esps_alloc_fea(r) == -1) return NULL; for (i=0; icount; i++) { switch (r->dtype) { case ESPS_DOUBLE: fread(&ddata,8,1,fd); if (hdr->swapped) swapdouble(&ddata); r->v.dval[i] = ddata; break; case ESPS_FLOAT: fread(&fdata,4,1,fd); if (hdr->swapped) swapfloat(&fdata); r->v.fval[i] = fdata; break; case ESPS_INT: fread(&idata,4,1,fd); if (hdr->swapped) idata = SWAPINT(idata); r->v.ival[i] = idata; break; case ESPS_SHORT: fread(&sdata,2,1,fd); if (hdr->swapped) sdata = SWAPSHORT(sdata); r->v.sval[i] = sdata; break; case ESPS_CHAR: fread(&cdata,1,1,fd); r->v.cval[i] = cdata; break; default: fprintf(stderr,"ESPS read_hdr: unsupported FEA dtype %d\n",r->dtype); wfree(r); return NULL; } } return r; } static char *esps_get_field_name(FILE *fd, esps_hdr hdr, int expect_source) { /* read the next field name */ short size=0; /* bet its really a short */ char *name; if (fread(&size,2,1,fd) != 1) { fputs("error reading field name size\n", stderr); return wstrdup("ERROR"); } if (hdr->swapped) size = SWAPSHORT(size); name = walloc(char,size+1); if (fread(name,1,size,fd) != (unsigned)size) { fputs("error reading field name\n", stderr); strncpy(name, "ERROR", size); } name[size] = '\0'; if (hdr->file_type == ESPS_SD || expect_source) fseek(fd,6,SEEK_CUR); /* skip some zeroes */ else fseek(fd,2,SEEK_CUR); if (expect_source) { fread(&size,2,1,fd); if (hdr->swapped) size = SWAPSHORT(size); fseek(fd,size,SEEK_CUR); } return name; } static void esps_put_field_name(char *name,FILE *fd, esps_hdr hdr) { /* write the next field name */ short size = strlen(name); short shortdata; shortdata = 0; fwrite(&shortdata,2,1,fd); fwrite(&size,2,1,fd); fwrite(name,1,size,fd); if (hdr->file_type == ESPS_SD) { shortdata = 0; fwrite(&shortdata,2,1,fd); fwrite(&shortdata,2,1,fd); fwrite(&shortdata,2,1,fd); } return; } esps_hdr new_esps_hdr(void) { esps_hdr h = walloc(struct ESPS_HDR_struct,1); h->file_type = ESPS_FEA; h->swapped = FALSE; h->num_records = 0; h->num_fields = 0; h->field_name = NULL; h->field_type = NULL; h->field_dimension = NULL; h->fea = NULL; return h; } void delete_esps_hdr(esps_hdr h) { int i; if (h != NULL) { if (h->field_name != NULL) { for (i=0; i < h->num_fields; i++) wfree(h->field_name[i]); wfree(h->field_name); } delete_esps_fea(h->fea); } } esps_rec new_esps_rec(esps_hdr hdr) { /* New esps record */ esps_rec r = walloc(struct ESPS_REC_struct,1); int i,size; r->field = walloc(esps_field,hdr->num_fields); for (size=0,i=0; i < hdr->num_fields; i++) { r->field[i]=walloc(struct ESPS_FIELD_struct,1); r->field[i]->type = hdr->field_type[i]; r->field[i]->dimension = hdr->field_dimension[i]; switch(r->field[i]->type) { case ESPS_DOUBLE: r->field[i]->v.dval = walloc(double,r->field[i]->dimension); size += 8; break; case ESPS_FLOAT: r->field[i]->v.fval = walloc(float,r->field[i]->dimension); size += 4; break; case ESPS_INT: r->field[i]->v.ival = walloc(int,r->field[i]->dimension); size += 4; break; case ESPS_SHORT: r->field[i]->v.sval = walloc(short,r->field[i]->dimension); size += 2; break; case ESPS_CHAR: r->field[i]->v.cval = walloc(char,r->field[i]->dimension); size += 1; break; case ESPS_CODED: r->field[i]->v.sval = walloc(short,r->field[i]->dimension); size += 2; break; default: fprintf(stderr,"ESPS file: unsupported field type %d\n", r->field[i]->type); } } r->num_fields = hdr->num_fields; r->size = size; return r; } void delete_esps_rec(esps_rec r) { int i; for (i=0; inum_fields; i++) { wfree(r->field[i]->v.ival); wfree(r->field[i]); } wfree(r->field); return; } int read_esps_rec(esps_rec r, esps_hdr hdr, FILE *fd) { /* read the next record at point */ int i,j; double doubledata; float floatdata; int intdata; short shortdata; for (i=0; i< r->num_fields; i++) { switch (r->field[i]->type) { case ESPS_DOUBLE: for(j=0; j < r->field[i]->dimension; j++) { if (fread(&doubledata,8,1,fd) == 0) return EOF; if (hdr->swapped) swapdouble(&doubledata); r->field[i]->v.dval[j] = doubledata; } break; case ESPS_FLOAT: for(j=0; j < r->field[i]->dimension; j++) { if (fread(&floatdata,4,1,fd) == 0) return EOF; if (hdr->swapped) swapfloat(&floatdata); r->field[i]->v.fval[j] = floatdata; } break; case ESPS_INT: for(j=0; j < r->field[i]->dimension; j++) { if (fread(&intdata,4,1,fd) == 0) return EOF; if (hdr->swapped) intdata = SWAPINT(intdata); r->field[i]->v.ival[j] = intdata; } break; case ESPS_SHORT: for(j=0; j < r->field[i]->dimension; j++) { if (fread(&shortdata,2,1,fd) == 0) return EOF; if (hdr->swapped) shortdata = SWAPSHORT(shortdata); r->field[i]->v.sval[j] = shortdata; } break; case ESPS_CHAR: if (fread(r->field[i]->v.cval,1,r->field[i]->dimension,fd) != (unsigned)r->field[i]->dimension) return EOF; break; case ESPS_CODED: for(j=0; j < r->field[i]->dimension; j++) { if (fread(&shortdata,2,1,fd) == 0) return EOF; if (hdr->swapped) shortdata = SWAPSHORT(shortdata); r->field[i]->v.sval[j] = shortdata; } break; default: fprintf(stderr,"ESPS file: unsupported field type %d\n", r->field[i]->type); return EOF; } } return 0; } double get_field_d(esps_rec r, int field, int pos) { return r->field[field]->v.dval[pos]; } float get_field_f(esps_rec r, int field, int pos) { return r->field[field]->v.fval[pos]; } int get_field_i(esps_rec r, int field, int pos) { return r->field[field]->v.ival[pos]; } short get_field_s(esps_rec r, int field, int pos) { return r->field[field]->v.sval[pos]; } char get_field_c(esps_rec r, int field, int pos) { return r->field[field]->v.cval[pos]; } void set_field_d(esps_rec r, int field, int pos, double d) { r->field[field]->v.dval[pos] = d; } void set_field_f(esps_rec r, int field, int pos, float d) { r->field[field]->v.fval[pos] = d; } void set_field_i(esps_rec r, int field, int pos, int d) { r->field[field]->v.ival[pos] = d; } void set_field_s(esps_rec r, int field, int pos, short d) { r->field[field]->v.sval[pos] = d; } void set_field_c(esps_rec r, int field, int pos, char d) { r->field[field]->v.cval[pos] = d; } int esps_record_size(esps_hdr hdr) { /* works out the number of bytes in a record */ esps_rec r = new_esps_rec(hdr); int size = r->size; delete_esps_rec(r); return size; } static int esps_num_of_type(int type,esps_hdr hdr) { /* counts up the number of occurrences of fields of type in a record */ int i; int sum; for (sum=i=0; i < hdr->num_fields; i++) if (hdr->field_type[i] == type) sum++; return sum; } esps_hdr make_esps_sd_hdr(void) { /* returns a basic header for an ESPS_SD file */ esps_hdr hdr = new_esps_hdr(); hdr->file_type = ESPS_SD; return hdr; } esps_hdr make_esps_hdr(void) { /* returns a basic header for an ESPS_SD file */ esps_hdr hdr = new_esps_hdr(); hdr->file_type = ESPS_FEA; return hdr; } enum EST_read_status read_esps_hdr(esps_hdr *uhdr,FILE *fd) { /* reads an ESPS header from fd at point (should be position 0) */ /* leaves point at start of data (immediately after header) */ struct ESPS_PREAMBLE preamble; struct ESPS_FIXED_HDR fhdr; esps_hdr hdr; int end,pos,intdata,i; short shortdata; double sd_sample_rate; int typematch; int swap; short name_flag; fread(&preamble,sizeof(preamble),1,fd); if (preamble.check == ESPS_MAGIC) swap = FALSE; else if (preamble.check == SWAPINT(ESPS_MAGIC)) swap = TRUE; else return wrong_format; hdr = new_esps_hdr(); hdr->swapped = swap; fread(&fhdr,sizeof(fhdr),1,fd); if (hdr->swapped) { preamble.data_offset = SWAPINT(preamble.data_offset); preamble.record_size = SWAPINT(preamble.record_size); fhdr.num_samples = SWAPINT(fhdr.num_samples); fhdr.num_doubles = SWAPINT(fhdr.num_doubles); fhdr.num_floats = SWAPINT(fhdr.num_floats); fhdr.num_ints = SWAPINT(fhdr.num_ints); fhdr.num_shorts = SWAPINT(fhdr.num_shorts); fhdr.num_chars = SWAPINT(fhdr.num_chars); fhdr.fea_type = SWAPSHORT(fhdr.fea_type); fhdr.num_fields = SWAPSHORT(fhdr.num_fields); } pos = ftell(fd); if (fhdr.num_samples == 0) /* has to be derived from the file size */ { pos = ftell(fd); fseek(fd,0,SEEK_END); end = ftell(fd); fseek(fd,pos,SEEK_SET); fhdr.num_samples = (end - preamble.data_offset)/preamble.record_size; } hdr->num_records = fhdr.num_samples; hdr->num_fields = fhdr.num_fields; hdr->hdr_size = preamble.data_offset; if (fhdr.thirteen == 9) { /* esps identifies such files are as Sample Data Files */ hdr->file_type = ESPS_SD; /* fake the rest to make it appear like other SD files */ hdr->num_fields = 1; hdr->field_dimension = walloc(int,hdr->num_fields); hdr->field_dimension[0] = 1; hdr->field_type = walloc(short,hdr->num_fields); hdr->field_type[0] = ESPS_SHORT; hdr->field_name = walloc(char *,1); hdr->field_name[0] = wstrdup("samples"); fseek(fd,hdr->hdr_size,SEEK_SET); /* In this cases its just in the header as a float */ sd_sample_rate = *((float *)&fhdr.fil4[0]); add_fea_d(hdr,"record_freq",0,(double)sd_sample_rate); *uhdr = hdr; return format_ok; } else if ((fhdr.fea_type == 8) && (hdr->num_fields == 1) && ((fhdr.num_shorts*2) == preamble.record_size)) hdr->file_type = ESPS_SD; /* this is a heuristic */ else hdr->file_type = ESPS_FEA; /* Now we have the field descriptions */ /* 0000 0001 dimensions */ hdr->field_dimension = walloc(int,hdr->num_fields); for (i=0; inum_fields; i++) { fread(&intdata,4,1,fd); /* dimensions */ if (hdr->swapped) intdata = SWAPINT(intdata); hdr->field_dimension[i] = intdata; } /* 0 -> num_fields-1 -- probably ordering information */ fseek(fd,hdr->num_fields*4,SEEK_CUR); /* ordering info */ fseek(fd,hdr->num_fields*2,SEEK_CUR); /* zeros */ hdr->field_type = walloc(short,hdr->num_fields); for (i=0; inum_fields; i++) { fread(&shortdata,2,1,fd); /* field types */ if (hdr->swapped) shortdata = SWAPSHORT(shortdata); hdr->field_type[i] = shortdata; } typematch = TRUE; fread(&intdata,4,1,fd); /* number of doubles */ if (hdr->swapped) intdata = SWAPINT(intdata); if (fhdr.num_doubles != intdata) typematch = FALSE; fread(&intdata,4,1,fd); /* number of floats */ if (hdr->swapped) intdata = SWAPINT(intdata); if (fhdr.num_floats != intdata) typematch = FALSE; fread(&intdata,4,1,fd); /* number of ints */ if (hdr->swapped) intdata = SWAPINT(intdata); if (fhdr.num_ints != intdata) typematch = FALSE; fread(&intdata,4,1,fd); /* number of shorts */ if (hdr->swapped) intdata = SWAPINT(intdata); if (fhdr.num_shorts != intdata) typematch = FALSE; fread(&intdata,4,1,fd); /* number of chars */ if (hdr->swapped) intdata = SWAPINT(intdata); if (fhdr.num_chars != intdata) typematch = FALSE; if ((hdr->file_type != ESPS_SD) && (typematch == FALSE)) { fprintf(stderr,"ESPS hdr: got lost in the header (record description)\n"); delete_esps_hdr(hdr); return misc_read_error; } /* other types ... */ fseek(fd,9*2,SEEK_CUR); /* other types */ fseek(fd,hdr->num_fields*2,SEEK_CUR); /* zeros */ /* Now we can read the field names */ hdr->field_name = walloc(char *,hdr->num_fields); fread(&name_flag, 2, 1, fd); if (hdr->swapped) name_flag = SWAPSHORT(name_flag); for (i=0; i < hdr->num_fields; i++) hdr->field_name[i] = esps_get_field_name(fd,hdr,name_flag); /* field names */ if (hdr->file_type == ESPS_SD) { /* Only one field 'samples' */ if (!streq(hdr->field_name[0],"samples")) { fprintf(stderr,"ESPS hdr: guessed wrong about FEA_SD file (no 'samples' field)\n"); delete_esps_hdr(hdr); return misc_read_error; } } /* Now fea, feature and value -- but how many are there ? */ while (ftell(fd) < preamble.data_offset-4) { esps_fea r = read_esps_fea(fd,hdr); /* feas */ if (r == NULL) break; /* print_esps_fea(r); */ r->next = hdr->fea; hdr->fea = r; if (r->type == 1) break; /* I think this (filename) is last FEA */ } /* There's other gunk after this but I think I've done enough */ /* The rest seems to be mostly previous headers */ fseek(fd,hdr->hdr_size,SEEK_SET); /* skip the rest of the header */ *uhdr = hdr; return format_ok; } enum EST_write_status write_esps_hdr(esps_hdr hdr,FILE *fd) { /* well here's the scary part, try to write a valid file hdr to */ /* the file */ struct ESPS_PREAMBLE preamble; struct ESPS_FIXED_HDR fhdr; time_t tx = time(0); esps_fea t; int i,intdata; short shortdata; memset(&preamble,0,sizeof(preamble)); memset(&fhdr,0,sizeof(fhdr)); /* I can't really make the machine code work properly, so I'll */ /* just fix it for the two major byte orders to Sun and Suni386 */ if (EST_NATIVE_BO == bo_big) preamble.machine_code = 4; /* a sun */ else preamble.machine_code = 6; /* a suni386 */ preamble.check_code = 3000; /* ? */ preamble.data_offset = 0; /* will come back and fix this later */ preamble.record_size = esps_record_size(hdr); preamble.check = ESPS_MAGIC; preamble.edr = 0; preamble.fil1 = 0; preamble.foreign_hd = 0; /* docs say it should be -1, but its always 0 */ fhdr.thirteen = 13; /* must be for luck */ fhdr.sdr_size = 0; fhdr.magic = ESPS_MAGIC; strncpy(fhdr.date,ctime(&tx),26); sprintf(fhdr.version,"1.91"); /* that's what all the others have */ sprintf(fhdr.prog,"EDST"); sprintf(fhdr.vers,"0.1"); strncpy(fhdr.progcompdate,ctime(&tx),26); fhdr.num_samples = hdr->num_records; fhdr.filler = 0; /* in each record */ fhdr.num_doubles = esps_num_of_type(ESPS_DOUBLE,hdr); fhdr.num_floats = esps_num_of_type(ESPS_FLOAT,hdr); fhdr.num_ints = esps_num_of_type(ESPS_INT,hdr); fhdr.num_shorts = esps_num_of_type(ESPS_SHORT,hdr); fhdr.num_chars = esps_num_of_type(ESPS_CHAR,hdr); fhdr.fsize = 40; fhdr.hsize = 0; /* given value below on second shot */ if (hdr->file_type == ESPS_SD) fhdr.fea_type = 8; else fhdr.fea_type = 0; fhdr.num_fields = hdr->num_fields; fwrite(&preamble,sizeof(preamble),1,fd); fwrite(&fhdr,sizeof(fhdr),1,fd); /* The following cover dimensions, type and ordering info */ for (i=0; i < hdr->num_fields; i++) { /* Dimensions (i.e. number of channels) */ intdata = 1; fwrite(&intdata,4,1,fd); /* dimensions */ } for (i=0; i < hdr->num_fields; i++) /* ordering info (?) */ fwrite(&i,4,1,fd); if (hdr->file_type == ESPS_SD) /* zeros hmm should be zeroes only */ shortdata = 1; /* is FEA case, 1 in ESPS_SD case */ else /* fixed 24/7/98 */ shortdata = 0; for (i=0; i < hdr->num_fields; i++) fwrite(&shortdata,2,1,fd); for (i=0; i < hdr->num_fields; i++) { shortdata = hdr->field_type[0]; /* field types */ fwrite(&shortdata,2,1,fd); } intdata = fhdr.num_doubles; /* number of doubles */ fwrite(&intdata,4,1,fd); intdata = fhdr.num_floats; /* number of floats */ fwrite(&intdata,4,1,fd); intdata = fhdr.num_ints; /* number of ints */ fwrite(&intdata,4,1,fd); intdata = fhdr.num_shorts; /* number of shorts */ fwrite(&intdata,4,1,fd); intdata = fhdr.num_chars; /* number of chars */ fwrite(&intdata,4,1,fd); shortdata = 0; for (i=0; i < 9; i++) fwrite(&shortdata,2,1,fd); /* other types */ for (i=0; i < hdr->num_fields; i++) fwrite(&shortdata,2,1,fd); /* zeros */ /* Now dump the filednames */ for (i=0; i < hdr->num_fields; i++) esps_put_field_name(hdr->field_name[i],fd,hdr); /* field names */ if (hdr->file_type != ESPS_SD) fwrite(&shortdata,2,1,fd); /* another 0 */ /* Now the feas */ for (t=hdr->fea; t != NULL; t=t->next) write_esps_fea(fd,t,hdr); /* feas */ /* now have to go back and fix the header size */ intdata = 0; fwrite(&intdata,4,1,fd); preamble.data_offset = ftell(fd); fhdr.hsize = (preamble.data_offset-249)/2; if (fseek(fd,0,SEEK_SET) == -1) { fprintf(stderr,"esps write header: can't fseek to start of file\n"); return misc_write_error; } fwrite(&preamble,sizeof(preamble),1,fd); fwrite(&fhdr,sizeof(fhdr),1,fd); fseek(fd,preamble.data_offset,SEEK_SET); return write_ok; }