• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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