1 /*---------------------------------------------------------------------------*
2 * riff.c *
3 * *
4 * Copyright 2007, 2008 Nuance Communciations, Inc. *
5 * *
6 * Licensed under the Apache License, Version 2.0 (the 'License'); *
7 * you may not use this file except in compliance with the License. *
8 * *
9 * You may obtain a copy of the License at *
10 * http://www.apache.org/licenses/LICENSE-2.0 *
11 * *
12 * Unless required by applicable law or agreed to in writing, software *
13 * distributed under the License is distributed on an 'AS IS' BASIS, *
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15 * See the License for the specific language governing permissions and *
16 * limitations under the License. *
17 * *
18 *---------------------------------------------------------------------------*/
19
20 #include "plog.h"
21 #include "riff.h"
22
23 #define MTAG NULL
24
25 typedef struct ChunkContext_t
26 {
27 char tag[4];
28 long start;
29 int length;
30 }
31 ChunkContext;
32
33 typedef enum
34 {
35 FIND_RIFF,
36 FIND_CHUNK,
37 FIND_LIST
38 } DescendType;
39
isLittleEndian()40 int isLittleEndian()
41 {
42 char b[4];
43
44 *(int *)b = 1;
45 return (int)b[0];
46 }
47
48 /* waveReadFunc
49 * - converts data to an array of signed shorts
50 * - fills in *length with the number of samples converted
51 * - allocates memory for *samples
52 * - returns GS_OK if conversion was successful or GS_ERROR and an error
53 * message in res if not. If the conversion fails the function must free
54 * all the memory it had allocated before returning.
55 * On entry
56 * wf - points to the WaveFormat structure that describes the data format
57 * cb - data read from the RIFF file
58 * data - descriptor for the "data" chunk
59 */
60 typedef ESR_ReturnCode(waveReadFunc)(WaveFormat *wf, ChunkContext *data,
61 char *cb, short **samples, int *length, int doSwap);
62
63 static ESR_ReturnCode readPCMWave(WaveFormat *wf, ChunkContext *data,
64 char *cb, short **samples, int *length, int doSwap);
65 static ESR_ReturnCode readMulawWave(WaveFormat *wf, ChunkContext *data,
66 char *cb, short **samples, int *length, int doSwap);
67 static ESR_ReturnCode readAlawWave(WaveFormat *wf, ChunkContext *data,
68 char *cb, short **samples, int *length, int doSwap);
69
70 static struct
71 {
72 int id;
73 waveReadFunc *func;
74 }
75 WaveCodecs[] = {
76 {WAVEFORMAT_PCM, readPCMWave},
77 {WAVEFORMAT_MULAW, readMulawWave},
78 {WAVEFORMAT_ALAW, readAlawWave},
79 {0, 0},
80 };
81
82 /************* FIXME: regroup all swap routines outahere;
83 * ditto for audio conversion routines
84 */
85
swapInt(int * i)86 static void swapInt(int *i)
87 {
88 char *a = (char *)i, t;
89 t = a[0];
90 a[0] = a[3];
91 a[3] = t;
92 t = a[1];
93 a[1] = a[2];
94 a[2] = t;
95 }
96
swapShort(short * s)97 static void swapShort(short *s)
98 {
99 char *a = (char *)s, t;
100 t = a[0];
101 a[0] = a[1];
102 a[1] = t;
103 }
104
swapConstInt(const int value)105 static int swapConstInt(const int value)
106 {
107 int converted = value;
108 unsigned char *cp = (unsigned char *) & converted;
109
110 *cp ^= *(cp + 3);
111 *(cp + 3) ^= *cp;
112 *cp ^= *(cp + 3);
113 *(cp + 1) ^= *(cp + 2);
114 *(cp + 2) ^= *(cp + 1);
115 *(cp + 1) ^= *(cp + 2);
116
117 return converted;
118 }
119
swapConstShort(const short value)120 static short swapConstShort(const short value)
121 {
122 short converted = value;
123 unsigned char *cp = (unsigned char *) & converted;
124 unsigned char tmp = *cp;
125
126 *cp = *(cp + 1);
127 *++cp = tmp;
128
129 return converted;
130 }
131
132 /* len == number of bytes to swap
133 */
short_byte_swap(short * buf,int len)134 static void short_byte_swap(short *buf, int len)
135 {
136 char *cp, *end, tmp;
137
138 end = ((char *)buf) + (len << 1);
139 for (cp = (char *)buf; cp < end; cp++)
140 {
141 tmp = *cp;
142 *cp = *(cp + 1);
143 *++cp = tmp;
144 }
145 }
146
147 /* len == number of bytes to swap
148 */
int_byte_swap(int * buf,int len)149 static void int_byte_swap(int *buf, int len)
150 {
151 char *cp, *end;
152
153 end = ((char *)buf) + (len << 2);
154 for (cp = (char *)buf; cp < end; cp += 4)
155 {
156 *cp ^= *(cp + 3);
157 *(cp + 3) ^= *cp;
158 *cp ^= *(cp + 3);
159 *(cp + 1) ^= *(cp + 2);
160 *(cp + 2) ^= *(cp + 1);
161 *(cp + 1) ^= *(cp + 2);
162 }
163 }
164
swapWaveFormat(WaveFormat * wf)165 static void swapWaveFormat(WaveFormat *wf)
166 {
167 swapShort(&wf->nFormatTag);
168 swapShort(&wf->nChannels);
169 swapInt(&wf->nSamplesPerSec);
170 swapInt(&wf->nAvgBytesPerSec);
171 swapShort(&wf->nBlockAlign);
172 swapShort(&wf->wBitsPerSample);
173 //swapShort(&wf->cbSize);
174 }
175
ulaw2linear(unsigned char ulawbyte)176 static int ulaw2linear(unsigned char ulawbyte)
177 {
178 static int exp_lut[8] =
179 {
180 0, 132, 396, 924, 1980, 4092, 8316, 16764
181 };
182 int sign, exponent, mantissa, sample;
183
184 ulawbyte = ~ulawbyte;
185 sign = (ulawbyte & 0x80);
186 exponent = (ulawbyte >> 4) & 0x07;
187 mantissa = ulawbyte & 0x0F;
188 sample = exp_lut[exponent] + (mantissa << (exponent + 3));
189 if (sign != 0) sample = -sample;
190 return sample;
191 }
192
alaw2linear(unsigned char alawbyte)193 static int alaw2linear(unsigned char alawbyte)
194 {
195
196 int sign, achord, astep, delta, sample;
197 unsigned char alawcode;
198 static int exp_lut[8] =
199 {
200 1, 1, 2, 4, 8, 16, 32, 64
201 };
202 alawcode = alawbyte ^ 0x55;
203 sign = (alawcode & 0x80);
204 achord = (alawcode >> 4) & 0x07;
205 astep = alawcode & 0x0F;
206 delta = ((achord == 0) ? 1 : 0);
207 sample = ((2 * astep + 33) * exp_lut[achord]) - 32 * delta;
208 if (sign != 0) sample = -sample;
209 sample = sample * 8;
210
211 return sample;
212 }
213
214 /* Converts PCM wave data
215 * cb: input :1
216
217 */
readPCMWave(WaveFormat * wf,ChunkContext * data,char * cb,short ** samples,int * length,int doSwap)218 static ESR_ReturnCode readPCMWave(WaveFormat *wf, ChunkContext *data,
219 char *cb, short **samples, int *length, int doSwap)
220 {
221 int i;
222 if (wf->nChannels != 1)
223 {
224 //GS_SetResult(res,"PCM WAVE file contains more than one data channel",
225 //GS_STATIC);
226 return ESR_FATAL_ERROR;
227 }
228 if (wf->wBitsPerSample != 16 && wf->wBitsPerSample != 8)
229 {
230 //GS_SetResult(res,GS_Spf(0,"%d bits per sample PCM format not supported",
231 //wf->wBitsPerSample),GS_VOLATILE);
232 return ESR_FATAL_ERROR;
233 }
234 *length = data->length * 8 / wf->wBitsPerSample;
235 *samples = MALLOC(*length * sizeof(short), MTAG);
236 if (wf->wBitsPerSample == 16)
237 {
238 memcpy(*samples, cb, *length*sizeof(short));
239 if (doSwap)
240 for (i = 0;i < *length;i++) swapShort(*samples + i);
241 }
242 else
243 {
244 for (i = 0;i < *length;i++)(*samples)[i] = (short)((unsigned)(cb[i]) - 128) << 8;
245 }
246 return ESR_SUCCESS;
247 }
248
249 /* Converts CCITT u-law wave data
250 */
readMulawWave(WaveFormat * wf,ChunkContext * data,char * cb,short ** samples,int * length,int doSwap)251 static ESR_ReturnCode readMulawWave(WaveFormat *wf, ChunkContext *data,
252 char *cb, short **samples, int *length, int doSwap)
253 {
254 int i;
255 if (wf->nChannels != 1)
256 {
257 //GS_SetResult(res,"u-law WAVE file contains more than one data channel",
258 //GS_STATIC);
259 return ESR_FATAL_ERROR;
260 }
261 if (wf->wBitsPerSample != 8)
262 {
263 //GS_SetResult(res,GS_Spf(0,"%d bits per sample u-law format not supported",
264 //wf->wBitsPerSample),GS_VOLATILE);
265 return ESR_FATAL_ERROR;
266 }
267 *length = data->length;
268 *samples = MALLOC(*length * sizeof(short), MTAG);
269 for (i = 0;i < *length;i++)
270 (*samples)[i] = (short) ulaw2linear(cb[i]);
271 return ESR_SUCCESS;
272 }
273
274 /* Converts a-law wave data
275 */
readAlawWave(WaveFormat * wf,ChunkContext * data,char * cb,short ** samples,int * length,int doSwap)276 static ESR_ReturnCode readAlawWave(WaveFormat *wf, ChunkContext *data,
277 char *cb, short **samples, int *length, int doSwap)
278 {
279 int i;
280 if (wf->nChannels != 1)
281 {
282 //GS_SetResult(res,"u-law WAVE file contains more than one data channel",
283 //GS_STATIC);
284 return ESR_FATAL_ERROR;
285 }
286 if (wf->wBitsPerSample != 8)
287 {
288 //GS_SetResult(res,GS_Spf(0,"%d bits per sample u-law format not supported",
289 //wf->wBitsPerSample),GS_VOLATILE);
290 return ESR_FATAL_ERROR;
291 }
292 *length = data->length;
293 samples = MALLOC(*length * sizeof(short), MTAG);
294 for (i = 0;i < *length;i++)(*samples)[i] = alaw2linear(cb[i]);
295 return ESR_SUCCESS;
296 }
297
298 /* ------------------------------------------------------------------------- */
299
300 /* RIFF INTERFACE UTILS */
301
free_swiRiff(SwiRiffStruct * swichunk)302 void free_swiRiff(SwiRiffStruct *swichunk)
303 {
304 if (swichunk->segs.num_tuples)
305 {
306 FREE(swichunk->segs.tuples);
307 swichunk->segs.num_tuples = 0;
308 }
309 if (swichunk->kvals.num_pairs)
310 {
311 FREE(swichunk->kvals.kvpairs[0].key);
312 FREE(swichunk->kvals.kvpairs);
313 swichunk->kvals.num_pairs = 0;
314 }
315 }
316
getSwiRiffKVal(SwiRiffStruct * swichunk,char * key)317 char *getSwiRiffKVal(SwiRiffStruct *swichunk, char *key)
318 {
319 int i;
320
321 for (i = 0; i < swichunk->kvals.num_pairs; i++)
322 if (! strcmp(swichunk->kvals.kvpairs[i].key, key))
323 return swichunk->kvals.kvpairs[i].value;
324
325 return NULL;
326 }
327
328 /* ------------------------------------------------------------------------- */
329
riffDescend(FILE * f,ChunkContext * c,ChunkContext * parent,DescendType t,int doSwap)330 static int riffDescend(FILE *f, ChunkContext *c, ChunkContext *parent, DescendType t, int doSwap)
331 {
332 char form[4], tag[4];
333 int len;
334 long start, end;
335
336 end = 0;
337 if (!parent) start = 0;
338 else
339 {
340 start = parent->start;
341 end = start + parent->length;
342 }
343 if (fseek(f, start, SEEK_SET) < 0)
344 {
345 //GS_SetResult(res,"seek failed",GS_STATIC);
346 return ESR_FATAL_ERROR;
347 }
348
349 switch (t)
350 {
351
352 case FIND_RIFF:
353 while (1)
354 {
355 if (fread(form, 1, 4, f) != 4) break;
356 if (fread(&len, sizeof(int), 1, f) != 1)
357 return ESR_FATAL_ERROR;
358 if (doSwap)
359 swapInt(&len);
360 if (strncmp(form, "RIFF", 4))
361 { /* skip this non-RIFF chunk */
362 if (fseek(f, (long)len, SEEK_CUR) < 0) break;
363 start += len + 8;
364 if (end && start >= end)
365 {
366 //GS_SetResult(res,"RIFF form type not found",GS_STATIC);
367 return ESR_FATAL_ERROR;
368 }
369 continue;
370 }
371 if (fread(tag, 1, 4, f) != 4) break;
372 if (!strncmp(tag, c->tag, 4))
373 {
374 c->start = start + 12;
375 c->length = len - 4;
376 return ESR_SUCCESS;
377 }
378 }
379 //if(feof(f)) GS_SetResult(res,"RIFF form type not found",GS_STATIC);
380 //else GS_SetResult(res,"Corrupt RIFF file",GS_STATIC);
381 return ESR_FATAL_ERROR;
382
383 case FIND_CHUNK:
384 while (1)
385 {
386 if (fread(tag, 1, 4, f) != 4) break;
387 if (fread(&len, sizeof(int), 1, f) != 1)
388 return ESR_FATAL_ERROR;
389 if (doSwap)
390 swapInt(&len);
391 if (!strncmp(tag, c->tag, 4))
392 {
393 c->start = start + 8;
394 c->length = len;
395 return ESR_SUCCESS;
396 }
397 if (fseek(f, (long)len, SEEK_CUR) < 0) break;
398 start += len + 8;
399 if (end && start >= end)
400 {
401 //GS_SetResult(res,"RIFF chunk not found",GS_STATIC);
402 return ESR_FATAL_ERROR;
403 }
404 }
405 //if(feof(f)) GS_SetResult(res,"RIFF chunk not found",GS_STATIC);
406 //else GS_SetResult(res,"corrupt RIFF file",GS_STATIC);
407 return ESR_FATAL_ERROR;
408
409 case FIND_LIST:
410 while (1)
411 {
412 if (fread(form, 1, 4, f) != 4) break;
413 if (fread(&len, sizeof(int), 1, f) != 1)
414 return ESR_FATAL_ERROR;
415 if (doSwap)
416 swapInt(&len);
417 if (strncmp(form, "LIST", 4))
418 { /* skip this non-LIST chunk */
419 if (fseek(f, (long)len, SEEK_CUR) < 0) break;
420 start += len + 8;
421 if (end && start >= end)
422 {
423 //GS_SetResult(res,"RIFF form type not found",GS_STATIC);
424 return ESR_FATAL_ERROR;
425 }
426 continue;
427 }
428 if (fread(tag, 1, 4, f) != 4) break;
429 if (!strncmp(tag, c->tag, 4))
430 {
431 c->start = start + 12;
432 c->length = len - 4;
433 return ESR_SUCCESS;
434 }
435 }
436
437 //if(feof(f)) GS_SetResult(res,"RIFF form type not found",GS_STATIC);
438 //else GS_SetResult(res,"Corrupt RIFF file",GS_STATIC);
439 return ESR_FATAL_ERROR;
440 }
441
442 //GS_AppendResult(res,"bad search flag",GS_STATIC);
443 return ESR_FATAL_ERROR;
444 }
445
riffAscend(FILE * f,ChunkContext * c)446 static int riffAscend(FILE *f, ChunkContext *c)
447 {
448 if (fseek(f, c->start + c->length, SEEK_SET) < 0)
449 {
450 //GS_SetResult(res,"seek failed",GS_STATIC);
451 return ESR_FATAL_ERROR;
452 }
453 return ESR_SUCCESS;
454 }
455
456
readSwiChunk(FILE * f,ChunkContext * parent,SwiRiffStruct * swichunk,int doSwap)457 static ESR_ReturnCode readSwiChunk(FILE *f, ChunkContext *parent, SwiRiffStruct *swichunk, int doSwap)
458 {
459 ESR_ReturnCode rc = ESR_SUCCESS;
460 ChunkContext chunk, list_chunk;
461 int sub_length;
462 swichunk->segs.num_tuples = 0;
463 swichunk->kvals.num_pairs = 0;
464
465 strncpy(chunk.tag, "swi ", 4);
466 if (riffDescend(f, &chunk, parent, FIND_LIST, doSwap) == ESR_SUCCESS)
467 {
468 /* is it as "swi " list? */
469 strncpy(list_chunk.tag, "segs", 4);
470 if (riffDescend(f, &list_chunk, &chunk, FIND_CHUNK, doSwap) == ESR_SUCCESS)
471 {
472 fread(&swichunk->segs.num_tuples, 1, sizeof(int), f);
473 if (doSwap) swapInt(&swichunk->segs.num_tuples);
474
475 sub_length = list_chunk.length - sizeof(int);
476 if (sub_length)
477 {
478 swichunk->segs.tuples = MALLOC(sub_length, MTAG);
479 if (!swichunk->segs.tuples)
480 {
481 swichunk->segs.num_tuples = 0; /* so that the free routine will work */
482 rc = ESR_OUT_OF_MEMORY;
483 }
484 else if (fread(swichunk->segs.tuples, 1, sub_length, f) != (size_t)sub_length)
485 {
486 rc = ESR_FATAL_ERROR;
487 }
488 if (rc != ESR_SUCCESS)
489 goto swichunk_cleanup;
490
491 }
492 else
493 swichunk->segs.tuples = NULL;
494 }
495 strncpy(list_chunk.tag, "kvs ", 4);
496 /* start searching from after "swi" */
497 if (riffDescend(f, &list_chunk, &chunk, FIND_CHUNK, doSwap) == ESR_SUCCESS)
498 {
499 int i, num_pairs;
500
501 fread(&num_pairs, 1, sizeof(int), f);
502 if (doSwap) swapInt(&num_pairs);
503 swichunk->kvals.num_pairs = num_pairs;
504
505 sub_length = list_chunk.length - sizeof(int);
506 if (sub_length)
507 {
508 char *kvpair_buf = NULL;
509 RiffKVPair *pairs;
510
511 swichunk->kvals.kvpairs = (RiffKVPair *)CALLOC(num_pairs, sizeof(RiffKVPair), MTAG);
512 kvpair_buf = CALLOC(sub_length, sizeof(char), MTAG);
513 if (!swichunk->kvals.kvpairs || !kvpair_buf)
514 {
515 if (kvpair_buf) FREE(kvpair_buf);
516 if (swichunk->kvals.kvpairs) FREE(swichunk->kvals.kvpairs);
517 swichunk->kvals.num_pairs = 0;
518 rc = ESR_OUT_OF_MEMORY;
519 goto swichunk_cleanup;
520 }
521
522 swichunk->kvals.kvpairs[0].key = kvpair_buf;
523 if (fread(kvpair_buf, 1, sub_length, f) != (size_t)sub_length)
524 {
525 rc = ESR_FATAL_ERROR;
526 goto swichunk_cleanup;
527 }
528 for (pairs = swichunk->kvals.kvpairs, i = 0; i < swichunk->kvals.num_pairs; i++, pairs++)
529 {
530 pairs->key = kvpair_buf;
531 kvpair_buf += strlen(kvpair_buf) + 1;
532 pairs->value = kvpair_buf;
533 kvpair_buf += strlen(kvpair_buf) + 1;
534 }
535 }
536 else
537 swichunk->kvals.kvpairs = NULL;
538 }
539 }
540 /* no matter what was found or not found, return with the file pointer in
541 * the state that it was upon entering this function */
542 if (riffAscend(f, parent) != ESR_SUCCESS)
543 {
544 rc = ESR_FATAL_ERROR;
545 goto swichunk_cleanup;
546 }
547
548 swichunk_cleanup:
549 if (rc == ESR_FATAL_ERROR) free_swiRiff(swichunk);
550 return rc;
551 }
552
553
554 /* Reads RIFF format WAVE files
555 */
riffReadWave2L16(FILE * f,double from,double to,short ** samples,int * rate,int * length,SwiRiffStruct * swichunk)556 ESR_ReturnCode riffReadWave2L16(FILE *f, double from, double to,
557 short **samples, int *rate, int *length, SwiRiffStruct *swichunk)
558 {
559 ChunkContext chunk, parent;
560 WaveFormat *wf;
561 char *cb;
562 ESR_ReturnCode rc;
563 int i, ifrom, ito;
564 int doSwap = ! isLittleEndian();
565
566 /* find the WAVE chunk */
567 strncpy(parent.tag, "WAVE", 4);
568 if (riffDescend(f, &parent, NULL, FIND_RIFF, doSwap) != ESR_SUCCESS)
569 {
570 //GS_AppendResult(res,"\nnot a RIFF waveform audio file",NULL);
571 return ESR_FATAL_ERROR;
572 }
573
574 /* Wave format */
575 strncpy(chunk.tag, "fmt ", 4);
576 if (riffDescend(f, &chunk, &parent, FIND_CHUNK, doSwap) != ESR_SUCCESS)
577 {
578 //GS_AppendResult(res,"\nwaveform audio file has no \"fmt \" chunk.",NULL);
579 return ESR_FATAL_ERROR;
580 }
581 if (chunk.length < sizeof(WaveFormat))
582 wf = MALLOC(sizeof(WaveFormat), MTAG);
583 else
584 wf = MALLOC(chunk.length, MTAG);
585
586 if (fread(wf, 1, chunk.length, f) != (size_t)chunk.length)
587 {
588 FREE((char *)wf);
589 //GS_SetResult(res,"fmt chunk read failed.",GS_STATIC);
590 return ESR_FATAL_ERROR;
591 }
592 if (doSwap) swapWaveFormat(wf);
593 *rate = wf->nSamplesPerSec;
594
595 /* data chunk */
596 if (riffAscend(f, &chunk) != ESR_SUCCESS)
597 {
598 return ESR_FATAL_ERROR;
599 }
600 strncpy(chunk.tag, "data", 4);
601 if (riffDescend(f, &chunk, &parent, FIND_CHUNK, doSwap) != ESR_SUCCESS)
602 {
603 //GS_AppendResult(res,"\nwaveform audio file has no \"data\" chunk.",NULL);
604 return ESR_FATAL_ERROR;
605 }
606 cb = MALLOC(chunk.length, MTAG); /* waveform */
607 if (fread(cb, 1, chunk.length, f) != (size_t)chunk.length)
608 {
609 FREE((char *)wf);
610 FREE((char *)cb);
611 //GS_SetResult(res,"truncated \"data\" chunk",GS_STATIC);
612 return ESR_FATAL_ERROR;
613 }
614
615 if (swichunk)
616 {
617 rc = readSwiChunk(f, &parent, swichunk, doSwap);
618 if (rc != ESR_SUCCESS)
619 {
620 FREE((char *)wf);
621 FREE((char *)cb);
622 return rc;
623 }
624 }
625
626 for (i = 0;WaveCodecs[i].func;i++)
627
628 if (wf->nFormatTag == WaveCodecs[i].id)
629 {
630 rc = (WaveCodecs[i].func)(wf, &chunk, cb, samples, length, doSwap);
631 FREE((char *)wf);
632 FREE((char *)cb);
633 if (rc != ESR_SUCCESS)
634 {
635 if (swichunk) free_swiRiff(swichunk);
636 return rc;
637 }
638 /* handle 'from' and 'to' - this isn't very efficient, but
639 * saves all the format conversion routines the trouble of doing so
640 */
641 if (from == 0 && to == -1) return ESR_SUCCESS;
642 if (from > 0)
643 ifrom = (int)(from * (*rate) / 1000.0);
644 else
645 ifrom = 0;
646
647 if (to >= 0)
648 {
649 ito = (int)(to * (*rate) / 1000.0 + 0.5);
650 if (ito > *length)
651 ito = *length;
652 }
653 else
654 ito = *length;
655
656 *length = ito - ifrom;
657 if (ifrom > 0) memmove(*samples, (*samples) + ifrom, (*length)*sizeof(short));
658 return ESR_SUCCESS;
659 }
660
661 //GS_SetResult(res,GS_Spf(0,"WAVE format (id 0x%x) not supported",
662 //wf->nFormatTag),GS_VOLATILE);
663 //
664 if (swichunk) free_swiRiff(swichunk);
665 FREE((char *)cb);
666 return ESR_FATAL_ERROR;
667 }
668
669
670
671 /* Reads RIFF format WAVE files and returns:
672 * waveform: allocated with size num_bytes
673 * audio_type is a constant string (not allocated)
674 * If swichunk==NULL, does not look for swi-specific chunk,
675 * Returns ESR_FATAL_ERROR if num_channels != 1
676 * If and only if ESR_SUCCESS, caller must free waveform, and swichunk contents (if any)
677 */
readRiff2Buf(FILE * f,void ** waveform,unsigned int * num_bytes,const wchar_t ** audio_type,SwiRiffStruct * swichunk)678 ESR_ReturnCode readRiff2Buf(FILE *f, void **waveform, unsigned int *num_bytes,
679 const wchar_t **audio_type, SwiRiffStruct *swichunk)
680 {
681 ChunkContext chunk, parent;
682 WaveFormat *wf = NULL;
683 ESR_ReturnCode rc = ESR_SUCCESS;
684 int doSwap = ! isLittleEndian();
685 *waveform = NULL;
686
687 *audio_type = NULL; /* for error recovery higher up */
688
689 if (swichunk)
690 { /* for error recovery */
691 swichunk->segs.num_tuples = 0;
692 swichunk->kvals.num_pairs = 0;
693 }
694
695 /* find the WAVE chunk */
696 strncpy(parent.tag, "WAVE", 4);
697 if (riffDescend(f, &parent, NULL, FIND_RIFF, doSwap) != ESR_SUCCESS)
698 {
699 return ESR_FATAL_ERROR;
700 }
701
702 /* Wave format */
703 strncpy(chunk.tag, "fmt ", 4);
704 if (riffDescend(f, &chunk, &parent, FIND_CHUNK, doSwap) != ESR_SUCCESS)
705 {
706 return ESR_FATAL_ERROR;
707 }
708 if (chunk.length < sizeof(WaveFormat))
709 wf = MALLOC(sizeof(WaveFormat), MTAG);
710 else
711 wf = MALLOC(chunk.length, MTAG);
712
713 if (fread(wf, 1, chunk.length, f) != (size_t)chunk.length)
714 {
715 FREE((char *)wf);
716 return ESR_FATAL_ERROR;
717 }
718 if (doSwap) swapWaveFormat(wf);
719
720 if (wf->nChannels != 1)
721 {
722 FREE((char *)wf);
723 return ESR_FATAL_ERROR;
724 }
725 if (doSwap)
726 {
727 swapShort(&wf->nBlockAlign); /* usually == blockAlign / nChannels */
728 swapInt(&wf->nSamplesPerSec);
729 swapShort(&wf->nFormatTag);
730 }
731
732 /* data chunk */
733 if (riffAscend(f, &chunk) != ESR_SUCCESS)
734 {
735 rc = ESR_FATAL_ERROR;
736 goto cleanup;
737 }
738
739 strncpy(chunk.tag, "data", 4);
740 if (riffDescend(f, &chunk, &parent, FIND_CHUNK, doSwap) != ESR_SUCCESS)
741 {
742 rc = ESR_FATAL_ERROR;
743 goto cleanup;
744 }
745
746 *num_bytes = chunk.length; /* already swapped, if need be */
747 *waveform = CALLOC(chunk.length, 1, MTAG);
748 if (fread(*waveform, 1, chunk.length, f) != (size_t)chunk.length)
749 {
750 rc = ESR_FATAL_ERROR;
751 goto cleanup;
752 }
753 if (doSwap)
754 {
755 if (wf->nBlockAlign == 2)
756 short_byte_swap((short *)*waveform, chunk.length);
757 else if (wf->nBlockAlign == 4)
758 int_byte_swap((int *)*waveform, chunk.length);
759 }
760
761 if (swichunk)
762 {
763 rc = readSwiChunk(f, &parent, swichunk, doSwap);
764 goto cleanup;
765 }
766
767 *audio_type = NULL;
768
769 /* assuming nchannels = 1, usually bytes_per_sample==blockAlign / nchannels (not aurora!) */
770 if (wf->nFormatTag == WAVEFORMAT_PCM)
771 {
772 if (wf->nBlockAlign == 2)
773 {/* can only be L16 */
774 if (wf->nSamplesPerSec == 8000)
775 *audio_type = L"audio/L16;rate=8000";
776 else if (wf->nSamplesPerSec == 16000)
777 *audio_type = L"audio/L16;rate=16000";
778 }
779 }
780 else if (wf->nFormatTag == WAVEFORMAT_ALAW)
781 {
782 if (wf->nSamplesPerSec == 8000)
783 *audio_type = L"audio/x-alaw-basic;rate=8000";
784 }
785 else if (wf->nFormatTag == WAVEFORMAT_MULAW)
786 {
787 if (wf->nSamplesPerSec == 8000)
788 {
789 if (swichunk)
790 {
791 char *encoding = getSwiRiffKVal(swichunk, "orig-encoding");
792 if (!encoding)
793 *audio_type = L"audio/basic;rate=8000";
794 else if (! strcmp(encoding, "g723"))
795 *audio_type = L"audio/basic;rate=8000;orig-encoding=g723";
796 else if (! strcmp(encoding, "g729"))
797 *audio_type = L"audio/basic;rate=8000;orig-encoding=g729";
798 else
799 {
800 // FIXME: warning because unknown orig-encoding??
801 // rec_test will never get here cuz already checked validity of audiotype
802 // but to be careful pour l'avenir, should handle this
803 *audio_type = L"audio/basic;rate=8000";
804 }
805 }
806 else
807 *audio_type = L"audio/basic;rate=8000";
808 }
809 else if (wf->nSamplesPerSec == 16000)
810 *audio_type = L"audio/basic;rate=16000";
811
812 }
813 else if (wf->nFormatTag == WAVEFORMAT_AURORA)
814 {
815 if (wf->nSamplesPerSec == 8000)
816 *audio_type = L"application/x-feature;rate=8000;encoding=swifeature_aurora";
817 else if (wf->nSamplesPerSec == 11000)
818 *audio_type = L"application/x-feature;rate=11000;encoding=swifeature_aurora";
819 else if (wf->nSamplesPerSec == 16000)
820 *audio_type = L"application/x-feature;rate=16000;encoding=swifeature_aurora";
821 }
822 else if (wf->nFormatTag == WAVEFORMAT_ES_202_050)
823 {
824 if (wf->nSamplesPerSec == 8000)
825 *audio_type = L"application/x-feature;rate=8000;encoding=ES_202_050";
826 else if (wf->nSamplesPerSec == 11000)
827 *audio_type = L"application/x-feature;rate=11000;encoding=ES_202_050";
828 else if (wf->nSamplesPerSec == 16000)
829 *audio_type = L"application/x-feature;rate=16000;encoding=ES_202_050";
830 }
831
832 if (*audio_type == NULL)
833 {
834 rc = ESR_FATAL_ERROR;
835 goto cleanup;
836 }
837
838 cleanup:
839 if (wf) FREE((char *)wf);
840 if (rc != ESR_SUCCESS)
841 {
842 if (swichunk)
843 free_swiRiff(swichunk);
844 if (*waveform)
845 {
846 FREE((char *)*waveform);
847 *waveform = NULL;
848 }
849 }
850 return rc;
851 }
852
getFormatTag(wchar_t * audio_type)853 static int getFormatTag(wchar_t *audio_type)
854 {
855 if (!wcsncmp(audio_type, L"audio/basic", 11))
856 {
857 return WAVEFORMAT_MULAW;
858 }
859 if (!wcsncmp(audio_type, L"application/x-feature;", 14) &&
860 wcsstr(audio_type, L"encoding=swifeature_aurora"))
861 {
862 return WAVEFORMAT_AURORA;
863 }
864 else if (!wcsncmp(audio_type, L"application/x-feature;", 14) &&
865 wcsstr(audio_type, L"encoding=ES_202_050"))
866 {
867 return WAVEFORMAT_ES_202_050;
868 }
869 else if (!wcsncmp(audio_type, L"audio/x-alaw-basic", 18))
870 {
871 return WAVEFORMAT_ALAW;
872 }
873 else if (!wcsncmp(audio_type, L"audio/L16", 9))
874 {
875 return WAVEFORMAT_PCM;
876 }
877 return -1;
878 }
879
880 /* we are assuming that riffaudio->num_tuples!=0, and hence riffaudio->tuples!=NULL
881 */
writeSwiAudioChunk(int doSwap,int chunk_len,SwiRiffAudio * riffaudio,unsigned char * workbuf)882 static unsigned char *writeSwiAudioChunk(int doSwap, int chunk_len, SwiRiffAudio *riffaudio,
883 unsigned char *workbuf)
884 {
885 ChunkInfoStruct ck;
886 int chunkinfosize = sizeof(ChunkInfoStruct);
887
888 strncpy(ck.ckString, "segs", 4);
889 ck.ckLength = chunk_len;
890 if (doSwap)
891 {
892 swapInt(&ck.ckLength);
893 memcpy(workbuf, &ck, chunkinfosize);
894 workbuf += chunkinfosize;
895
896 memcpy(workbuf, &riffaudio->num_tuples, sizeof(int));
897 workbuf += sizeof(int);
898 chunk_len -= sizeof(int);
899
900 memcpy(workbuf, riffaudio->tuples, chunk_len);
901 int_byte_swap((int *)workbuf, riffaudio->num_tuples*3 + 1);
902 /* count every tuple (3) + num_tuples itself */
903 return workbuf + chunk_len;
904 }
905 else
906 {
907 memcpy(workbuf, &ck, chunkinfosize);
908 workbuf += chunkinfosize;
909 memcpy(workbuf, &riffaudio->num_tuples, sizeof(int));
910 workbuf += sizeof(int);
911 chunk_len -= sizeof(int);
912
913 memcpy(workbuf, riffaudio->tuples, chunk_len);
914 return workbuf + chunk_len;
915 }
916 }
917
918 /* WARNING: returns with file pointer past the 4 first chars
919 *
920 * If the first 4 bytes of the specified file are "RIFF",
921 * then we assume it's a RIFF file
922 */
isRiffFile(FILE * fp)923 int isRiffFile(FILE *fp)
924 {
925 char tmpbuf[4];
926 fseek(fp, 0, SEEK_SET);
927 fread(tmpbuf, 4, sizeof(char), fp);
928 return !strncmp(tmpbuf, "RIFF", 4);
929
930 }
931
932 /*
933 * WARNING: assuming num_channels = 1
934 * INPUT: waveform, num_bytes (waveform length), audio_type,
935 * swichunk (it returns unmodified, including not swapped)
936 * OUTPUT: buf (entire riff chunk) and buflen
937 *
938 * AURORA special case:
939 * sampling rate = bytes_per_sample = -1; other fields of WaveFormat undefined
940 */
convertBuf2Riff(unsigned char * waveform,unsigned int num_bytes,wchar_t * audio_type,int rate,int bytes_per_sample,SwiRiffStruct * swichunk,unsigned char ** buf,unsigned int * buflen)941 ESR_ReturnCode convertBuf2Riff(
942 unsigned char *waveform,
943 unsigned int num_bytes,
944 wchar_t *audio_type,
945 int rate,
946 int bytes_per_sample,
947 SwiRiffStruct *swichunk,
948 unsigned char **buf,
949 unsigned int *buflen)
950 {
951 unsigned int total_buflen;
952 unsigned char *ptr, *workbuf;
953 short num_channels = 1;
954 int num_samples;
955 int bytes_sec;
956 short block_align;
957 int doSwap;
958 ChunkInfoStruct ck;
959 RiffHeaderStruct header;
960 int headerSize = sizeof(RiffHeaderStruct);
961 int chunkInfoSize = sizeof(ChunkInfoStruct);
962 int listChunkSize = 0;
963 int segs_chunk_size, kvals_chunk_size;
964 short format_tag = (short) getFormatTag(audio_type);
965
966 if (format_tag == -1 ||
967 (bytes_per_sample == -1 && format_tag != WAVEFORMAT_AURORA &&
968 format_tag != WAVEFORMAT_ES_202_050))
969 {
970 PLogError(L("audio type not supported for RIFF conversion"));
971 return ESR_FATAL_ERROR;
972
973 }
974 if (bytes_per_sample > 0)
975 num_samples = num_bytes / bytes_per_sample;
976 else
977 num_samples = num_bytes;
978
979 strncpy(header.riffString, "RIFF", 4);
980 strncpy(header.waveString, "WAVE", 4);
981 strncpy(header.fmtString, "fmt ", 4);
982 strncpy(header.dataString, "data", 4);
983
984 total_buflen = headerSize + num_bytes;
985
986 if (swichunk->segs.num_tuples || swichunk->kvals.num_pairs)
987 {
988 listChunkSize = chunkInfoSize /* LIST chunk info */ + 4 * sizeof(char); /* "swi " */
989 if (swichunk->segs.num_tuples)
990 {
991 segs_chunk_size = sizeof(int) + (swichunk->segs.num_tuples) * sizeof(RiffAudioTuple);
992 listChunkSize += chunkInfoSize + segs_chunk_size;
993 }
994 if (swichunk->kvals.num_pairs)
995 {
996 int i;
997 kvals_chunk_size = 0;
998 for (i = 0; i < swichunk->kvals.num_pairs; i++)
999 {
1000 kvals_chunk_size += (strlen(swichunk->kvals.kvpairs[i].key) + 1
1001 + strlen(swichunk->kvals.kvpairs[i].value) + 1) * sizeof(char);
1002 }
1003 kvals_chunk_size += sizeof(int); /* num_pairs */
1004 listChunkSize += chunkInfoSize + kvals_chunk_size;
1005 }
1006 total_buflen += listChunkSize;
1007 }
1008 if (total_buflen > *buflen)
1009 {
1010 PLogError(L("ESR_BUFFER_OVERFLOW"));
1011 return ESR_BUFFER_OVERFLOW;
1012 }
1013 workbuf = *buf;
1014
1015 *buflen = total_buflen;
1016 ptr = workbuf;
1017 if (format_tag == WAVEFORMAT_AURORA || format_tag == WAVEFORMAT_ES_202_050)
1018 {
1019 bytes_sec = AURORA_BYTES_SEC;
1020 block_align = 4;
1021 }
1022 else
1023 {
1024 bytes_sec = (short)(rate * num_channels * bytes_per_sample);
1025 block_align = bytes_per_sample * num_channels;
1026 }
1027 doSwap = !isLittleEndian();
1028 if (doSwap)
1029 {
1030 header.riffChunkLength = swapConstInt(*buflen - chunkInfoSize);
1031 header.fmtChunkLength = swapConstInt(sizeof(WaveFormat));
1032 header.waveinfo.nFormatTag = swapConstShort(format_tag); /* codec */
1033 header.waveinfo.nChannels = swapConstShort(num_channels);
1034 header.waveinfo.nSamplesPerSec = swapConstInt(rate);
1035 header.waveinfo.nAvgBytesPerSec = swapConstInt(bytes_sec);
1036 header.waveinfo.nBlockAlign = swapConstShort(block_align);
1037 header.waveinfo.wBitsPerSample = swapConstShort((short)((bytes_sec * 8) / rate));
1038 header.dataLength = swapConstInt(num_bytes);
1039 memcpy(ptr, &header, headerSize);
1040
1041 memcpy(ptr + headerSize, waveform, header.dataLength);
1042 if (bytes_per_sample == 2)
1043 short_byte_swap((short *)(ptr + headerSize), num_samples);
1044 }
1045 else
1046 {
1047 header.riffChunkLength = total_buflen - chunkInfoSize;
1048 header.fmtChunkLength = sizeof(WaveFormat);
1049 header.waveinfo.nFormatTag = format_tag; /* codec */
1050 header.waveinfo.nChannels = num_channels;
1051 header.waveinfo.nSamplesPerSec = rate;
1052 header.waveinfo.nAvgBytesPerSec = bytes_sec;
1053 header.waveinfo.nBlockAlign = (short) block_align;
1054 header.waveinfo.wBitsPerSample = (bytes_sec * 8) / rate;
1055 header.dataLength = num_bytes;
1056
1057 memcpy(ptr, &header, headerSize);
1058 memcpy(ptr + headerSize, waveform, header.dataLength);
1059 }
1060 ptr += headerSize + header.dataLength;
1061
1062 if (swichunk->segs.num_tuples || swichunk->kvals.num_pairs)
1063 {
1064 strncpy(ck.ckString, "LIST", 4);
1065 ck.ckLength = listChunkSize - chunkInfoSize;
1066 if (doSwap) swapInt(&ck.ckLength);
1067 memcpy(ptr, &ck, chunkInfoSize); /* copy LIST */
1068 ptr += chunkInfoSize;
1069
1070 strncpy((char *)ptr, "swi ", 4);
1071 ptr += 4;
1072
1073 if (swichunk->segs.num_tuples)
1074 {
1075 ptr = writeSwiAudioChunk(doSwap, segs_chunk_size, &swichunk->segs, ptr);
1076 }
1077 if (swichunk->kvals.num_pairs)
1078 {
1079 int i, num_pairs;
1080 RiffKVPair *pairs;
1081
1082 strncpy(ck.ckString, "kvs ", 4);
1083 ck.ckLength = kvals_chunk_size; /* num_pairs and pairs themselves */
1084 if (doSwap) swapInt(&ck.ckLength);
1085 memcpy(ptr, &ck, chunkInfoSize);
1086 ptr += chunkInfoSize;
1087
1088 num_pairs = (doSwap) ? swapConstInt(swichunk->kvals.num_pairs) : swichunk->kvals.num_pairs;
1089 memcpy(ptr, &num_pairs, sizeof(int));
1090 ptr += sizeof(int);
1091
1092 for (pairs = swichunk->kvals.kvpairs, i = 0; i < num_pairs; i++, pairs++)
1093 {
1094 strcpy((char *)ptr, pairs->key);
1095 ptr += strlen(pairs->key) + 1;
1096
1097 strcpy((char *)ptr, pairs->value);
1098 ptr += strlen(pairs->value) + 1;
1099 }
1100 }
1101 }
1102 passert((unsigned int)(ptr - workbuf) == *buflen);
1103
1104 return ESR_SUCCESS;
1105 }
1106
1107
1108