Edinburgh Speech Tools  2.1-release
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EST_wave_io.cc
1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 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 Black and Paul Taylor */
34 /* Date : June 1996 */
35 /*-----------------------------------------------------------------------*/
36 /* File I/O functions specific to various file formats */
37 /* */
38 /* Note that internally data will always be shorts and */
39 /* native byte order, conversions to/from other byte formats */
40 /* or encodings happend at read/write time */
41 /* */
42 /*=======================================================================*/
43 #include <cstdlib>
44 #include <cstdio>
45 #include "EST_unix.h"
46 #include <cstring>
47 #include "EST_wave_aux.h"
48 #include "EST_wave_utils.h"
49 #include "EST_strcasecmp.h"
50 #include "waveP.h"
51 #include "EST_FileType.h"
52 
53 static int def_load_sample_rate = 16000;
54 
55 /*************************************************************************/
56 /* */
57 /* Functions specific for each file format */
58 /* */
59 /*************************************************************************/
60 
61 /*=======================================================================*/
62 /* Sphere Nist files */
63 /*=======================================================================*/
64 
65 static const char *NIST_SIG = "NIST_1A\n 1024\n";
66 static const char *NIST_END_SIG = "end_head\n";
67 #define NIST_HDR_SIZE 1024
68 
69 int nist_get_param_int(const char *hdr, const char *field, int def_val)
70 {
71  const char *p;
72  int val;
73 
74  if (((p=strstr(hdr,field)) != NULL) &&
75  (strncmp(" -i ",p+strlen(field),4) == 0))
76  {
77  sscanf(p+strlen(field)+4,"%d",&val);
78  return val;
79  }
80  else
81  return def_val;
82 
83 }
84 
85 char *nist_get_param_str(const char *hdr, const char *field, const char *def_val)
86 {
87  const char *p;
88  char *val;
89  int size;
90 
91  if (((p=strstr(hdr,field)) != NULL) &&
92  (strncmp(" -s",p+strlen(field),3) == 0))
93  {
94  sscanf(p+strlen(field)+3,"%d",&size);
95  val = walloc(char,size+1);
96  /* Hmm don't know how long the %d is so do it again */
97  sscanf(p+strlen(field)+3,"%d %s",&size,val);
98  return val;
99  }
100  else
101  return wstrdup(def_val);
102 
103 
104 }
105 
106 const char *sample_type_to_nist(enum EST_sample_type_t sample_type)
107 {
108  const char *c;
109  switch (sample_type) {
110  case st_unknown:
111  c = ""; break;
112  case st_schar:
113  c = "PCM-1"; break;
114  case st_alaw:
115  c = "ALAW"; break;
116  case st_mulaw:
117  c = "ULAW"; break;
118  case st_short:
119  c = "pcm"; break;
120  case st_int:
121  c = "PCM-4"; break;
122  case st_float:
123  c = "REAL"; break;
124  case st_double:
125  c = "REAL"; break;
126  default:
127  fprintf(stderr,"Unknown sample type for nist");
128  c = "";
129  }
130  return c;
131 }
132 
133 enum EST_sample_type_t nist_to_sample_type(char *type)
134 {
135  if ((streq(type,"pcm")) ||
136  (streq(type,"PCM")) ||
137  (streq(type,"pcm-2")))
138  return st_short;
139  if (strcmp(type,"pcm,embedded-shorten-v1.1") == 0)
140  return st_shorten;
141  else if ((EST_strcasecmp(type,"ULAW",NULL) == 0) ||
142  (EST_strcasecmp(type,"U-LAW",NULL) == 0) ||
143  (EST_strcasecmp(type,"mu-law",NULL) == 0) ||
144  (EST_strcasecmp(type,"mulaw",NULL) == 0))
145  return st_mulaw;
146  else if ((EST_strcasecmp(type,"ALAW",NULL) == 0) ||
147  (EST_strcasecmp(type,"A-LAW",NULL) == 0))
148  return st_alaw;
149  else if (strcmp(type,"alaw") == 0)
150  return st_alaw;
151  else if (strcmp(type,"PCM-1") == 0)
152  return st_schar;
153  else if (strcmp(type,"PCM-4") == 0)
154  return st_int;
155  else if (strcmp(type,"REAL") == 0)
156  return st_float;
157  else
158 
159  {
160  fprintf(stderr,"NIST: unknown sample type: %s\n",type);
161  return st_unknown;
162  }
163 }
164 
165 enum EST_read_status load_wave_nist(EST_TokenStream &ts, short **data, int
166  *num_samples, int *num_channels, int
167  *word_size, int *sample_rate, enum
168  EST_sample_type_t *sample_type, int *bo , int
169  offset, int length)
170 
171 {
172  char header[NIST_HDR_SIZE];
173  int samps,sample_width,data_length,actual_bo;
174  unsigned char *file_data;
175  enum EST_sample_type_t actual_sample_type;
176  char *byte_order, *sample_coding;
177  int n;
178  int current_pos;
179 
180  current_pos = ts.tell();
181  if (ts.fread(header,NIST_HDR_SIZE,1) != 1)
182  return wrong_format;
183 
184  if (strncmp(header,NIST_SIG,sizeof(NIST_SIG)) != 0)
185  return wrong_format;
186 
187  samps = nist_get_param_int(header,"sample_count",-1);
188  *num_channels = nist_get_param_int(header,"channel_count",1);
189  sample_width = nist_get_param_int(header,"sample_n_bytes",2);
190  *sample_rate =
191  nist_get_param_int(header,"sample_rate",def_load_sample_rate);
192  byte_order = nist_get_param_str(header,"sample_byte_format",
193  (EST_BIG_ENDIAN ? "10" : "01"));
194  sample_coding = nist_get_param_str(header,"sample_coding","pcm");
195  if (streq(byte_order,"mu-law"))
196  {
197  byte_order = wstrdup((EST_BIG_ENDIAN ? "10" : "01"));
198  sample_coding = wstrdup("ULAW");
199  }
200  if (streq(byte_order,"a-law"))
201  {
202  byte_order = wstrdup((EST_BIG_ENDIAN ? "10" : "01"));
203  sample_coding = wstrdup("ALAW");
204  }
205 
206  /* code for reading in Tony Robinson's shorten files.
207  This is a temporary fix which calls the unshorten program on the
208  speech file and reads in the answer by calling this function.
209  It would be nice to have a simple library routine which did the
210  unshortening.
211  */
212 
213  if (streq(sample_coding,"pcm,embedded-shorten-v1.1"))
214  {
215  char *tmpfile, *cmdstr;
216  enum EST_read_status rval;
217 
218  tmpfile = cmake_tmp_filename();
219  cmdstr = walloc(char,strlen(tmpfile)+200);
220  sprintf(cmdstr,"cstrshorten %s %s",
221  (const char*)ts.filename(),tmpfile);
222  printf("Command: %s\n", cmdstr);
223  system(cmdstr);
224  EST_TokenStream tt;
225  tt.open(tmpfile);
226 
227  rval = load_wave_nist(tt, data, num_samples,
228  num_channels, word_size, sample_rate,
229  sample_type, bo, offset, length);
230  unlink(tmpfile);
231  wfree(tmpfile);
232  wfree(cmdstr);
233  tt.close();
234  return rval;
235  }
236 
237  if (length == 0)
238  data_length = (samps - offset)*(*num_channels);
239  else
240  data_length = length*(*num_channels);
241 
242  file_data = walloc(unsigned char,sample_width * data_length);
243 
244  ts.seek(current_pos+NIST_HDR_SIZE+(sample_width*offset*(*num_channels)));
245 
246  n = ts.fread(file_data,sample_width,data_length);
247 
248  if ((n < 1) && (n != data_length))
249  {
250  wfree(file_data);
251  wfree(sample_coding);
252  wfree(byte_order);
253  return misc_read_error;
254  }
255  else if ((n < data_length) && (data_length/(*num_channels) == n))
256  {
257  fprintf(stderr,"WAVE read: nist header is (probably) non-standard\n");
258  fprintf(stderr,"WAVE read: assuming different num_channel interpretation\n");
259  data_length = n; /* wrongly headered file */
260  }
261  else if (n < data_length)
262  {
263  fprintf(stderr,"WAVE read: short file %s\n",
264  (const char *)ts.filename());
265  fprintf(stderr,"WAVE read: at %d got %d instead of %d samples\n",
266  offset,n,data_length);
267  data_length = n;
268  }
269 
270  actual_sample_type = nist_to_sample_type(sample_coding);
271  actual_bo = ((strcmp(byte_order,"10") == 0) ? bo_big : bo_little);
272 
273  *data = convert_raw_data(file_data,data_length,
274  actual_sample_type,actual_bo);
275 
276  *num_samples = data_length/ (*num_channels);
277  *sample_type = st_short;
278  *bo = EST_NATIVE_BO;
279  *word_size = 2;
280  wfree(sample_coding);
281  wfree(byte_order);
282 
283  return format_ok;
284 }
285 
286 enum EST_write_status save_wave_nist_header(FILE *fp,
287  int num_samples, int num_channels,
288  int sample_rate,
289  enum EST_sample_type_t sample_type, int bo)
290 {
291  char h[1024], p[1024];
292  const char *t;
293 
294  memset(h,0,1024);
295 
296  strcat(h, NIST_SIG);
297  sprintf(p, "channel_count -i %d\n", num_channels);
298  strcat(h, p);
299  sprintf(p, "sample_count -i %d\n", num_samples);
300  strcat(h, p);
301  sprintf(p, "sample_rate -i %d\n", sample_rate);
302  strcat(h, p);
303 
304  t = sample_type_to_nist(sample_type);
305  if (t)
306  {
307  sprintf(p, "sample_coding -s%d %s\n", (signed)strlen(t), t);
308  strcat(h, p);
309  sprintf(p, "sample_n_bytes -i %d\n", get_word_size(sample_type));
310  strcat(h, p);
311  }
312 
313  if (get_word_size(sample_type) > 1)
314  {
315  sprintf(p, "sample_byte_format -s%d %s\n", 2,
316  ((bo == bo_big) ? "10" : "01"));
317  strcat(h, p);
318  }
319 
320  strcat(h, NIST_END_SIG);
321  /*makes it nice to read */
322  strcat(h, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
323 
324  if (fwrite(&h, 1024, 1, fp) != 1)
325  return misc_write_error;
326 
327  return write_ok;
328 }
329 
330 
331 enum EST_write_status save_wave_nist_data(FILE *fp, const short *data, int offset,
332  int num_samples, int num_channels,
333  int sample_rate,
334  enum EST_sample_type_t sample_type, int bo)
335 {
336  if (data == NULL)
337  return write_ok;
338 
339  return save_raw_data(fp,data,offset,num_samples,num_channels,
340  sample_type,bo);
341 
342 }
343 
344 enum EST_write_status save_wave_nist(FILE *fp, const short *data, int offset,
345  int num_samples, int num_channels,
346  int sample_rate,
347  enum EST_sample_type_t sample_type, int bo)
348 {
349  save_wave_nist_header(fp, num_samples, num_channels,
350  sample_rate, sample_type, bo);
351  return save_wave_nist_data(fp, data, offset,
352  num_samples, num_channels,
353  sample_rate, sample_type, bo);
354 }
355 
356 /*=======================================================================*/
357 /* EST's own format */
358 /*=======================================================================*/
359 
360 enum EST_read_status load_wave_est(EST_TokenStream &ts, short **data, int
361  *num_samples, int *num_channels, int
362  *word_size, int *sample_rate, enum
363  EST_sample_type_t *sample_type, int *bo,
364  int offset, int length)
365 {
366  int data_length, actual_bo;
367  short *file_data;
368  EST_String byte_order;
369  int n;
370  EST_EstFileType t;
371  EST_Option hinfo;
372  bool ascii;
373  EST_read_status r;
374  EST_sample_type_t actual_sample_type;
375 
376  offset = 0;
377 
378  if ((r = read_est_header(ts, hinfo, ascii, t)) != format_ok)
379  return r;
380  if (t != est_file_wave)
381  return misc_read_error;
382 
383  *num_samples = hinfo.ival("NumSamples");
384  *num_channels = hinfo.ival("NumChannels");
385  *sample_rate = hinfo.ival("SampleRate");
386 
387  byte_order = hinfo.val("ByteOrder");
388 
389  if (length == 0)
390  data_length = (*num_samples)*(*num_channels);
391  else
392  data_length = length*(*num_channels);
393 
394  file_data = walloc(short, data_length);
395 
396  n = ts.fread(file_data, sizeof(short), data_length);
397  if ((n != data_length) && (n < 1))
398  {
399  cerr << "EST wave load: " << ts.pos_description() << endl;
400  cerr << "failed to read file\n";
401  wfree(file_data);
402  return misc_read_error;
403  }
404  else if (n != data_length)
405  {
406  cerr << "Wrong number of samples/channels in EST wave file\n";
407  cerr << ts.pos_description() << " ";
408  cerr << "expected " << data_length << " got " << n << endl;
409  data_length = n;
410  }
411 
412  actual_bo = (byte_order == "10") ? bo_big : bo_little;
413  if (hinfo.present("SampleType"))
414  actual_sample_type = str_to_sample_type(hinfo.val("SampleType"));
415  else
416  actual_sample_type = st_short; // some older files don't have this
417 
418  *data = convert_raw_data((unsigned char *)file_data,
419  data_length, actual_sample_type, actual_bo);
420  // because internally data is always shorts
421  *sample_type = st_short;
422  *bo = EST_NATIVE_BO;
423  *word_size = 2;
424 
425  return format_ok;
426 }
427 
428 enum EST_write_status save_wave_est_header(FILE *fp,
429  int num_samples, int num_channels,
430  int sample_rate,
431  enum EST_sample_type_t sample_type, int bo)
432 {
433  fprintf(fp, "EST_File wave\n");
434  fprintf(fp, "DataType binary\n");
435  fprintf(fp, "SampleRate %d\n", sample_rate);
436  fprintf(fp, "NumSamples %d\n", num_samples);
437  fprintf(fp, "NumChannels %d\n", num_channels);
438  fprintf(fp, "SampleType %s\n", sample_type_to_str(sample_type));
439  if (get_word_size(sample_type) > 1)
440  fprintf(fp, "ByteOrder %s\n", ((bo == bo_big) ? "10" : "01"));
441 
442  fprintf(fp, "EST_Header_End\n");
443  return write_ok;
444 }
445 
446 enum EST_write_status save_wave_est_data(FILE *fp, const short *data, int offset,
447  int num_samples, int num_channels,
448  int sample_rate,
449  enum EST_sample_type_t sample_type, int bo)
450 {
451  if (data == NULL)
452  return write_ok;
453 
454  return save_raw_data(fp, data, offset, num_samples, num_channels,
455  sample_type, bo);
456 }
457 
458 enum EST_write_status save_wave_est(FILE *fp, const short *data, int offset,
459  int num_samples, int num_channels,
460  int sample_rate,
461  enum EST_sample_type_t sample_type, int bo)
462 {
463  save_wave_est_header(fp, num_samples, num_channels,
464  sample_rate, sample_type, bo);
465 
466  return save_wave_est_data(fp, data, offset,
467  num_samples, num_channels,
468  sample_rate, sample_type, bo);
469 }
470 
471 /*=======================================================================*/
472 /* Microsoft RIFF (.wav) audio files */
473 /* */
474 /* The information on this format was gained by reading a document */
475 /* found on the net called "Multimedia Programming Interface and */
476 /* Data Specification v1.0" and by looking at Rick Richardson, */
477 /* Lance Norskog And Sundry Contributors code in SOX. All this code */
478 /* is rewritten from scratch though, but I couldn't do it without */
479 /* other's explanations. I would have used the SOX code directly but */
480 /* was not really in the right form so starting again was easier */
481 /*=======================================================================*/
482 #define WAVE_FORMAT_PCM 0x0001
483 #define WAVE_FORMAT_ADPCM 0x0002
484 #define WAVE_FORMAT_ALAW 0x0006
485 #define WAVE_FORMAT_MULAW 0x0007
486 
487 enum EST_read_status load_wave_riff(EST_TokenStream &ts, short **data, int
488  *num_samples, int *num_channels, int
489  *word_size, int *sample_rate, enum
490  EST_sample_type_t *sample_type, int *bo , int
491  offset, int length)
492 {
493  char info[4];
494  int samps,sample_width,data_length;
495  short shortdata;
496  int dsize,intdata;
497  unsigned char *file_data;
498  enum EST_sample_type_t actual_sample_type;
499 
500  if (ts.fread(info,sizeof(char),4) != 4)
501  return wrong_format; /* its almost definitely an error */
502  if (strncmp(info,"RIFF",4) != 0)
503  return wrong_format;
504 
505  /* We've got a riff file */
506  /* Next 4 bytes are the file size */
507  if(ts.fread(&dsize,4,1) != 1) return misc_read_error;
508  /* .wav files are always little endian */
509  if (EST_BIG_ENDIAN) dsize = SWAPINT(dsize);
510  if ((ts.fread(info,sizeof(char),4) != 4) ||
511  (strncmp(info,"WAVE",4) != 0))
512  {
513  fprintf(stderr, "RIFF file is not of type WAVE\n");
514  return misc_read_error; /* not a wave file */
515  }
516  if ((ts.fread(info,sizeof(char),4) != 4) ||
517  (strncmp(info,"fmt ",4) != 0))
518  return misc_read_error; /* something else wrong */
519 
520  if (ts.fread(&dsize,4,1) != 1) return misc_read_error;
521  if (EST_BIG_ENDIAN) dsize = SWAPINT(dsize);
522  if (ts.fread(&shortdata,2,1) != 1) return misc_read_error;
523  if (EST_BIG_ENDIAN) shortdata = SWAPSHORT(shortdata);
524 
525  switch (shortdata)
526  {
527  /* This is a non-proprietary format */
528  case WAVE_FORMAT_PCM:
529  actual_sample_type = st_short; break;
530  /* The follow are registered proprietary WAVE formats (?) */
531  case WAVE_FORMAT_MULAW:
532  actual_sample_type = st_mulaw; break;
533  case WAVE_FORMAT_ALAW:
534  actual_sample_type = st_alaw; break;
535  case WAVE_FORMAT_ADPCM:
536  fprintf(stderr, "RIFF file: unsupported proprietary sample format ADPCM\n");
537  actual_sample_type = st_short;
538  break;
539  /* actual_sample_type = st_adpcm; break; */ /* yes but which adpcm ! */
540  default:
541  fprintf(stderr, "RIFF file: unknown sample format\n");
542  actual_sample_type = st_short;
543  /* return misc_read_error; */
544  }
545  if (ts.fread(&shortdata,2,1) != 1) return misc_read_error;
546  if (EST_BIG_ENDIAN) shortdata = SWAPSHORT(shortdata);
547  *num_channels = shortdata;
548  if (ts.fread(sample_rate,4,1) != 1) return misc_read_error;
549  if (EST_BIG_ENDIAN) *sample_rate = SWAPINT(*sample_rate);
550  if (ts.fread(&intdata,4,1) != 1) return misc_read_error; /* average bytes per second -- ignored */
551  if (EST_BIG_ENDIAN) intdata = SWAPINT(intdata);
552  if (ts.fread(&shortdata,2,1) != 1) return misc_read_error; /* block align ? */
553  if (EST_BIG_ENDIAN) shortdata = SWAPSHORT(shortdata);
554  if (ts.fread(&shortdata,2,1) != 1) return misc_read_error;
555  if (EST_BIG_ENDIAN) shortdata = SWAPSHORT(shortdata);
556 
557  sample_width = (shortdata+7)/8;
558  if ((sample_width == 1) && (actual_sample_type == st_short))
559  actual_sample_type = st_uchar; /* oops I meant 8 bit */
560 
561  ts.seek((dsize-16)+ts.tell()); /* skip rest of header */
562  while (1)
563  {
564  if (ts.fread(info,sizeof(char),4) != 4)
565  {
566  fprintf(stderr,"RIFF file truncated\n");
567  return misc_read_error; /* something else wrong */
568  }
569  if (strncmp(info,"data",4) == 0)
570  {
571  if (ts.fread(&samps,4,1) != 1) return misc_read_error;
572  if (EST_BIG_ENDIAN) samps = SWAPINT(samps);
573  samps /= (sample_width*(*num_channels));
574  break;
575  }
576  else if (strncmp(info,"fact",4) == 0)
577  { /* some other type of chunk -- skip it */
578  if (ts.fread(&samps,4,1) != 1) return misc_read_error;
579  if (EST_BIG_ENDIAN) samps = SWAPINT(samps);
580  ts.seek(samps+ts.tell()); /* skip rest of header */
581  /* Hope this is the right amount */
582  }
583  else
584  {
585  // fprintf(stderr,"Ignoring unsupported chunk type \"%c%c%c%c\" in RIFF file\n",
586  // info[0],info[1],info[2],info[3]);
587  //return misc_read_error;
588  if(ts.fread(&dsize,4,1) != 1) return misc_read_error;
589  if (EST_BIG_ENDIAN) dsize = SWAPINT(dsize);
590  ts.seek(dsize+ts.tell()); /* skip this chunk */
591  }
592  }
593  if (length == 0)
594  data_length = (samps - offset)*(*num_channels);
595  else
596  data_length = length*(*num_channels);
597 
598  file_data = walloc(unsigned char,sample_width * data_length);
599 
600  ts.seek((sample_width*offset*(*num_channels))+ts.tell());
601  if ((dsize=ts.fread(file_data,sample_width,data_length)) != data_length)
602  {
603  /* It seems so many WAV files have their datasize wrong I'll */
604  /* let it through -- I think SOX is a major culprit */
605  if (length == 0) /* the file did the identification */
606  fprintf(stderr,"Unexpected end of file but continuing (apparently missing %d samples)\n",data_length-dsize);
607  else
608  {
609  fprintf(stderr,"Unexpected end of file: (missing %d samples)\n",data_length-dsize);
610  wfree(file_data);
611  return misc_read_error;
612  }
613  }
614 
615  *data = convert_raw_data(file_data,dsize,
616  actual_sample_type, bo_little);
617 
618  *num_samples = dsize / (*num_channels);
619  *sample_type = st_short;
620  *bo = EST_NATIVE_BO;
621  *word_size = 2;
622 
623  return format_ok;
624 }
625 
626 enum EST_write_status save_wave_riff_header(FILE *fp, int num_samples,
627  int num_channels, int sample_rate,
628  enum EST_sample_type_t sample_type, int bo)
629 {
630  (void)bo;
631  const char *info;
632  int data_size, data_int;
633  short data_short;
634 
635  if (sample_type == st_schar)
636  {
637  EST_warning("RIFF format: Signed 8-bit not allowed by this file format");
638  sample_type=st_uchar;
639  }
640 
641  info = "RIFF"; fwrite(info,4,1,fp);
642  data_size = num_channels*num_samples*get_word_size(sample_type)+ 8+16+12;
643  /* WAV files are always LITTLE_ENDIAN (i.e. intel x86 format) */
644  if (EST_BIG_ENDIAN) data_size = SWAPINT(data_size);
645  fwrite(&data_size,1,4,fp); /* total number of bytes in file */
646  info = "WAVE"; fwrite(info,4,1,fp);
647  info = "fmt "; fwrite(info,4,1,fp);
648  data_size = 16;
649  if (EST_BIG_ENDIAN) data_size = SWAPINT(data_size);
650  fwrite(&data_size,1,4,fp); /* size of header */
651  switch (sample_type)
652  {
653  case st_short: data_short = WAVE_FORMAT_PCM; break;
654  case st_uchar: data_short = WAVE_FORMAT_PCM; break;
655  case st_mulaw: data_short = WAVE_FORMAT_MULAW; break;
656  case st_alaw: data_short = WAVE_FORMAT_ALAW; break;
657  case st_adpcm: data_short = WAVE_FORMAT_ADPCM; break;
658  default:
659  fprintf(stderr,"RIFF format: unsupported data format %d\n",
660  sample_type);
661  return misc_write_error;
662  }
663  if (EST_BIG_ENDIAN) data_short = SWAPSHORT(data_short);
664  fwrite(&data_short,1,2,fp); /* sample type */
665  data_short = num_channels;
666  if (EST_BIG_ENDIAN) data_short = SWAPSHORT(data_short);
667  fwrite(&data_short,1,2,fp); /* number of channels */
668  data_int = sample_rate;
669  if (EST_BIG_ENDIAN) data_int = SWAPINT(data_int);
670  fwrite(&data_int,1,4,fp); /* sample rate */
671  data_int = sample_rate * num_channels * get_word_size(sample_type);
672  if (EST_BIG_ENDIAN) data_int = SWAPINT(data_int);
673  fwrite(&data_int,1,4,fp); /* Average bytes per second */
674  data_short = num_channels * get_word_size(sample_type);
675  if (EST_BIG_ENDIAN) data_short = SWAPSHORT(data_short);
676  fwrite(&data_short,1,2,fp); /* block align */
677  data_short = get_word_size(sample_type) * 8;
678  if (EST_BIG_ENDIAN) data_short = SWAPSHORT(data_short);
679  fwrite(&data_short,1,2,fp); /* bits per sample */
680  info = "data"; fwrite(info,4,1,fp);
681  data_size = num_channels*num_samples*get_word_size(sample_type);
682  if (EST_BIG_ENDIAN) data_size = SWAPINT(data_size);
683  fwrite(&data_size,1,4,fp); /* total number of bytes in data */
684 
685  return write_ok;
686 }
687 
688 enum EST_write_status save_wave_riff_data(FILE *fp, const short *data,
689  int offset, int num_samples, int num_channels,
690  int sample_rate,
691  enum EST_sample_type_t sample_type, int bo)
692 {
693  if (data == NULL)
694  return write_ok;
695 
696  return save_raw_data(fp,data,offset,num_samples,num_channels,
697  sample_type,bo_little);
698 }
699 
700 
701 enum EST_write_status save_wave_riff(FILE *fp, const short *data, int offset,
702  int num_samples, int num_channels,
703  int sample_rate,
704  enum EST_sample_type_t sample_type, int bo)
705 {
706  save_wave_riff_header(fp, num_samples, num_channels, sample_rate,
707  sample_type, bo);
708 
709  return save_wave_riff_data(fp, data, offset, num_samples,
710  num_channels, sample_rate, sample_type, bo);
711 
712 }
713 
714 /*=======================================================================*/
715 /* Amiga/Apple AIFF waveform format */
716 /* This was constructed using info in AudioIFF1.3.hqx found on the web */
717 /* and also I did look at SOX's aiff.c written by Guido van Rossum */
718 /* and Sundry Contributors. */
719 /*=======================================================================*/
720 
721 struct AIFFchunk {
722  char id[4];
723  int size;
724 };
725 
726 struct AIFFssnd { /* Sound Data Chunk */
727  int offset;
728  int blocksize;
729 };
730 
731 enum EST_read_status load_wave_aiff(EST_TokenStream &ts, short **data, int
732  *num_samples, int *num_channels, int
733  *word_size, int *sample_rate, enum
734  EST_sample_type_t *sample_type, int *bo , int
735  offset, int length)
736 {
737  char info[4];
738  struct AIFFchunk chunk;
739  short comm_channels;
740  int comm_samples;
741  short comm_bits;
742  unsigned char ieee_ext_sample_rate[10];
743  struct AIFFssnd ssndchunk;
744  enum EST_sample_type_t actual_sample_type;
745  int dsize,data_length,n;
746  unsigned char *file_data;
747 
748  if (ts.fread(info,sizeof(char),4) != 4)
749  return wrong_format; /* but its almost definitely an error */
750  if (strncmp(info,"FORM",4) != 0)
751  return wrong_format;
752 
753  /* We've got an aiff file, I hope */
754  if (ts.fread(&dsize,4,1) != 1) return misc_read_error;
755  if (EST_LITTLE_ENDIAN) /* file is in different byte order */
756  dsize = SWAPINT(dsize);
757  if ((ts.fread(info,sizeof(char),4) != 4) ||
758  (strncmp(info,"AIFF",4) != 0))
759  {
760  fprintf(stderr, "AIFF file does not have AIFF chunk\n");
761  return misc_read_error;
762  }
763 
764  for ( ; ts.fread(&chunk, sizeof(chunk), 1) == 1 ; )
765  { /* for each chunk in the file */
766  if (EST_LITTLE_ENDIAN) /* file is in different byte order */
767  chunk.size = SWAPINT(chunk.size);
768  if (strncmp(chunk.id,"COMM",4) == 0)
769  {
770  if (chunk.size != 18)
771  {
772  fprintf(stderr,"AIFF chunk: bad size\n");
773  return misc_read_error;
774  }
775  if (ts.fread(&comm_channels, sizeof(short), 1) != 1)
776  return misc_read_error;
777  if (ts.fread(&comm_samples, sizeof(int), 1) != 1)
778  return misc_read_error;
779  if (ts.fread(&comm_bits, sizeof(short), 1) != 1)
780  return misc_read_error;
781  if (ts.fread(ieee_ext_sample_rate, 10, 1) != 1)
782  {
783  fprintf(stderr,"AIFF chunk: eof within COMM chunk\n");
784  return misc_read_error;
785  }
786  if (EST_LITTLE_ENDIAN)
787  {
788  comm_channels = SWAPSHORT(comm_channels);
789  comm_samples = SWAPINT(comm_samples);
790  comm_bits = SWAPSHORT(comm_bits);
791  }
792  *sample_rate = (int)ConvertFromIeeeExtended(ieee_ext_sample_rate);
793  }
794  else if (strncmp(chunk.id,"SSND",4) == 0)
795  {
796  if (ts.fread(&ssndchunk, sizeof(ssndchunk), 1) != 1)
797  {
798  fprintf(stderr,"AIFF chunk: eof within SSND chunk\n");
799  return misc_read_error;
800  }
801  if (EST_LITTLE_ENDIAN)
802  {
803  ssndchunk.offset = SWAPINT(ssndchunk.offset);
804  ssndchunk.blocksize = SWAPINT(ssndchunk.blocksize);
805  }
806 
807  *num_channels = comm_channels;
808  switch (comm_bits)
809  {
810  case 8: actual_sample_type = st_uchar; break;
811  case 16: actual_sample_type = st_short; break;
812  default:
813  fprintf(stderr,"AIFF: unsupported sample width %d bits\n",
814  comm_bits);
815  return misc_read_error;
816  }
817 
818  ts.seek(ssndchunk.offset+(comm_channels*offset)+ts.tell());
819  if (length == 0)
820  data_length = (comm_samples-offset)*comm_channels;
821  else
822  data_length = length*comm_channels;
823  file_data = walloc(unsigned char,
824  data_length*comm_channels*
825  get_word_size(actual_sample_type));
826  if ((n=ts.fread(file_data,get_word_size(actual_sample_type),
827  data_length)) != data_length)
828  {
829  fprintf(stderr,"AIFF read: short file %s\n",
830  (const char *)ts.filename());
831  fprintf(stderr,"AIFF read: at %d got %d instead of %d samples\n",
832  offset,n,data_length);
833  data_length = n;
834  }
835 
836  *data = convert_raw_data(file_data,data_length,
837  actual_sample_type,bo_big);
838  *num_samples = data_length/comm_channels;
839  *sample_type = st_short;
840  *word_size = 2;
841  *bo = EST_NATIVE_BO;
842  break; /* only care about the first SSND chunk */
843  }
844  else
845  { /* skip bytes in chunk */
846  ts.seek(ts.tell()+chunk.size);
847  }
848  }
849 
850  return format_ok;
851 }
852 
853 
854 enum EST_write_status save_wave_aiff_header(FILE *fp,
855  int num_samples, int num_channels,
856  int sample_rate,
857  enum EST_sample_type_t sample_type, int bo)
858 {
859  (void)bo;
860  const char *info;
861  int data_size, data_int;
862  unsigned char ieee_ext_buf[10];
863  short data_short;
864 
865  info = "FORM";
866  fwrite(info,1,4,fp);
867  /* This number seems to be derived different for each example */
868  data_size = 54+(num_samples*num_channels*get_word_size(sample_type));
869  if (EST_LITTLE_ENDIAN)
870  data_size = SWAPINT(data_size);
871  fwrite(&data_size,1,4,fp);
872  info = "AIFF";
873  fwrite(info,1,4,fp);
874  info = "COMM";
875  fwrite(info,1,4,fp);
876  data_int = 18;
877  if (EST_LITTLE_ENDIAN)
878  data_int = SWAPINT(data_int);
879  fwrite(&data_int,1,4,fp);
880  data_short = num_channels;
881  if (EST_LITTLE_ENDIAN)
882  data_short = SWAPSHORT(data_short);
883  fwrite(&data_short,1,2,fp);
884  data_int = num_samples;
885  if (EST_LITTLE_ENDIAN)
886  data_int = SWAPINT(data_int);
887  fwrite(&data_int,1,4,fp);
888  data_short = 8*get_word_size(sample_type);
889  if (EST_LITTLE_ENDIAN)
890  data_short = SWAPSHORT(data_short);
891  fwrite(&data_short,1,2,fp);
892  ConvertToIeeeExtended((double)sample_rate,ieee_ext_buf);
893  fwrite(ieee_ext_buf,1,10,fp);
894  info = "SSND";
895  fwrite(info,1,4,fp);
896  data_int = 8 + (num_samples*num_channels*get_word_size(sample_type));
897  if (EST_LITTLE_ENDIAN)
898  data_int = SWAPINT(data_int);
899  fwrite(&data_int,1,4,fp);
900  data_int = 0;
901  if (EST_LITTLE_ENDIAN)
902  data_int = SWAPINT(data_int);
903  fwrite(&data_int,1,4,fp); /* offset */
904  if (EST_LITTLE_ENDIAN)
905  data_int = SWAPINT(data_int);
906  fwrite(&data_int,1,4,fp); /* blocksize */
907 
908  return write_ok;
909 
910 }
911 
912 enum EST_write_status save_wave_aiff_data(FILE *fp, const short *data, int offset,
913  int num_samples, int num_channels,
914  int sample_rate,
915  enum EST_sample_type_t sample_type, int bo)
916 {
917 
918  if (data == NULL)
919  return write_ok;
920  if ((sample_type == st_short) || (sample_type == st_uchar))
921  return save_raw_data(fp,data, offset, num_samples, num_channels,
922  sample_type, bo_big);
923  else
924  {
925  fprintf(stderr,"AIFF: requested data type not uchar or short\n");
926  return misc_write_error;
927  }
928 }
929 
930 
931 enum EST_write_status save_wave_aiff(FILE *fp, const short *data, int offset,
932  int num_samples, int num_channels,
933  int sample_rate,
934  enum EST_sample_type_t sample_type, int bo)
935 {
936  save_wave_aiff_header(fp, num_samples, num_channels,
937  sample_rate, sample_type, bo);
938 
939  return save_wave_aiff_data(fp, data, offset,
940  num_samples, num_channels,
941  sample_rate, sample_type, bo);
942 }
943 
944 /*=======================================================================*/
945 /* ulaw EST_filetype are just raw data with 8K ulaw contents */
946 /*=======================================================================*/
947 
948 enum EST_read_status load_wave_ulaw(EST_TokenStream &ts, short **data, int
949  *num_samples, int *num_channels, int *word_size, int
950  *sample_rate, enum EST_sample_type_t *sample_type, int *bo,
951  int offset, int length)
952 
953 {
954  unsigned char *ulaw;
955  int data_length,samps;
956 
957  ts.seek_end();
958  samps = ts.tell();
959 
960  if (length == 0)
961  data_length = samps - offset;
962  else
963  data_length = length;
964 
965  ulaw = walloc(unsigned char, data_length);
966  ts.seek(offset);
967  if (ts.fread(ulaw,1,data_length) != data_length)
968  {
969  wfree(ulaw);
970  return misc_read_error;
971  }
972 
973  *data = walloc(short,data_length);
974  ulaw_to_short(ulaw,*data,data_length);
975  wfree(ulaw);
976 
977  *num_samples = data_length;
978  *sample_rate = 8000;
979  *num_channels = 1;
980  *sample_type = st_short;
981  *word_size = 2;
982  *bo = EST_NATIVE_BO;
983 
984  return format_ok;
985 }
986 
987 enum EST_write_status save_wave_ulaw_header(FILE *fp,
988  int num_samples, int num_channels,
989  int sample_rate,
990  enum EST_sample_type_t sample_type, int bo)
991 {
992  (void) sample_rate;
993  (void) sample_type;
994  (void) fp;
995  (void) num_samples;
996  (void) num_channels;
997  (void) bo;
998  return write_ok;
999 }
1000 
1001 enum EST_write_status save_wave_ulaw_data(FILE *fp, const short *data, int offset,
1002  int num_samples, int num_channels,
1003  int sample_rate,
1004  enum EST_sample_type_t sample_type, int bo)
1005 {
1006  if (data == NULL)
1007  return write_ok;
1008 
1009  return save_wave_raw(fp,data,offset,num_samples,num_channels,
1010  8000,st_mulaw,bo);
1011 }
1012 
1013 enum EST_write_status save_wave_ulaw(FILE *fp, const short *data, int offset,
1014  int num_samples, int num_channels,
1015  int sample_rate,
1016  enum EST_sample_type_t sample_type, int bo)
1017 {
1018  save_wave_ulaw_header(fp, num_samples, num_channels,
1019  sample_rate, sample_type, bo);
1020 
1021  return save_wave_ulaw_data(fp, data, offset,
1022  num_samples, num_channels,
1023  sample_rate, sample_type, bo);
1024 }
1025 
1026 
1027 
1028 enum EST_read_status load_wave_alaw(EST_TokenStream &ts, short **data, int
1029  *num_samples, int *num_channels, int *word_size, int
1030  *sample_rate, enum EST_sample_type_t *sample_type, int *bo,
1031  int offset, int length)
1032 
1033 {
1034  unsigned char *alaw;
1035  int data_length,samps;
1036 
1037  ts.seek_end();
1038  samps = ts.tell();
1039 
1040  if (length == 0)
1041  data_length = samps - offset;
1042  else
1043  data_length = length;
1044 
1045  alaw = walloc(unsigned char, data_length);
1046  ts.seek(offset);
1047  if (ts.fread(alaw,1,data_length) != data_length)
1048  {
1049  wfree(alaw);
1050  return misc_read_error;
1051  }
1052 
1053  *data = walloc(short,data_length);
1054  alaw_to_short(alaw,*data,data_length);
1055  wfree(alaw);
1056 
1057  *num_samples = data_length;
1058  *sample_rate = 8000;
1059  *num_channels = 1;
1060  *sample_type = st_short;
1061  *word_size = 2;
1062  *bo = EST_NATIVE_BO;
1063 
1064  return format_ok;
1065 }
1066 
1067 enum EST_write_status save_wave_alaw_header(FILE *fp,
1068  int num_samples, int num_channels,
1069  int sample_rate,
1070  enum EST_sample_type_t sample_type, int bo)
1071 {
1072  (void) sample_rate;
1073  (void) sample_type;
1074  (void) fp;
1075  (void) num_samples;
1076  (void) num_channels;
1077  (void) bo;
1078  return write_ok;
1079 }
1080 
1081 enum EST_write_status save_wave_alaw_data(FILE *fp, const short *data, int offset,
1082  int num_samples, int num_channels,
1083  int sample_rate,
1084  enum EST_sample_type_t sample_type, int bo)
1085 {
1086  (void)sample_rate;
1087  (void)sample_type;
1088  if (data == NULL)
1089  return write_ok;
1090  return save_wave_raw(fp,data,offset,num_samples,num_channels,
1091  8000,st_alaw,bo);
1092 }
1093 
1094 enum EST_write_status save_wave_alaw(FILE *fp, const short *data, int offset,
1095  int num_samples, int num_channels,
1096  int sample_rate,
1097  enum EST_sample_type_t sample_type, int bo)
1098 {
1099  save_wave_alaw_header(fp, num_samples, num_channels,
1100  sample_rate, sample_type, bo);
1101 
1102  return save_wave_alaw_data(fp, data, offset,
1103  num_samples, num_channels,
1104  sample_rate, sample_type, bo);
1105 }
1106 
1107 
1108 /*=======================================================================*/
1109 /* Sun and Next snd files */
1110 /*=======================================================================*/
1111 
1112 typedef struct {
1113  unsigned int magic; /* magic number */
1114  unsigned int hdr_size; /* size of this header */
1115  int data_size; /* length of data (optional) */
1116  unsigned int encoding; /* data encoding format */
1117  unsigned int sample_rate; /* samples per second */
1118  unsigned int channels; /* number of interleaved channels */
1119 } Sun_au_header;
1120 
1121 enum EST_read_status load_wave_snd(EST_TokenStream &ts, short **data, int
1122  *num_samples, int *num_channels, int *word_size, int
1123  *sample_rate,enum EST_sample_type_t *sample_type, int *bo ,
1124  int offset, int length)
1125 {
1126  /* Header structures */
1127  Sun_au_header header;
1128  enum EST_sample_type_t encoding_type;
1129  int data_length, sample_width, bytes, samps, n;
1130  unsigned char *file_data;
1131  int current_pos;
1132 
1133  current_pos = ts.tell();
1134  if (ts.fread(&header, sizeof(Sun_au_header), 1) != 1)
1135  return misc_read_error;
1136 
1137  /* test for magic number */
1138  if ((EST_LITTLE_ENDIAN) &&
1139  ((unsigned int)0x2e736e64 == SWAPINT(header.magic)))
1140  { /* wrong byte order, swap header */
1141  header.hdr_size = SWAPINT(header.hdr_size);
1142  header.data_size = SWAPINT(header.data_size);
1143  header.encoding = SWAPINT(header.encoding);
1144  header.sample_rate = SWAPINT(header.sample_rate);
1145  header.channels = SWAPINT(header.channels);
1146  }
1147  else if ((unsigned int)0x2e736e64 != header.magic)
1148  return wrong_format;
1149 
1150  switch (header.encoding)
1151  {
1152  case 1:
1153  encoding_type = st_mulaw;
1154  break;
1155  case 2:
1156  encoding_type = st_uchar;
1157  break;
1158  case 3:
1159  encoding_type = st_short;
1160  break;
1161  default:
1162  fprintf(stderr, "Unsupported data type in SND header\n");
1163  return misc_read_error;
1164  }
1165 
1166  *num_channels = header.channels;
1167  sample_width = get_word_size(encoding_type);
1168  *sample_rate = header.sample_rate;
1169 
1170  if ((header.data_size == 0) ||
1171  (header.data_size == -1))
1172  {
1173  ts.seek_end();
1174  bytes = ts.tell() - header.hdr_size;
1175  }
1176  else
1177  bytes = header.data_size;
1178  samps = bytes/sample_width;
1179 
1180  if (length == 0)
1181  data_length = (samps - offset)*(*num_channels);
1182  else
1183  data_length = length *(*num_channels);
1184 
1185  file_data = walloc(unsigned char, sample_width * data_length);
1186  ts.seek(current_pos+header.hdr_size+(sample_width*offset*(*num_channels)));
1187  if ((n=ts.fread(file_data,sample_width,data_length)) != data_length)
1188  {
1189  fprintf(stderr,"WAVE read: short file %s\n",
1190  (const char *)ts.filename());
1191  fprintf(stderr,"WAVE read: at %d got %d instead of %d samples\n",
1192  offset,n,data_length);
1193  data_length = n;
1194  }
1195 
1196  *data = convert_raw_data(file_data,data_length,encoding_type,bo_big);
1197 
1198  if (*data == NULL)
1199  return read_error;
1200 
1201  *num_samples = data_length/ (*num_channels);
1202  *sample_type = st_short;
1203  *bo = EST_NATIVE_BO;
1204  *word_size = 2;
1205  return read_ok;
1206 }
1207 
1208 enum EST_write_status save_wave_snd_header(FILE *fp,
1209  int num_samples, int num_channels,
1210  int sample_rate,
1211  enum EST_sample_type_t sample_type, int bo)
1212 {
1213  (void)bo;
1214  /* Header structures */
1215  Sun_au_header header;
1216 
1217  /* Fill in header structure */
1218  header.magic = (unsigned int)0x2e736e64; /* should be a macro surely */
1219  header.hdr_size = sizeof(header); /* ! */
1220  header.data_size = get_word_size(sample_type) * num_channels * num_samples;
1221 
1222  switch (sample_type) {
1223  case st_mulaw:
1224  header.encoding = 1;
1225  break;
1226  case st_uchar:
1227  header.encoding = 2;
1228  break;
1229  case st_short:
1230  header.encoding = 3;
1231  break;
1232 
1233  default:
1234  fprintf(stderr,
1235  "Unsupported sample type cannot be saved in SND format\n");
1236  return misc_write_error;
1237 
1238  }
1239 
1240  /* check consistency */
1241 
1242  header.sample_rate = sample_rate;
1243 
1244  header.channels = num_channels;
1245 
1246  if (EST_LITTLE_ENDIAN)
1247  {
1248  /* snd files all in big endian format */
1249  header.magic = SWAPINT(header.magic);
1250  header.hdr_size = SWAPINT(header.hdr_size);
1251  header.data_size = SWAPINT(header.data_size);
1252  header.encoding = SWAPINT(header.encoding);
1253  header.sample_rate = SWAPINT(header.sample_rate);
1254  header.channels = SWAPINT(header.channels);
1255 
1256  }
1257  /* write header */
1258  if (fwrite(&header, sizeof(header), 1, fp) != 1)
1259  return misc_write_error;
1260 
1261  return write_ok;
1262 }
1263 
1264 enum EST_write_status save_wave_snd_data(FILE *fp, const short *data, int offset,
1265  int num_samples, int num_channels,
1266  int sample_rate,
1267  enum EST_sample_type_t sample_type, int bo)
1268 {
1269  if (data == NULL)
1270  return write_ok;
1271 
1272  /* snd files are always in BIG_ENDIAN (sun) byte order */
1273  return save_raw_data(fp,data,offset,num_samples,num_channels,
1274  sample_type,bo_big);
1275 }
1276 
1277 
1278 enum EST_write_status save_wave_snd(FILE *fp, const short *data, int offset,
1279  int num_samples, int num_channels,
1280  int sample_rate,
1281  enum EST_sample_type_t sample_type, int bo)
1282 {
1283  save_wave_snd_header(fp, num_samples, num_channels, sample_rate,
1284  sample_type, bo);
1285  return save_wave_snd_data(fp, data, offset, num_samples,
1286  num_channels, sample_rate, sample_type, bo);
1287 }
1288 
1289 
1290 /*=======================================================================*/
1291 /* CSTR Audlab files (from the last century) */
1292 /* They are always bigendian */
1293 /*=======================================================================*/
1294 struct s1 {
1295  char c[17];
1296  float f1;
1297  float f2;
1298 };
1299 
1300 struct s2 {
1301  float f1;
1302  float f2;
1303  float f3;
1304  char c1;
1305  char c2;
1306  int i1;
1307  int i2;
1308 };
1309 
1310 struct audlabfh {
1311  struct s1 z;
1312  char file_type[8];
1313  char c1[17];
1314  char c2[17];
1315  char c3[17];
1316  int start;
1317  char data_type;
1318  char c5[64];
1319 };
1320 
1321 struct audlabsh {
1322  int channel_count;
1323  char serial;
1324  int sample_rate;
1325  char c1[20];
1326  int i1;
1327  char c2;
1328  char c3[121];
1329  char c4[121];
1330 
1331 };
1332 struct audlabsd {
1333  char descr[17];
1334  int sample_count;
1335  int nbits;
1336  float f1;
1337  struct s2 z;
1338 };
1339 
1340 enum EST_read_status load_wave_audlab(EST_TokenStream &ts, short **data, int
1341  *num_samples, int *num_channels, int *word_size, int
1342  *sample_rate, enum EST_sample_type_t *sample_type, int *bo, int
1343  offset, int length)
1344 {
1345  /* Header structures */
1346  struct audlabfh fh;
1347  struct audlabsh sh;
1348  struct audlabsd sd;
1349  int data_length,sample_count;
1350  int hdr_length;
1351  int current_pos;
1352 
1353  /* Read header structures from char array */
1354  current_pos = ts.tell();
1355 
1356  if (ts.fread(&fh, sizeof(struct audlabfh), 1) != 1)
1357  return misc_read_error;
1358  if (strcmp(fh.file_type, "Sample") != 0)
1359  return wrong_format;
1360 
1361  if (ts.fread(&sh, sizeof(struct audlabsh), 1) != 1)
1362  return misc_read_error;
1363  if (ts.fread(&sd, sizeof(struct audlabsd), 1) != 1)
1364  return misc_read_error;
1365  hdr_length = sizeof(struct audlabfh) +
1366  sizeof(struct audlabsh) +
1367  sizeof(struct audlabsd);
1368 
1369  if (EST_BIG_ENDIAN)
1370  {
1371  *num_channels = sh.channel_count;
1372  *sample_rate = sh.sample_rate;
1373  sample_count = sd.sample_count;
1374  }
1375  else // audlab files are bigendian
1376  {
1377  *num_channels = SWAPINT(sh.channel_count);
1378  *sample_rate = SWAPINT(sh.sample_rate);
1379  sample_count = SWAPINT(sd.sample_count);
1380  }
1381  if (length == 0)
1382  data_length = (sample_count - offset) * (*num_channels);
1383  else
1384  data_length = length *(*num_channels);
1385 
1386  *data = walloc(short,sizeof(short) * data_length);
1387  ts.seek(current_pos+hdr_length+(sizeof(short)*offset*(*num_channels)));
1388 
1389  if ((int)ts.fread(*data, sizeof(short), data_length) != data_length)
1390  {
1391  wfree(*data);
1392  return misc_read_error;
1393  }
1394  if (EST_LITTLE_ENDIAN)
1395  swap_bytes_short(*data,data_length);
1396 
1397  *num_samples = data_length / (*num_channels);
1398  *sample_type = st_short; /* set internal type*/
1399  *word_size = sizeof(short);
1400  *bo = EST_NATIVE_BO;
1401 
1402  return format_ok;
1403 }
1404 
1405 enum EST_write_status save_wave_audlab_header(FILE *fp,
1406  int num_samples, int num_channels,
1407  int sample_rate,
1408  enum EST_sample_type_t sample_type, int bo)
1409 {
1410  (void)bo;
1411  (void)sample_type;
1412  /* Header structures */
1413  struct audlabfh fh;
1414  struct audlabsh sh;
1415  struct audlabsd sd;
1416 
1417  fh.start = sizeof (struct audlabfh) +
1418  sizeof (struct audlabsh) + sizeof (struct audlabsd);
1419  fh.data_type = 2;
1420  strcpy(fh.file_type, "Sample");
1421 
1422  if (EST_LITTLE_ENDIAN)
1423  { // need to swap some of those numbers
1424  sh.channel_count = SWAPINT(num_channels);
1425  sh.serial = 1;
1426  sh.sample_rate = SWAPINT(sample_rate);
1427 
1428  sd.sample_count = SWAPINT(num_samples);
1429  sd.nbits = SWAPINT(16);
1430  }
1431  else
1432  {
1433  sh.channel_count = num_channels;
1434  sh.serial = 1;
1435  sh.sample_rate = sample_rate;
1436 
1437  sd.sample_count = num_samples;
1438  sd.nbits = 16;
1439  }
1440  sprintf(sd.descr, "Filter 1");
1441 
1442  /* write headers */
1443  fwrite (&fh, sizeof(fh), 1, fp);
1444  fwrite (&sh, sizeof(sh), 1, fp);
1445  fwrite (&sd, sizeof(sd), 1, fp);
1446  return write_ok;
1447 }
1448 
1449 enum EST_write_status save_wave_audlab_data(FILE *fp, const short *data, int offset,
1450  int num_samples, int num_channels,
1451  int sample_rate,
1452  enum EST_sample_type_t sample_type, int bo)
1453 {
1454  if (data == NULL)
1455  return write_ok;
1456 
1457  /* write data*/
1458  return save_raw_data(fp,data,offset,num_samples,num_channels,
1459  st_short,bo_big);
1460 }
1461 
1462 enum EST_write_status save_wave_audlab(FILE *fp, const short *data, int offset,
1463  int num_samples, int num_channels,
1464  int sample_rate,
1465  enum EST_sample_type_t sample_type, int bo)
1466 {
1467  save_wave_audlab_header(fp, num_samples, num_channels,
1468  sample_rate, sample_type, bo);
1469  return save_wave_audlab_data(fp, data, offset,
1470  num_samples, num_channels,
1471  sample_rate, sample_type, bo);
1472 }
1473 
1474 /*=======================================================================*/
1475 /* Entropic ESPS SD files: portable (non-proprietary) method */
1476 /*=======================================================================*/
1477 
1478 /* Deep thanks go to Peter Kabal from McGill University whose AF code */
1479 /* showed me this was even possible. I looked at his code to find */
1480 /* parts I couldn't work out myself. Also to Rodney Johnson of */
1481 /* Entropic whose document "ESPS APPLICATION NOTE: Non-ESPS Programs */
1482 /* and the ESPS File System" gave details of how to access ESPS files */
1483 /* without using the ESPS library code. */
1484 
1485 #include "esps_utils.h"
1486 enum EST_read_status load_wave_sd(EST_TokenStream &ts, short **data, int
1487  *num_samples, int *num_channels, int
1488  *word_size, int *sample_rate, enum
1489  EST_sample_type_t *sample_type, int *bo , int
1490  offset, int length)
1491 {
1492  /* A license free version of an esps file reading program */
1493  FILE *fd;
1494  esps_hdr hdr;
1495  int actual_bo, sample_width, data_length;
1496  enum EST_read_status rv;
1497  int dl;
1498  enum EST_sample_type_t actual_sample_type;
1499  double d;
1500  unsigned char *file_data;
1501 
1502  if ((fd = ts.filedescriptor()) == NULL)
1503  {
1504  fprintf(stderr, "Can't open esps file %s for reading\n",
1505  (const char *)ts.filename());
1506  return misc_read_error;
1507  }
1508 
1509  if ((rv=read_esps_hdr(&hdr,fd)) != format_ok)
1510  return rv;
1511 
1512  if (hdr->file_type != ESPS_SD)
1513  {
1514  fprintf(stderr,"ESPS file: not an FEA_SD file\n");
1515  delete_esps_hdr(hdr);
1516  return misc_read_error;
1517  }
1518 
1519  if (fea_value_d("record_freq",0,hdr,&d) != 0)
1520  {
1521  fprintf(stderr,"ESPS file: can't find sample_rate in header assuming 16000\n");
1522  *sample_rate = 16000;
1523  }
1524  else
1525  *sample_rate = (int)d;
1526  actual_sample_type = st_short; /* you're not trying hard enough */
1527  sample_width = get_word_size(actual_sample_type);
1528  *num_channels = hdr->field_dimension[0];
1529  if (hdr->swapped)
1530  actual_bo = (EST_BIG_ENDIAN ? bo_little : bo_big);
1531  else
1532  actual_bo = (EST_BIG_ENDIAN ? bo_big : bo_little);
1533 
1534  if (length == 0)
1535  data_length = (hdr->num_records - offset)*(*num_channels);
1536  else
1537  data_length = length *(*num_channels);
1538 
1539  file_data = walloc(unsigned char, sample_width * data_length);
1540  fseek(fd,hdr->hdr_size+(sample_width*offset*(*num_channels)),
1541  SEEK_SET);
1542  if ((dl=fread(file_data,sample_width,data_length,fd)) != data_length)
1543  {
1544  fprintf(stderr,"WAVE read: esps short file %s\n",
1545  (const char *)ts.filename());
1546  fprintf(stderr,"WAVE read: at %d got %d instead of %d samples\n",
1547  offset,dl,data_length);
1548  data_length = dl;
1549  }
1550 
1551  *data = convert_raw_data(file_data,data_length,
1552  actual_sample_type,
1553  actual_bo);
1554 
1555  *num_samples = data_length/ (*num_channels);
1556  *sample_type = st_short;
1557  *bo = EST_NATIVE_BO;
1558  *word_size = 2;
1559  delete_esps_hdr(hdr);
1560  return format_ok;
1561 
1562 }
1563 
1564 
1565 enum EST_write_status save_wave_sd_header(FILE *fp,
1566  int num_samples, int num_channels,
1567  int sample_rate,
1568  enum EST_sample_type_t sample_type, int bo)
1569 
1570 {
1571  (void)bo;
1572  esps_hdr hdr = make_esps_sd_hdr();
1573  enum EST_write_status rv;
1574  short esps_type;
1575 
1576  hdr->num_records = num_samples;
1577  switch (sample_type)
1578  {
1579  case st_short: esps_type = ESPS_SHORT; break;
1580  case st_schar: esps_type = ESPS_CHAR; break; /* maybe should be BYTE */
1581  case st_int: esps_type = ESPS_INT; break;
1582  case st_float: esps_type = ESPS_FLOAT; break;
1583  case st_double: esps_type = ESPS_DOUBLE; break;
1584  default:
1585  fprintf(stderr,"ESPS file: no support for sample_type %s\n",
1586  sample_type_to_str(sample_type));
1587  return misc_write_error;
1588  }
1589  /* I believe all of the following are necessary and in this order */
1590  add_field(hdr,"samples",esps_type,num_channels);
1591  /* FIXME: What is doing this path here?? */
1592  add_fea_special(hdr,ESPS_FEA_DIRECTORY,"margo:/disk/disk10/home/awb/projects/speech_tools/main");
1593  add_fea_special(hdr,ESPS_FEA_COMMAND,
1594  "EDST waveform written as ESPS FEA_SD.\n\
1595  ");
1596  add_fea_d(hdr,"start_time",0,(double)0);
1597  add_fea_d(hdr,"record_freq",0,(double)sample_rate);
1598  add_fea_d(hdr,"max_value",0,(double)27355);
1599 
1600  if ((rv=write_esps_hdr(hdr,fp)) != write_ok)
1601  {
1602  delete_esps_hdr(hdr);
1603  return rv;
1604  }
1605  /* lets ignore desired bo and sample type for the time being */
1606  delete_esps_hdr(hdr);
1607  return write_ok;
1608 }
1609 
1610 
1611 enum EST_write_status save_wave_sd_data(FILE *fp, const short *data,
1612  int offset,
1613  int num_samples, int num_channels,
1614  int sample_rate,
1615  enum EST_sample_type_t sample_type, int bo)
1616 
1617 {
1618  if (data == NULL)
1619  return write_ok;
1620 
1621  return save_raw_data(fp,data,offset,num_samples,num_channels,
1622  sample_type,EST_NATIVE_BO);
1623 }
1624 
1625 enum EST_write_status save_wave_sd(FILE *fp, const short *data, int offset,
1626  int num_samples, int num_channels,
1627  int sample_rate,
1628  enum EST_sample_type_t sample_type, int bo)
1629 
1630 {
1631  save_wave_sd_header(fp, num_samples, num_channels, sample_rate,
1632  sample_type, bo);
1633  return save_wave_sd_data(fp, data, offset, num_samples,
1634  num_channels, sample_rate, sample_type, bo);
1635 
1636 }
1637 
1638 /*=======================================================================*/
1639 /* Raw data files -- unheadered */
1640 /* THESE FUNCTIONS ARE DIFFERENT FROM THE REST */
1641 /* These function have more parameters than the standard file i/o */
1642 /* as information cannot be gleamed from the file */
1643 /*=======================================================================*/
1644 
1645 enum EST_read_status load_wave_raw(EST_TokenStream &ts, short **data, int
1646  *num_samples, int *num_channels,
1647  int *word_size, int
1648  *sample_rate,
1649  enum EST_sample_type_t *sample_type,
1650  int *bo, int offset, int length,
1651  int isample_rate,
1652  enum EST_sample_type_t isample_type,
1653  int ibo, int inc)
1654 {
1655  unsigned char *file_data;
1656  int data_length,samps,sample_width;
1657  int guess,i,samp;
1658  short *ndata;
1659 
1660  if (isample_type == st_ascii)
1661  {
1662  /* Guess the size */
1663  if ((offset != 0) || (length != 0))
1664  {
1665  fprintf(stderr,"Load ascii wave: doesn't support offets and lengths\n");
1666  return misc_read_error;
1667  }
1668 
1669  ts.seek_end();
1670  guess = (int)(1.2*ts.tell()/7)+10; /* rough guess of the num of samps */
1671  ts.seek(0);
1672  *data = walloc(short, guess);
1673  i=0;
1674  while (!ts.eof())
1675  {
1676  samp = atoi(ts.get().string());
1677  if (i == guess)
1678  {
1679  ndata = walloc(short,(int)(guess*1.2));
1680  memmove(ndata,*data,guess*sizeof(short));
1681  wfree(*data);
1682  *data = ndata;
1683  guess = (int)(guess*1.2);
1684  }
1685  if (samp < -32768)
1686  {
1687  fprintf(stderr,"Load ascii wave: sample %d underflow clipping\n",
1688  i);
1689  (*data)[i] = -32768;
1690  }
1691  else if (samp > 32767)
1692  {
1693  fprintf(stderr,"Load ascii wave: sample %d overflow clipping\n",
1694  i);
1695  (*data)[i] = 32767;
1696  }
1697  else
1698  (*data)[i] = (short)samp;
1699  i++;
1700  }
1701  data_length = i;
1702  }
1703  else
1704  {
1705  ts.seek_end();
1706  sample_width = get_word_size(isample_type);
1707  samps = ts.tell()/sample_width;
1708 
1709  if (length == 0)
1710  data_length = samps - offset;
1711  else
1712  data_length = length;
1713 
1714  file_data = walloc(unsigned char, data_length * sample_width *inc);
1715  ts.seek(offset*sample_width*inc);
1716  if ((int)ts.fread(file_data,sample_width,data_length) != data_length)
1717  return misc_read_error;
1718 
1719  *data = convert_raw_data(file_data,data_length,isample_type,ibo);
1720  }
1721 
1722  *num_samples = data_length/inc;
1723  *sample_rate = isample_rate;
1724  *num_channels = inc;
1725  *sample_type = st_short;
1726  *word_size = 2;
1727  *bo = EST_NATIVE_BO;
1728 
1729  return format_ok;
1730 }
1731 
1732 enum EST_write_status save_wave_raw_header(FILE *fp,
1733  int num_samples, int num_channels,
1734  int sample_rate,
1735  enum EST_sample_type_t sample_type, int bo)
1736 {
1737  return write_ok;
1738 }
1739 
1740 enum EST_write_status save_wave_raw_data(FILE *fp, const short *data,
1741  int offset,
1742  int num_samples, int num_channels,
1743  int sample_rate,
1744  enum EST_sample_type_t sample_type, int bo)
1745 {
1746  if (data == NULL)
1747  return write_ok;
1748 
1749  return save_raw_data(fp,data,offset,num_samples,num_channels,
1750  sample_type,bo);
1751 }
1752 
1753 enum EST_write_status save_wave_raw(FILE *fp, const short *data,
1754  int offset,
1755  int num_samples, int num_channels,
1756  int sample_rate,
1757  enum EST_sample_type_t sample_type, int bo)
1758 {
1759  (void)sample_rate;
1760 
1761  return save_wave_raw_data(fp, data, offset, num_samples,
1762  num_channels, sample_rate, sample_type, bo);
1763 }
1764 
1765 /***********************************************************************/
1766 /* */
1767 /* end of file type specific functions */
1768 /* */
1769 /***********************************************************************/
1770 
1771 enum EST_write_status wave_io_save_header(FILE *fp,
1772  const int num_samples, const int num_channels,
1773  const int sample_rate,
1774  const EST_String& stype, const int bo,
1775  const EST_String& ftype)
1776 {
1777  EST_WaveFileType t = EST_WaveFile::map.token(ftype);
1778  EST_sample_type_t sample_type = EST_sample_type_map.token(stype);
1779  switch(t)
1780  {
1781  case wff_nist:
1782  return save_wave_nist_header(fp, num_samples, num_channels,
1783  sample_rate, sample_type, bo);
1784  break;
1785  case wff_esps:
1786  return save_wave_sd_header(fp, num_samples, num_channels,
1787  sample_rate, sample_type, bo);
1788  break;
1789  case wff_est:
1790  return save_wave_est_header(fp, num_samples, num_channels,
1791  sample_rate, sample_type, bo);
1792  break;
1793  case wff_audlab:
1794  return save_wave_audlab_header(fp, num_samples, num_channels,
1795  sample_rate, sample_type, bo);
1796  break;
1797  case wff_snd:
1798  return save_wave_snd_header(fp, num_samples, num_channels,
1799  sample_rate, sample_type, bo);
1800  break;
1801  case wff_aiff:
1802  return save_wave_aiff_header(fp, num_samples, num_channels,
1803  sample_rate, sample_type, bo);
1804  break;
1805  case wff_riff:
1806  return save_wave_riff_header(fp, num_samples, num_channels,
1807  sample_rate, sample_type, bo);
1808  break;
1809  case wff_raw:
1810  return save_wave_raw_header(fp, num_samples, num_channels,
1811  sample_rate, sample_type, bo);
1812  break;
1813  case wff_ulaw:
1814  return save_wave_ulaw_header(fp, num_samples, num_channels,
1815  sample_rate, sample_type, bo);
1816  break;
1817  default:
1818  case wff_none:
1819  cerr << "Can't save wave header to files type " << ftype << endl;
1820  break;
1821  }
1822  return write_ok;
1823 }
1824 
1825 
1826 enum EST_write_status wave_io_save_data(FILE *fp, const short * data,
1827  const int offset,
1828  const int num_samples, const int num_channels,
1829  const int sample_rate,
1830  const EST_String& stype, const int bo,
1831  const EST_String& ftype)
1832 {
1833  EST_WaveFileType t = EST_WaveFile::map.token(ftype);
1834  EST_sample_type_t sample_type = EST_sample_type_map.token(stype);
1835  switch(t)
1836  {
1837  case wff_nist:
1838  return save_wave_nist_data(fp, data, offset, num_samples, num_channels,
1839  sample_rate, sample_type, bo);
1840  break;
1841  case wff_esps:
1842  return save_wave_sd_data(fp, data, offset, num_samples, num_channels,
1843  sample_rate, sample_type, bo);
1844  break;
1845  case wff_est:
1846  return save_wave_est_data(fp, data, offset, num_samples, num_channels,
1847  sample_rate, sample_type, bo);
1848  break;
1849  case wff_audlab:
1850  return save_wave_audlab_data(fp, data, offset, num_samples, num_channels,
1851  sample_rate, sample_type, bo);
1852  break;
1853  case wff_snd:
1854  return save_wave_snd_data(fp, data, offset, num_samples, num_channels,
1855  sample_rate, sample_type, bo);
1856  break;
1857  case wff_aiff:
1858  return save_wave_aiff_data(fp, data, offset, num_samples, num_channels,
1859  sample_rate, sample_type, bo);
1860  break;
1861  case wff_riff:
1862  return save_wave_riff_data(fp, data, offset, num_samples, num_channels,
1863  sample_rate, sample_type, bo);
1864  break;
1865  case wff_raw:
1866  return save_wave_raw_data(fp, data, offset, num_samples, num_channels,
1867  sample_rate, sample_type, bo);
1868  break;
1869  case wff_ulaw:
1870  return save_wave_ulaw_data(fp, data, offset, num_samples, num_channels,
1871  sample_rate, sample_type, bo);
1872  break;
1873  default:
1874  case wff_none:
1875  cerr << "Can't save wave data to files type " << ftype << endl;
1876  break;
1877  }
1878  return write_ok;
1879 }
EST_TokenStream & get(EST_Token &t)
get next token in stream
Definition: EST_Token.cc:486
FILE * filedescriptor()
For the people who need the actual description (if possible)
Definition: EST_Token.h:381
int ival(const EST_String &rkey, int m=1) const
Definition: EST_Option.cc:76
void close(void)
Close stream.
Definition: EST_Token.cc:406
int tell(void) const
tell, synonym for filepos
Definition: EST_Token.h:370
const EST_String filename() const
The originating filename (if there is one)
Definition: EST_Token.h:379
int fread(void *buff, int size, int nitems)
Reading binary data, (don't use peek() immediately beforehand)
Definition: EST_Token.cc:355
int open(const EST_String &filename)
open a EST_TokenStream for a file.
Definition: EST_Token.cc:200
int eof()
end of file
Definition: EST_Token.h:363
const int present(const K &rkey) const
Returns true if key is present.
Definition: EST_TKVL.cc:222
const V & val(const K &rkey, bool m=0) const
return value according to key (const)
Definition: EST_TKVL.cc:145
const EST_String pos_description()
A string describing current position, suitable for error messages.
Definition: EST_Token.cc:868
int seek(int position)
seek, reposition file pointer
Definition: EST_Token.cc:305