14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*---------------------------------------------------------------------------*
24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  riff.c  *
34a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
44a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
54a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
64a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the 'License');          *
74a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  you may not use this file except in compliance with the License.         *
84a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
94a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  You may obtain a copy of the License at                                  *
104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0                           *
114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software      *
134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  distributed under the License is distributed on an 'AS IS' BASIS,        *
144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  See the License for the specific language governing permissions and      *
164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  limitations under the License.                                           *
174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *---------------------------------------------------------------------------*/
194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "plog.h"
214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "riff.h"
224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define MTAG NULL
244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttypedef struct ChunkContext_t
264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char tag[4];
284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  long  start;
294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int  length;
304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectChunkContext;
324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttypedef enum
344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FIND_RIFF,
364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FIND_CHUNK,
374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FIND_LIST
384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} DescendType;
394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint isLittleEndian()
414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char b[4];
434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *(int *)b = 1;
454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return (int)b[0];
464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* waveReadFunc
494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * - converts data to an array of signed shorts
504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * - fills in *length with the number of samples converted
514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * - allocates memory for *samples
524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * - returns GS_OK if conversion was successful or GS_ERROR and an error
534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *    message in res if not.  If the conversion fails the function must free
544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *    all the memory it had allocated before returning.
554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * On entry
564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  wf   - points to the WaveFormat structure that describes the data format
574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  cb   - data read from the RIFF file
584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  data - descriptor for the "data" chunk
594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttypedef ESR_ReturnCode(waveReadFunc)(WaveFormat *wf, ChunkContext *data,
614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                     char *cb, short **samples, int *length, int doSwap);
624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic ESR_ReturnCode readPCMWave(WaveFormat *wf, ChunkContext *data,
644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                  char *cb, short **samples, int *length, int doSwap);
654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic ESR_ReturnCode readMulawWave(WaveFormat *wf, ChunkContext *data,
664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                    char *cb, short **samples, int *length, int doSwap);
674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic ESR_ReturnCode readAlawWave(WaveFormat *wf, ChunkContext *data,
684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                   char *cb, short **samples, int *length, int doSwap);
694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic struct
714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int id;
734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  waveReadFunc *func;
744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectWaveCodecs[] = {
764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                 {WAVEFORMAT_PCM, readPCMWave},
774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                 {WAVEFORMAT_MULAW, readMulawWave},
784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                 {WAVEFORMAT_ALAW, readAlawWave},
794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                 {0, 0},
804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project               };
814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/************* FIXME: regroup all swap routines outahere;
834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                    ditto for audio conversion routines
844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic void swapInt(int *i)
874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char *a = (char *)i, t;
894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  t = a[0];
904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  a[0] = a[3];
914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  a[3] = t;
924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  t = a[1];
934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  a[1] = a[2];
944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  a[2] = t;
954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic void swapShort(short *s)
984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char *a = (char *)s, t;
1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  t = a[0];
1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  a[0] = a[1];
1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  a[1] = t;
1034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int swapConstInt(const int value)
1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int converted = value;
1084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  unsigned char *cp = (unsigned char *) & converted;
1094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *cp ^= *(cp + 3);
1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *(cp + 3) ^= *cp;
1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *cp ^= *(cp + 3);
1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *(cp + 1) ^= *(cp + 2);
1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *(cp + 2) ^= *(cp + 1);
1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *(cp + 1) ^= *(cp + 2);
1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return converted;
1184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic short swapConstShort(const short value)
1214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  short converted = value;
1234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  unsigned char *cp = (unsigned char *) & converted;
1244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  unsigned char tmp = *cp;
1254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *cp = *(cp + 1);
1274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *++cp = tmp;
1284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return converted;
1304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* len == number of bytes to swap
1334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
1344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic void short_byte_swap(short *buf, int len)
1354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char *cp, *end, tmp;
1374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  end = ((char *)buf) + (len << 1);
1394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (cp = (char *)buf; cp < end; cp++)
1404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
1414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    tmp = *cp;
1424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    *cp = *(cp + 1);
1434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    *++cp = tmp;
1444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* len == number of bytes to swap
1484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
1494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic void int_byte_swap(int *buf, int len)
1504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char *cp, *end;
1524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  end = ((char *)buf) + (len << 2);
1544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (cp = (char *)buf; cp < end; cp += 4)
1554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
1564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    *cp ^= *(cp + 3);
1574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    *(cp + 3) ^= *cp;
1584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    *cp ^= *(cp + 3);
1594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    *(cp + 1) ^= *(cp + 2);
1604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    *(cp + 2) ^= *(cp + 1);
1614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    *(cp + 1) ^= *(cp + 2);
1624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic void swapWaveFormat(WaveFormat *wf)
1664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  swapShort(&wf->nFormatTag);
1684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  swapShort(&wf->nChannels);
1694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  swapInt(&wf->nSamplesPerSec);
1704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  swapInt(&wf->nAvgBytesPerSec);
1714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  swapShort(&wf->nBlockAlign);
1724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  swapShort(&wf->wBitsPerSample);
1734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  //swapShort(&wf->cbSize);
1744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int ulaw2linear(unsigned char ulawbyte)
1774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static int exp_lut[8] =
1794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
1804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      0, 132, 396, 924, 1980, 4092, 8316, 16764
1814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    };
1824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int sign, exponent, mantissa, sample;
1834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ulawbyte = ~ulawbyte;
1854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  sign = (ulawbyte & 0x80);
1864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  exponent = (ulawbyte >> 4) & 0x07;
1874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  mantissa = ulawbyte & 0x0F;
1884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  sample = exp_lut[exponent] + (mantissa << (exponent + 3));
1894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (sign != 0) sample = -sample;
1904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return sample;
1914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int alaw2linear(unsigned char alawbyte)
1944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int sign, achord, astep, delta, sample;
1974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  unsigned char alawcode;
1984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  static int exp_lut[8] =
1994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
2004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      1, 1, 2, 4, 8, 16, 32, 64
2014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    };
2024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  alawcode = alawbyte ^ 0x55;
2034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  sign = (alawcode & 0x80);
2044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  achord = (alawcode >> 4) & 0x07;
2054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  astep = alawcode & 0x0F;
2064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  delta = ((achord == 0) ? 1 : 0);
2074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  sample = ((2 * astep + 33) * exp_lut[achord]) - 32 * delta;
2084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (sign != 0) sample = -sample;
2094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  sample = sample * 8;
2104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return sample;
2124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* Converts PCM wave data
2154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  cb: input :1
2164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
2184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic ESR_ReturnCode readPCMWave(WaveFormat *wf, ChunkContext *data,
2194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                  char *cb, short **samples, int *length, int doSwap)
2204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
2214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i;
2224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (wf->nChannels != 1)
2234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_SetResult(res,"PCM WAVE file contains more than one data channel",
2254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_STATIC);
2264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
2274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (wf->wBitsPerSample != 16 && wf->wBitsPerSample != 8)
2294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_SetResult(res,GS_Spf(0,"%d bits per sample PCM format not supported",
2314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //wf->wBitsPerSample),GS_VOLATILE);
2324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
2334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *length = data->length * 8 / wf->wBitsPerSample;
2354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *samples = MALLOC(*length * sizeof(short), MTAG);
2364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (wf->wBitsPerSample == 16)
2374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(*samples, cb, *length*sizeof(short));
2394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (doSwap)
2404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      for (i = 0;i < *length;i++) swapShort(*samples + i);
2414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
2434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (i = 0;i < *length;i++)(*samples)[i] = (short)((unsigned)(cb[i]) - 128) << 8;
2454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ESR_SUCCESS;
2474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* Converts CCITT u-law wave data
2504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
2514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic ESR_ReturnCode readMulawWave(WaveFormat *wf, ChunkContext *data,
2524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                    char *cb, short **samples, int *length, int doSwap)
2534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
2544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i;
2554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (wf->nChannels != 1)
2564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_SetResult(res,"u-law WAVE file contains more than one data channel",
2584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_STATIC);
2594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
2604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (wf->wBitsPerSample != 8)
2624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_SetResult(res,GS_Spf(0,"%d bits per sample u-law format not supported",
2644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //wf->wBitsPerSample),GS_VOLATILE);
2654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
2664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *length = data->length;
2684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *samples = MALLOC(*length * sizeof(short), MTAG);
2694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = 0;i < *length;i++)
2704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    (*samples)[i] = (short) ulaw2linear(cb[i]);
2714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ESR_SUCCESS;
2724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* Converts a-law wave data
2754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
2764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic ESR_ReturnCode readAlawWave(WaveFormat *wf, ChunkContext *data,
2774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                   char *cb, short **samples, int *length, int doSwap)
2784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
2794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i;
2804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (wf->nChannels != 1)
2814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_SetResult(res,"u-law WAVE file contains more than one data channel",
2834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_STATIC);
2844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
2854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (wf->wBitsPerSample != 8)
2874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_SetResult(res,GS_Spf(0,"%d bits per sample u-law format not supported",
2894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //wf->wBitsPerSample),GS_VOLATILE);
2904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
2914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *length = data->length;
2934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  samples = MALLOC(*length * sizeof(short), MTAG);
2944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = 0;i < *length;i++)(*samples)[i] = alaw2linear(cb[i]);
2954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ESR_SUCCESS;
2964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* ------------------------------------------------------------------------- */
2994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* RIFF INTERFACE UTILS  */
3014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid free_swiRiff(SwiRiffStruct *swichunk)
3034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
3044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (swichunk->segs.num_tuples)
3054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
3064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    FREE(swichunk->segs.tuples);
3074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    swichunk->segs.num_tuples = 0;
3084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (swichunk->kvals.num_pairs)
3104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
3114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    FREE(swichunk->kvals.kvpairs[0].key);
3124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    FREE(swichunk->kvals.kvpairs);
3134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    swichunk->kvals.num_pairs = 0;
3144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectchar *getSwiRiffKVal(SwiRiffStruct *swichunk, char *key)
3184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
3194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i;
3204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = 0; i < swichunk->kvals.num_pairs; i++)
3224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (! strcmp(swichunk->kvals.kvpairs[i].key, key))
3234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return swichunk->kvals.kvpairs[i].value;
3244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return NULL;
3264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* ------------------------------------------------------------------------- */
3294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int riffDescend(FILE *f, ChunkContext *c, ChunkContext *parent, DescendType t, int doSwap)
3314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
3324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char form[4], tag[4];
3334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int len;
3344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  long start, end;
3354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  end = 0;
3374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (!parent) start = 0;
3384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
3394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
3404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    start = parent->start;
3414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    end = start + parent->length;
3424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (fseek(f, start, SEEK_SET) < 0)
3444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
3454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_SetResult(res,"seek failed",GS_STATIC);
3464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
3474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  switch (t)
3504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
3514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    case FIND_RIFF:
3534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      while (1)
3544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
3554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (fread(form, 1, 4, f) != 4) break;
3564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (fread(&len, sizeof(int), 1, f) != 1)
3574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          return ESR_FATAL_ERROR;
3584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (doSwap)
3594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          swapInt(&len);
3604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (strncmp(form, "RIFF", 4))
3614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {  /* skip this non-RIFF chunk */
3624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (fseek(f, (long)len, SEEK_CUR) < 0) break;
3634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          start += len + 8;
3644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (end && start >= end)
3654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          {
3664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            //GS_SetResult(res,"RIFF form type not found",GS_STATIC);
3674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            return ESR_FATAL_ERROR;
3684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
3694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          continue;
3704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
3714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (fread(tag, 1, 4, f) != 4) break;
3724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (!strncmp(tag, c->tag, 4))
3734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
3744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          c->start = start + 12;
3754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          c->length = len - 4;
3764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          return ESR_SUCCESS;
3774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
3784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
3794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      //if(feof(f)) GS_SetResult(res,"RIFF form type not found",GS_STATIC);
3804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      //else GS_SetResult(res,"Corrupt RIFF file",GS_STATIC);
3814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return ESR_FATAL_ERROR;
3824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    case FIND_CHUNK:
3844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      while (1)
3854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
3864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (fread(tag, 1, 4, f) != 4) break;
3874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (fread(&len, sizeof(int), 1, f) != 1)
3884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          return ESR_FATAL_ERROR;
3894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (doSwap)
3904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          swapInt(&len);
3914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (!strncmp(tag, c->tag, 4))
3924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
3934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          c->start = start + 8;
3944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          c->length = len;
3954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          return ESR_SUCCESS;
3964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
3974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (fseek(f, (long)len, SEEK_CUR) < 0) break;
3984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        start += len + 8;
3994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (end && start >= end)
4004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
4014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          //GS_SetResult(res,"RIFF chunk not found",GS_STATIC);
4024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          return ESR_FATAL_ERROR;
4034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
4044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
4054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      //if(feof(f)) GS_SetResult(res,"RIFF chunk not found",GS_STATIC);
4064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      //else GS_SetResult(res,"corrupt RIFF file",GS_STATIC);
4074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return ESR_FATAL_ERROR;
4084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    case FIND_LIST:
4104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      while (1)
4114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
4124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (fread(form, 1, 4, f) != 4) break;
4134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (fread(&len, sizeof(int), 1, f) != 1)
4144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          return ESR_FATAL_ERROR;
4154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (doSwap)
4164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          swapInt(&len);
4174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (strncmp(form, "LIST", 4))
4184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {  /* skip this non-LIST chunk */
4194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (fseek(f, (long)len, SEEK_CUR) < 0) break;
4204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          start += len + 8;
4214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (end && start >= end)
4224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          {
4234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            //GS_SetResult(res,"RIFF form type not found",GS_STATIC);
4244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            return ESR_FATAL_ERROR;
4254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          }
4264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          continue;
4274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
4284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (fread(tag, 1, 4, f) != 4) break;
4294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (!strncmp(tag, c->tag, 4))
4304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
4314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          c->start = start + 12;
4324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          c->length = len - 4;
4334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          return ESR_SUCCESS;
4344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
4354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
4364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      //if(feof(f)) GS_SetResult(res,"RIFF form type not found",GS_STATIC);
4384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      //else GS_SetResult(res,"Corrupt RIFF file",GS_STATIC);
4394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return ESR_FATAL_ERROR;
4404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  //GS_AppendResult(res,"bad search flag",GS_STATIC);
4434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ESR_FATAL_ERROR;
4444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
4454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int riffAscend(FILE *f, ChunkContext *c)
4474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
4484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (fseek(f, c->start + c->length, SEEK_SET) < 0)
4494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
4504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_SetResult(res,"seek failed",GS_STATIC);
4514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
4524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ESR_SUCCESS;
4544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
4554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic ESR_ReturnCode readSwiChunk(FILE *f,  ChunkContext *parent, SwiRiffStruct *swichunk, int doSwap)
4584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
4594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ESR_ReturnCode rc = ESR_SUCCESS;
4604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ChunkContext chunk, list_chunk;
4614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int sub_length;
4624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  swichunk->segs.num_tuples = 0;
4634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  swichunk->kvals.num_pairs = 0;
4644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strncpy(chunk.tag, "swi ", 4);
4664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (riffDescend(f, &chunk, parent, FIND_LIST, doSwap) == ESR_SUCCESS)
4674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
4684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* is it as "swi " list? */
4694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    strncpy(list_chunk.tag, "segs", 4);
4704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (riffDescend(f, &list_chunk, &chunk, FIND_CHUNK, doSwap) == ESR_SUCCESS)
4714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
4724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      fread(&swichunk->segs.num_tuples, 1, sizeof(int), f);
4734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (doSwap) swapInt(&swichunk->segs.num_tuples);
4744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      sub_length = list_chunk.length - sizeof(int);
4764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (sub_length)
4774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
4784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        swichunk->segs.tuples = MALLOC(sub_length, MTAG);
4794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (!swichunk->segs.tuples)
4804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
4814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          swichunk->segs.num_tuples = 0;  /* so that the free routine will work */
4824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          rc = ESR_OUT_OF_MEMORY;
4834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
4844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        else if (fread(swichunk->segs.tuples, 1, sub_length, f) != (size_t)sub_length)
4854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
4864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          rc = ESR_FATAL_ERROR;
4874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
4884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (rc != ESR_SUCCESS)
4894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          goto swichunk_cleanup;
4904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
4924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else
4934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        swichunk->segs.tuples = NULL;
4944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
4954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    strncpy(list_chunk.tag, "kvs ", 4);
4964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* start searching from after "swi" */
4974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (riffDescend(f, &list_chunk, &chunk, FIND_CHUNK, doSwap) == ESR_SUCCESS)
4984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
4994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      int i, num_pairs;
5004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      fread(&num_pairs, 1, sizeof(int), f);
5024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (doSwap) swapInt(&num_pairs);
5034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      swichunk->kvals.num_pairs = num_pairs;
5044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      sub_length = list_chunk.length - sizeof(int);
5064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (sub_length)
5074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
5084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        char *kvpair_buf = NULL;
5094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        RiffKVPair *pairs;
5104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        swichunk->kvals.kvpairs = (RiffKVPair *)CALLOC(num_pairs, sizeof(RiffKVPair), MTAG);
5124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        kvpair_buf = CALLOC(sub_length, sizeof(char), MTAG);
5134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (!swichunk->kvals.kvpairs || !kvpair_buf)
5144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
5154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (kvpair_buf) FREE(kvpair_buf);
5164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          if (swichunk->kvals.kvpairs) FREE(swichunk->kvals.kvpairs);
5174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          swichunk->kvals.num_pairs = 0;
5184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          rc = ESR_OUT_OF_MEMORY;
5194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          goto swichunk_cleanup;
5204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
5214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        swichunk->kvals.kvpairs[0].key = kvpair_buf;
5234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (fread(kvpair_buf, 1, sub_length, f) != (size_t)sub_length)
5244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
5254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          rc = ESR_FATAL_ERROR;
5264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          goto swichunk_cleanup;
5274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
5284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        for (pairs = swichunk->kvals.kvpairs, i = 0; i < swichunk->kvals.num_pairs; i++, pairs++)
5294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
5304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          pairs->key = kvpair_buf;
5314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          kvpair_buf +=  strlen(kvpair_buf) + 1;
5324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          pairs->value = kvpair_buf;
5334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          kvpair_buf +=  strlen(kvpair_buf) + 1;
5344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
5354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
5364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else
5374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        swichunk->kvals.kvpairs = NULL;
5384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
5394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* no matter what was found or not found, return with the file pointer in
5414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project   * the state that it was upon entering this function */
5424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (riffAscend(f, parent) != ESR_SUCCESS)
5434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
5444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rc = ESR_FATAL_ERROR;
5454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    goto swichunk_cleanup;
5464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectswichunk_cleanup:
5494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (rc == ESR_FATAL_ERROR) free_swiRiff(swichunk);
5504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return rc;
5514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
5524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* Reads RIFF format WAVE files
5554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
5564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectESR_ReturnCode riffReadWave2L16(FILE *f, double from, double to,
5574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                short **samples, int *rate, int *length, SwiRiffStruct *swichunk)
5584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
5594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ChunkContext chunk, parent;
5604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  WaveFormat *wf;
5614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char *cb;
5624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ESR_ReturnCode rc;
5634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i, ifrom, ito;
5644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int doSwap = ! isLittleEndian();
5654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* find the WAVE chunk */
5674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strncpy(parent.tag, "WAVE", 4);
5684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (riffDescend(f, &parent, NULL, FIND_RIFF, doSwap) != ESR_SUCCESS)
5694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
5704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_AppendResult(res,"\nnot a RIFF waveform audio file",NULL);
5714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
5724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* Wave format */
5754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strncpy(chunk.tag, "fmt ", 4);
5764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (riffDescend(f, &chunk, &parent, FIND_CHUNK, doSwap) != ESR_SUCCESS)
5774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
5784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_AppendResult(res,"\nwaveform audio file has no \"fmt \" chunk.",NULL);
5794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
5804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (chunk.length < sizeof(WaveFormat))
5824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    wf = MALLOC(sizeof(WaveFormat), MTAG);
5834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
5844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    wf = MALLOC(chunk.length, MTAG);
5854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (fread(wf, 1, chunk.length, f) != (size_t)chunk.length)
5874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
5884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    FREE((char *)wf);
5894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_SetResult(res,"fmt chunk read failed.",GS_STATIC);
5904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
5914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
5924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (doSwap) swapWaveFormat(wf);
5934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *rate = wf->nSamplesPerSec;
5944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
5954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* data chunk */
5964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (riffAscend(f, &chunk) != ESR_SUCCESS)
5974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
5984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
5994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strncpy(chunk.tag, "data", 4);
6014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (riffDescend(f, &chunk, &parent, FIND_CHUNK, doSwap) != ESR_SUCCESS)
6024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
6034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_AppendResult(res,"\nwaveform audio file has no \"data\" chunk.",NULL);
6044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
6054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  cb = MALLOC(chunk.length, MTAG); /* waveform */
6074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (fread(cb, 1, chunk.length, f) != (size_t)chunk.length)
6084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
6094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    FREE((char *)wf);
6104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    FREE((char *)cb);
6114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    //GS_SetResult(res,"truncated \"data\" chunk",GS_STATIC);
6124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
6134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (swichunk)
6164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
6174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rc = readSwiChunk(f, &parent, swichunk, doSwap);
6184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (rc != ESR_SUCCESS)
6194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
6204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      FREE((char *)wf);
6214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      FREE((char *)cb);
6224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return rc;
6234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
6244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = 0;WaveCodecs[i].func;i++)
6274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (wf->nFormatTag == WaveCodecs[i].id)
6294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
6304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      rc = (WaveCodecs[i].func)(wf, &chunk, cb, samples, length, doSwap);
6314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      FREE((char *)wf);
6324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      FREE((char *)cb);
6334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (rc != ESR_SUCCESS)
6344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
6354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (swichunk) free_swiRiff(swichunk);
6364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return rc;
6374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
6384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /* handle 'from' and 'to' - this isn't very efficient, but
6394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       * saves all the format conversion routines the trouble of doing so
6404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       */
6414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (from == 0 && to == -1) return ESR_SUCCESS;
6424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (from > 0)
6434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ifrom = (int)(from * (*rate) / 1000.0);
6444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else
6454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ifrom = 0;
6464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (to >= 0)
6484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
6494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ito = (int)(to * (*rate) / 1000.0 + 0.5);
6504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (ito > *length)
6514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          ito = *length;
6524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
6534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else
6544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ito = *length;
6554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *length = ito - ifrom;
6574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (ifrom > 0) memmove(*samples, (*samples) + ifrom, (*length)*sizeof(short));
6584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return ESR_SUCCESS;
6594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
6604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  //GS_SetResult(res,GS_Spf(0,"WAVE format (id 0x%x) not supported",
6624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  //wf->nFormatTag),GS_VOLATILE);
6634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  //
6644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (swichunk) free_swiRiff(swichunk);
6654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FREE((char *)cb);
6664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ESR_FATAL_ERROR;
6674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
6684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* Reads RIFF format WAVE files and returns:
6724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *   waveform: allocated with size num_bytes
6734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *   audio_type is a constant string (not allocated)
6744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * If swichunk==NULL, does not look for swi-specific chunk,
6754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * Returns ESR_FATAL_ERROR if num_channels != 1
6764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * If and only if ESR_SUCCESS, caller must free waveform, and swichunk contents (if any)
6774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
6784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectESR_ReturnCode readRiff2Buf(FILE *f, void **waveform, unsigned int *num_bytes,
6794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                            const wchar_t **audio_type, SwiRiffStruct *swichunk)
6804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
6814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ChunkContext chunk, parent;
6824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  WaveFormat *wf = NULL;
6834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ESR_ReturnCode rc = ESR_SUCCESS;
6844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int doSwap = ! isLittleEndian();
6854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *waveform = NULL;
6864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *audio_type = NULL;  /* for error recovery higher up */
6884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (swichunk)
6904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  { /* for error recovery */
6914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    swichunk->segs.num_tuples = 0;
6924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    swichunk->kvals.num_pairs = 0;
6934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
6944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
6954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* find the WAVE chunk */
6964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strncpy(parent.tag, "WAVE", 4);
6974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (riffDescend(f, &parent, NULL, FIND_RIFF, doSwap) != ESR_SUCCESS)
6984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
6994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
7004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* Wave format */
7034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strncpy(chunk.tag, "fmt ", 4);
7044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (riffDescend(f, &chunk, &parent, FIND_CHUNK, doSwap) != ESR_SUCCESS)
7054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
7074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (chunk.length < sizeof(WaveFormat))
7094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    wf = MALLOC(sizeof(WaveFormat), MTAG);
7104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
7114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    wf = MALLOC(chunk.length, MTAG);
7124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (fread(wf, 1, chunk.length, f) != (size_t)chunk.length)
7144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    FREE((char *)wf);
7164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
7174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (doSwap) swapWaveFormat(wf);
7194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (wf->nChannels != 1)
7214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    FREE((char *)wf);
7234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
7244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (doSwap)
7264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    swapShort(&wf->nBlockAlign);  /* usually == blockAlign / nChannels */
7284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    swapInt(&wf->nSamplesPerSec);
7294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    swapShort(&wf->nFormatTag);
7304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* data chunk */
7334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (riffAscend(f, &chunk) != ESR_SUCCESS)
7344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rc = ESR_FATAL_ERROR;
7364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    goto cleanup;
7374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strncpy(chunk.tag, "data", 4);
7404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (riffDescend(f, &chunk, &parent, FIND_CHUNK, doSwap) != ESR_SUCCESS)
7414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rc =  ESR_FATAL_ERROR;
7434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    goto cleanup;
7444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *num_bytes = chunk.length;  /* already swapped, if need be */
7474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *waveform = CALLOC(chunk.length, 1, MTAG);
7484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (fread(*waveform, 1, chunk.length, f) != (size_t)chunk.length)
7494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rc = ESR_FATAL_ERROR;
7514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    goto cleanup;
7524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (doSwap)
7544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (wf->nBlockAlign == 2)
7564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      short_byte_swap((short *)*waveform, chunk.length);
7574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if (wf->nBlockAlign == 4)
7584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      int_byte_swap((int *)*waveform, chunk.length);
7594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (swichunk)
7624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rc = readSwiChunk(f, &parent, swichunk, doSwap);
7644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    goto cleanup;
7654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *audio_type = NULL;
7684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
7694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* assuming nchannels = 1, usually bytes_per_sample==blockAlign / nchannels (not aurora!) */
7704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (wf->nFormatTag == WAVEFORMAT_PCM)
7714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (wf->nBlockAlign == 2)
7734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {/* can only be L16 */
7744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (wf->nSamplesPerSec == 8000)
7754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        *audio_type = L"audio/L16;rate=8000";
7764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else if (wf->nSamplesPerSec == 16000)
7774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        *audio_type = L"audio/L16;rate=16000";
7784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
7794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (wf->nFormatTag == WAVEFORMAT_ALAW)
7814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (wf->nSamplesPerSec == 8000)
7834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *audio_type = L"audio/x-alaw-basic;rate=8000";
7844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
7854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (wf->nFormatTag == WAVEFORMAT_MULAW)
7864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
7874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (wf->nSamplesPerSec == 8000)
7884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
7894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (swichunk)
7904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
7914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        char *encoding = getSwiRiffKVal(swichunk, "orig-encoding");
7924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        if (!encoding)
7934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          *audio_type = L"audio/basic;rate=8000";
7944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        else  if (! strcmp(encoding, "g723"))
7954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          *audio_type = L"audio/basic;rate=8000;orig-encoding=g723";
7964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        else if (! strcmp(encoding, "g729"))
7974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          *audio_type = L"audio/basic;rate=8000;orig-encoding=g729";
7984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        else
7994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        {
8004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          // FIXME: warning because unknown orig-encoding??
8014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          // rec_test will never get here cuz already checked validity of audiotype
8024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          // but to be careful pour l'avenir, should handle this
8034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          *audio_type = L"audio/basic;rate=8000";
8044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        }
8054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
8064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else
8074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        *audio_type = L"audio/basic;rate=8000";
8084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
8094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if (wf->nSamplesPerSec == 16000)
8104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *audio_type = L"audio/basic;rate=16000";
8114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (wf->nFormatTag == WAVEFORMAT_AURORA)
8144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
8154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (wf->nSamplesPerSec == 8000)
8164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *audio_type = L"application/x-feature;rate=8000;encoding=swifeature_aurora";
8174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if (wf->nSamplesPerSec == 11000)
8184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *audio_type = L"application/x-feature;rate=11000;encoding=swifeature_aurora";
8194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if (wf->nSamplesPerSec == 16000)
8204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *audio_type = L"application/x-feature;rate=16000;encoding=swifeature_aurora";
8214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (wf->nFormatTag == WAVEFORMAT_ES_202_050)
8234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
8244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (wf->nSamplesPerSec == 8000)
8254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *audio_type = L"application/x-feature;rate=8000;encoding=ES_202_050";
8264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if (wf->nSamplesPerSec == 11000)
8274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *audio_type = L"application/x-feature;rate=11000;encoding=ES_202_050";
8284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else if (wf->nSamplesPerSec == 16000)
8294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *audio_type = L"application/x-feature;rate=16000;encoding=ES_202_050";
8304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (*audio_type == NULL)
8334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
8344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    rc = ESR_FATAL_ERROR;
8354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    goto cleanup;
8364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectcleanup:
8394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (wf) FREE((char *)wf);
8404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (rc != ESR_SUCCESS)
8414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
8424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (swichunk)
8434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      free_swiRiff(swichunk);
8444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (*waveform)
8454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
8464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      FREE((char *)*waveform);
8474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      *waveform = NULL;
8484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
8494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return rc;
8514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
8524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int getFormatTag(wchar_t *audio_type)
8544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
8554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (!wcsncmp(audio_type, L"audio/basic", 11))
8564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
8574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return WAVEFORMAT_MULAW;
8584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (!wcsncmp(audio_type, L"application/x-feature;", 14) &&
8604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      wcsstr(audio_type, L"encoding=swifeature_aurora"))
8614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
8624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return WAVEFORMAT_AURORA;
8634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (!wcsncmp(audio_type, L"application/x-feature;", 14) &&
8654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project           wcsstr(audio_type, L"encoding=ES_202_050"))
8664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
8674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return WAVEFORMAT_ES_202_050;
8684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (!wcsncmp(audio_type, L"audio/x-alaw-basic", 18))
8704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
8714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return WAVEFORMAT_ALAW;
8724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else if (!wcsncmp(audio_type, L"audio/L16", 9))
8744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
8754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return WAVEFORMAT_PCM;
8764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
8774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return -1;
8784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
8794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* we are assuming that riffaudio->num_tuples!=0, and hence riffaudio->tuples!=NULL
8814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
8824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic unsigned char *writeSwiAudioChunk(int doSwap, int chunk_len, SwiRiffAudio *riffaudio,
8834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    unsigned char *workbuf)
8844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
8854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ChunkInfoStruct ck;
8864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int chunkinfosize = sizeof(ChunkInfoStruct);
8874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strncpy(ck.ckString, "segs", 4);
8894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ck.ckLength = chunk_len;
8904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (doSwap)
8914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
8924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    swapInt(&ck.ckLength);
8934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(workbuf, &ck, chunkinfosize);
8944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    workbuf += chunkinfosize;
8954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
8964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(workbuf, &riffaudio->num_tuples, sizeof(int));
8974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    workbuf += sizeof(int);
8984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    chunk_len -= sizeof(int);
8994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(workbuf, riffaudio->tuples, chunk_len);
9014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    int_byte_swap((int *)workbuf, riffaudio->num_tuples*3 + 1);
9024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* count every tuple (3) + num_tuples itself */
9034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return workbuf + chunk_len;
9044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
9054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
9064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
9074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(workbuf, &ck, chunkinfosize);
9084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    workbuf += chunkinfosize;
9094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(workbuf, &riffaudio->num_tuples, sizeof(int));
9104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    workbuf += sizeof(int);
9114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    chunk_len -= sizeof(int);
9124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(workbuf, riffaudio->tuples, chunk_len);
9144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return workbuf + chunk_len;
9154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
9164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
9174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* WARNING:  returns with file pointer past the 4 first chars
9194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *
9204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * If the first 4 bytes of the specified file are "RIFF",
9214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * then we assume it's a RIFF file
9224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
9234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint isRiffFile(FILE *fp)
9244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
9254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  char tmpbuf[4];
9264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fseek(fp, 0, SEEK_SET);
9274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fread(tmpbuf, 4, sizeof(char), fp);
9284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return !strncmp(tmpbuf, "RIFF", 4);
9294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
9314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*
9334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * WARNING: assuming num_channels = 1
9344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * INPUT: waveform, num_bytes (waveform length), audio_type,
9354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *        swichunk (it returns unmodified, including not swapped)
9364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * OUTPUT: buf (entire riff chunk) and buflen
9374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *
9384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * AURORA special case:
9394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *   sampling rate = bytes_per_sample = -1; other fields of WaveFormat undefined
9404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
9414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectESR_ReturnCode convertBuf2Riff(
9424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  unsigned char *waveform,
9434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  unsigned int num_bytes,
9444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wchar_t *audio_type,
9454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int rate,
9464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int bytes_per_sample,
9474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  SwiRiffStruct *swichunk,
9484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  unsigned char **buf,
9494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  unsigned int *buflen)
9504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
9514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  unsigned int total_buflen;
9524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  unsigned char *ptr, *workbuf;
9534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  short num_channels = 1;
9544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int num_samples;
9554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int bytes_sec;
9564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  short block_align;
9574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int doSwap;
9584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ChunkInfoStruct ck;
9594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  RiffHeaderStruct header;
9604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int headerSize = sizeof(RiffHeaderStruct);
9614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int chunkInfoSize = sizeof(ChunkInfoStruct);
9624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int listChunkSize = 0;
9634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int segs_chunk_size, kvals_chunk_size;
9644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  short format_tag = (short) getFormatTag(audio_type);
9654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (format_tag == -1 ||
9674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      (bytes_per_sample == -1 && format_tag != WAVEFORMAT_AURORA &&
9684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       format_tag != WAVEFORMAT_ES_202_050))
9694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
9704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    PLogError(L("audio type not supported for RIFF conversion"));
9714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_FATAL_ERROR;
9724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
9744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (bytes_per_sample > 0)
9754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    num_samples = num_bytes / bytes_per_sample;
9764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
9774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    num_samples = num_bytes;
9784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strncpy(header.riffString, "RIFF", 4);
9804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strncpy(header.waveString, "WAVE", 4);
9814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strncpy(header.fmtString, "fmt ", 4);
9824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  strncpy(header.dataString, "data", 4);
9834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  total_buflen = headerSize + num_bytes;
9854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
9864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (swichunk->segs.num_tuples || swichunk->kvals.num_pairs)
9874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
9884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    listChunkSize = chunkInfoSize  /* LIST chunk info */ + 4 * sizeof(char);  /* "swi " */
9894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (swichunk->segs.num_tuples)
9904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
9914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      segs_chunk_size = sizeof(int) + (swichunk->segs.num_tuples) * sizeof(RiffAudioTuple);
9924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      listChunkSize += chunkInfoSize + segs_chunk_size;
9934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
9944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (swichunk->kvals.num_pairs)
9954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
9964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      int i;
9974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      kvals_chunk_size = 0;
9984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      for (i = 0; i < swichunk->kvals.num_pairs; i++)
9994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
10004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        kvals_chunk_size += (strlen(swichunk->kvals.kvpairs[i].key) + 1
10014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                             + strlen(swichunk->kvals.kvpairs[i].value) + 1) * sizeof(char);
10024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
10034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      kvals_chunk_size += sizeof(int);  /* num_pairs */
10044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      listChunkSize += chunkInfoSize + kvals_chunk_size;
10054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
10064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    total_buflen += listChunkSize;
10074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
10084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (total_buflen > *buflen)
10094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
10104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    PLogError(L("ESR_BUFFER_OVERFLOW"));
10114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_BUFFER_OVERFLOW;
10124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
10134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  workbuf = *buf;
10144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *buflen = total_buflen;
10164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ptr = workbuf;
10174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (format_tag == WAVEFORMAT_AURORA || format_tag == WAVEFORMAT_ES_202_050)
10184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
10194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    bytes_sec = AURORA_BYTES_SEC;
10204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    block_align = 4;
10214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
10224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
10234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
10244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    bytes_sec = (short)(rate * num_channels * bytes_per_sample);
10254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    block_align = bytes_per_sample * num_channels;
10264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
10274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  doSwap = !isLittleEndian();
10284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (doSwap)
10294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
10304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.riffChunkLength = swapConstInt(*buflen - chunkInfoSize);
10314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.fmtChunkLength = swapConstInt(sizeof(WaveFormat));
10324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.waveinfo.nFormatTag = swapConstShort(format_tag);  /* codec */
10334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.waveinfo.nChannels = swapConstShort(num_channels);
10344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.waveinfo.nSamplesPerSec = swapConstInt(rate);
10354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.waveinfo.nAvgBytesPerSec = swapConstInt(bytes_sec);
10364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.waveinfo.nBlockAlign = swapConstShort(block_align);
10374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.waveinfo.wBitsPerSample = swapConstShort((short)((bytes_sec * 8) / rate));
10384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.dataLength = swapConstInt(num_bytes);
10394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(ptr, &header, headerSize);
10404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(ptr + headerSize, waveform, header.dataLength);
10424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (bytes_per_sample == 2)
10434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      short_byte_swap((short *)(ptr + headerSize), num_samples);
10444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
10454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
10464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
10474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.riffChunkLength = total_buflen - chunkInfoSize;
10484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.fmtChunkLength = sizeof(WaveFormat);
10494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.waveinfo.nFormatTag = format_tag;  /* codec */
10504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.waveinfo.nChannels = num_channels;
10514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.waveinfo.nSamplesPerSec = rate;
10524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.waveinfo.nAvgBytesPerSec = bytes_sec;
10534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.waveinfo.nBlockAlign = (short) block_align;
10544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.waveinfo.wBitsPerSample = (bytes_sec * 8) / rate;
10554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    header.dataLength = num_bytes;
10564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(ptr, &header, headerSize);
10584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(ptr + headerSize, waveform, header.dataLength);
10594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
10604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ptr += headerSize + header.dataLength;
10614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (swichunk->segs.num_tuples || swichunk->kvals.num_pairs)
10634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
10644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    strncpy(ck.ckString, "LIST", 4);
10654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ck.ckLength = listChunkSize - chunkInfoSize;
10664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (doSwap) swapInt(&ck.ckLength);
10674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(ptr, &ck, chunkInfoSize);   /* copy LIST */
10684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ptr += chunkInfoSize;
10694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    strncpy((char *)ptr, "swi ", 4);
10714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ptr += 4;
10724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (swichunk->segs.num_tuples)
10744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
10754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ptr = writeSwiAudioChunk(doSwap, segs_chunk_size, &swichunk->segs, ptr);
10764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
10774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (swichunk->kvals.num_pairs)
10784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
10794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      int i, num_pairs;
10804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      RiffKVPair *pairs;
10814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      strncpy(ck.ckString, "kvs ", 4);
10834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ck.ckLength = kvals_chunk_size;   /* num_pairs and pairs themselves */
10844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (doSwap) swapInt(&ck.ckLength);
10854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      memcpy(ptr, &ck, chunkInfoSize);
10864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ptr += chunkInfoSize;
10874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      num_pairs = (doSwap) ? swapConstInt(swichunk->kvals.num_pairs) : swichunk->kvals.num_pairs;
10894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      memcpy(ptr, &num_pairs, sizeof(int));
10904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ptr += sizeof(int);
10914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      for (pairs = swichunk->kvals.kvpairs, i = 0; i < num_pairs; i++, pairs++)
10934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
10944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        strcpy((char *)ptr, pairs->key);
10954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ptr += strlen(pairs->key) + 1;
10964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
10974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        strcpy((char *)ptr, pairs->value);
10984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        ptr += strlen(pairs->value) + 1;
10994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
11004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
11014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
11024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  passert((unsigned int)(ptr - workbuf) == *buflen);
11034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ESR_SUCCESS;
11054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
11064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
11074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1108