Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
esps_utils.cc
1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1994,1995,1996 */
6 /* All Rights Reserved. */
7 /* */
8 /* Permission is hereby granted, free of charge, to use and distribute */
9 /* this software and its documentation without restriction, including */
10 /* without limitation the rights to use, copy, modify, merge, publish, */
11 /* distribute, sublicense, and/or sell copies of this work, and to */
12 /* permit persons to whom this work is furnished to do so, subject to */
13 /* the following conditions: */
14 /* 1. The code must retain the above copyright notice, this list of */
15 /* conditions and the following disclaimer. */
16 /* 2. Any modifications must be clearly marked as such. */
17 /* 3. Original authors' names are not deleted. */
18 /* 4. The authors' names are not used to endorse or promote products */
19 /* derived from this software without specific prior written */
20 /* permission. */
21 /* */
22 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30 /* THIS SOFTWARE. */
31 /* */
32 /*************************************************************************/
33 /* 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 *)&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 }