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