1
2/* -----------------------------------------------------------------------------------------------------------
3Software License for The Fraunhofer FDK AAC Codec Library for Android
4
5� Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V.
6  All rights reserved.
7
8 1.    INTRODUCTION
9The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
12
13AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16of the MPEG specifications.
17
18Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20individually for the purpose of encoding or decoding bit streams in products that are compliant with
21the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23software may already be covered under those patent licenses when it is used for those licensed purposes only.
24
25Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27applications information and documentation.
28
292.    COPYRIGHT LICENSE
30
31Redistribution and use in source and binary forms, with or without modification, are permitted without
32payment of copyright license fees provided that you satisfy the following conditions:
33
34You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35your modifications thereto in source code form.
36
37You must retain the complete text of this software license in the documentation and/or other materials
38provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40modifications thereto to recipients of copies in binary form.
41
42The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43prior written permission.
44
45You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46software or your modifications thereto.
47
48Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49and the date of any change. For modified versions of the FDK AAC Codec, the term
50"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
51"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
52
533.    NO PATENT LICENSE
54
55NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57respect to this software.
58
59You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60by appropriate patent licenses.
61
624.    DISCLAIMER
63
64This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
65"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
66of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69or business interruption, however caused and on any theory of liability, whether in contract, strict
70liability, or tort (including negligence), arising in any way out of the use of this software, even if
71advised of the possibility of such damage.
72
735.    CONTACT INFORMATION
74
75Fraunhofer Institute for Integrated Circuits IIS
76Attention: Audio and Multimedia Departments - FDK AAC LL
77Am Wolfsmantel 33
7891058 Erlangen, Germany
79
80www.iis.fraunhofer.de/amm
81amm-info@iis.fraunhofer.de
82----------------------------------------------------------------------------------------------------------- */
83
84/**************************  Fraunhofer IIS FDK SysLib  **********************
85
86   Author(s):   Eric Allamanche
87   Description: a rudimentary wav file interface
88
89******************************************************************************/
90
91
92
93#include "wav_file.h"
94#include "genericStds.h"
95
96
97static INT_PCM ulaw2pcm (UCHAR ulawbyte);
98
99/*!
100 *
101 *  \brief Read header from a WAVEfile. Host endianess is handled accordingly.
102 *  \wav->fp filepointer of type FILE*.
103 *  \wavinfo SWavInfo struct where the decoded header info is stored into.
104 *  \return 0 on success and non-zero on failure.
105 *
106 */
107INT WAV_InputOpen (HANDLE_WAV *pWav, const char *filename)
108{
109    HANDLE_WAV wav = (HANDLE_WAV)FDKcalloc(1, sizeof(struct WAV));
110    INT offset;
111
112    if (wav == NULL) {
113      FDKprintfErr("WAV_InputOpen(): Unable to allocate WAV struct.\n");
114      goto error;
115    }
116
117    wav->fp = FDKfopen(filename, "rb");
118    if (wav->fp == NULL) {
119      FDKprintfErr("WAV_InputOpen(): Unable to open wav file. %s\n", filename);
120      goto error;
121    }
122
123    /* read RIFF-chunk */
124    if (FDKfread(&(wav->header.riffType), 1, 4, wav->fp) != 4) {
125      FDKprintfErr("WAV_InputOpen(): couldn't read RIFF_ID\n");
126      goto error;  /* bad error "couldn't read RIFF_ID" */
127    }
128    if (FDKstrncmp("RIFF", wav->header.riffType, 4)) {
129      FDKprintfErr("WAV_InputOpen(): RIFF descriptor not found.\n") ;
130      goto error;
131    }
132
133    /* Read RIFF size. Ignored. */
134    FDKfread_EL(&(wav->header.riffSize), 4, 1, wav->fp);
135
136    /* read WAVE-chunk */
137    if (FDKfread(&wav->header.waveType, 1, 4, wav->fp) !=4) {
138      FDKprintfErr("WAV_InputOpen(): couldn't read format\n");
139      goto error;  /* bad error "couldn't read format" */
140    }
141    if (FDKstrncmp("WAVE", wav->header.waveType, 4)) {
142      FDKprintfErr("WAV_InputOpen(): WAVE chunk ID not found.\n") ;
143      goto error;
144    }
145
146    /* read format-chunk */
147    if (FDKfread(&(wav->header.formatType), 1, 4, wav->fp) != 4) {
148      FDKprintfErr("WAV_InputOpen(): couldn't read format_ID\n");
149      goto error;  /* bad error "couldn't read format_ID" */
150    }
151    if (FDKstrncmp("fmt", wav->header.formatType, 3)) {
152      FDKprintfErr("WAV_InputOpen(): fmt chunk format not found.\n") ;
153     goto error;
154    }
155
156
157    FDKfread_EL(&wav->header.formatSize, 4, 1, wav->fp);   /* should be 16 for PCM-format (uncompressed) */
158
159
160    /* read  info */
161    FDKfread_EL(&(wav->header.compressionCode), 2, 1, wav->fp);
162    FDKfread_EL(&(wav->header.numChannels), 2, 1, wav->fp);
163    FDKfread_EL(&(wav->header.sampleRate), 4, 1, wav->fp);
164    FDKfread_EL(&(wav->header.bytesPerSecond), 4, 1, wav->fp);
165    FDKfread_EL(&(wav->header.blockAlign), 2, 1, wav->fp);
166    FDKfread_EL(&(wav->header.bitsPerSample), 2, 1, wav->fp);
167
168    offset = wav->header.formatSize - 16;
169
170    /* Wave format extensible */
171    if (wav->header.compressionCode == 0xFFFE) {
172      static const UCHAR guidPCM[16] = {
173          0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
174          0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
175      };
176      USHORT extraFormatBytes, validBitsPerSample;
177      UCHAR guid[16];
178      INT i;
179
180      /* read extra bytes */
181      FDKfread_EL(&(extraFormatBytes), 2, 1, wav->fp);
182      offset -= 2;
183
184      if (extraFormatBytes >= 22) {
185        FDKfread_EL(&(validBitsPerSample), 2, 1, wav->fp);
186        FDKfread_EL(&(wav->channelMask), 4, 1, wav->fp);
187        FDKfread_EL(&(guid), 16, 1, wav->fp);
188
189        /* check for PCM GUID */
190        for (i = 0; i < 16; i++) if (guid[i] != guidPCM[i]) break;
191        if (i == 16) wav->header.compressionCode = 0x01;
192
193        offset -= 22;
194      }
195    }
196
197    /* Skip rest of fmt header if any. */
198    for (;offset > 0; offset--) {
199      FDKfread(&wav->header.formatSize, 1, 1, wav->fp);
200    }
201
202    do {
203      /* Read data chunk ID */
204      if (FDKfread(wav->header.dataType, 1, 4, wav->fp) != 4) {
205        FDKprintfErr("WAV_InputOpen(): Unable to read data chunk ID.\n");
206        FDKfree(wav);
207        goto error;
208      }
209
210      /* Read chunk length. */
211      FDKfread_EL(&offset, 4, 1, wav->fp);
212
213      /* Check for data chunk signature. */
214      if (FDKstrncmp("data", wav->header.dataType, 4) == 0) {
215        wav->header.dataSize = offset;
216        break;
217      }
218      /* Jump over non data chunk. */
219      for (;offset > 0; offset--) {
220        FDKfread(&(wav->header.dataSize), 1, 1, wav->fp);
221      }
222    } while (!FDKfeof(wav->fp));
223
224    /* return success */
225    *pWav = wav;
226    return 0;
227
228    /* Error path */
229error:
230
231    if (wav) {
232      if (wav->fp) {
233        FDKfclose(wav->fp);
234        wav->fp = NULL;
235      }
236      FDKfree(wav);
237    }
238
239    *pWav = NULL;
240
241    return -1;
242}
243
244/*!
245 *
246 *  \brief Read samples from a WAVEfile. The samples are automatically reorder to the native
247 *    host endianess and scaled to full scale of the INT_PCM type, from whatever bps the WAVEfile
248 *    had specified in its haader data.
249 *
250 *  \wav HANDLE_WAV of the wav file.
251 *  \buffer Pointer to store read data.
252 *  \numSamples Desired number of samples to read.
253 *  \nBits sample size in bits to be used for the buffer
254 *
255 *  \return Number of samples actually read.
256 *
257 */
258
259INT WAV_InputRead (HANDLE_WAV wav, void *buffer, UINT numSamples, int nBits)
260{
261  UINT result = 0 ;
262  UINT i;
263  SCHAR *bptr = (SCHAR*)buffer;
264  LONG  *lptr = (LONG*)buffer;
265  SHORT *sptr = (SHORT*)buffer;
266
267  switch (wav->header.compressionCode)
268  {
269    case 0x01:  /* PCM uncompressed */
270      if (nBits == wav->header.bitsPerSample) {
271        result = FDKfread_EL(buffer, wav->header.bitsPerSample >> 3, numSamples, wav->fp) ;
272      } else {
273        result = 0;
274        for (i=0; i<numSamples; i++)
275        {
276          LONG tmp = 0;
277          result += FDKfread_EL(&tmp, wav->header.bitsPerSample >> 3, 1, wav->fp) ;
278
279          /* Move read bits to lower bits of LONG. */
280          if ( !IS_LITTLE_ENDIAN() && wav->header.bitsPerSample != 24 && wav->header.bitsPerSample < 32) {
281            tmp >>= (32-wav->header.bitsPerSample);
282          }
283
284          /* Full scale */
285          if (wav->header.bitsPerSample > nBits)
286            tmp >>= (wav->header.bitsPerSample-nBits);
287          else
288            tmp <<= (nBits-wav->header.bitsPerSample);
289
290          if (nBits == 8)
291            *bptr++ = (SCHAR) tmp;
292          if (nBits == 16)
293            *sptr++ = (SHORT) tmp;
294          if (nBits == 32)
295            *lptr++ = (LONG) tmp;
296        }
297      }
298      break;
299
300    case 0x07:  /* u-Law compression */
301      for (i=0; i<numSamples; i++) {
302        result += FDKfread(&(bptr[i<<1]), 1, 1, wav->fp) ;
303        sptr[i] = ulaw2pcm(bptr[i<<1]) ;
304      }
305      break ;
306
307    default:
308      FDKprintf("WAV_InputRead(): unsupported data-compression!!") ;
309      break ;
310  }
311  return result ;
312}
313
314void WAV_InputClose(HANDLE_WAV *pWav)
315{
316  HANDLE_WAV wav = *pWav;
317
318  if (wav != NULL) {
319    if (wav->fp != NULL) {
320       FDKfclose(wav->fp);
321       wav->fp = NULL;
322    }
323    if (wav) {
324       FDKfree(wav);
325    }
326  }
327  *pWav = NULL;
328}
329
330/* conversion of u-law to linear coding */
331static INT_PCM ulaw2pcm (UCHAR ulawbyte)
332{
333  static const INT exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 } ;
334  INT sign, exponent, mantissa, sample ;
335
336  ulawbyte = (UCHAR)~ulawbyte ;
337  sign = (ulawbyte & 0x80) ;
338  exponent = (ulawbyte >> 4) & 0x07 ;
339  mantissa = ulawbyte & 0x0F ;
340
341  sample = exp_lut[exponent] + (mantissa << (exponent + 3)) ;
342  if (sign != 0)
343    sample = -sample ;
344
345  return (INT_PCM)sample ;
346}
347
348/************** Writer ***********************/
349
350static UINT LittleEndian32(UINT v)
351{
352    if (IS_LITTLE_ENDIAN())
353        return v ;
354    else
355        return (v & 0x000000FF) << 24 | (v & 0x0000FF00) <<  8 | (v & 0x00FF0000) >>  8 | (v & 0xFF000000) >> 24;
356}
357
358static SHORT LittleEndian16(SHORT v)
359{
360    if (IS_LITTLE_ENDIAN())
361        return v;
362    else
363        return (SHORT)(((v << 8) & 0xFF00) | ((v >> 8) & 0x00FF));
364}
365
366static USHORT Unpack(USHORT v)
367{
368    if (IS_LITTLE_ENDIAN())
369      return v;
370    else
371      return (SHORT)(((v << 8) & 0xFF00) | ((v >> 8) & 0x00FF));
372}
373
374/**
375 * WAV_OutputOpen
376 * \brief Open WAV output/writer handle
377 * \param pWav pointer to WAV handle to be returned
378 * \param sampleRate desired samplerate of the resulting WAV file
379 * \param numChannels desired number of audio channels of the resulting WAV file
380 * \param bitsPerSample desired number of bits per audio sample of the resulting WAV file
381 *
382 * \return value:   0: ok
383 *                 -1: error
384 */
385INT WAV_OutputOpen(HANDLE_WAV *pWav, const char *outputFilename, INT sampleRate, INT numChannels, INT bitsPerSample)
386{
387  HANDLE_WAV wav = (HANDLE_WAV)FDKcalloc(1, sizeof(struct WAV));
388  UINT size = 0;
389
390  if (wav == NULL) {
391    FDKprintfErr("WAV_OutputOpen(): Unable to allocate WAV struct.\n");
392    goto bail;
393  }
394
395  if (bitsPerSample != 16 && bitsPerSample != 24 && bitsPerSample != 32)
396  {
397      FDKprintfErr("WAV_OutputOpen(): Invalid argument (bitsPerSample).\n");
398      goto bail;
399  }
400
401  wav->fp = FDKfopen(outputFilename, "wb");
402  if (wav->fp == NULL)
403  {
404      FDKprintfErr("WAV_OutputOpen(): unable to create file %s\n", outputFilename);
405      goto bail;
406  }
407
408  FDKstrcpy(wav->header.riffType, "RIFF");
409  wav->header.riffSize = LittleEndian32(0x7fffffff);  /* in case fseek() doesn't work later in WAV_OutputClose() */
410  FDKstrcpy(wav->header.waveType, "WAVE");
411
412  FDKstrcpy(wav->header.formatType, "fmt ");
413  wav->header.formatSize = LittleEndian32(16);
414
415  wav->header.compressionCode = LittleEndian16(0x01);
416  wav->header.bitsPerSample   = LittleEndian16((SHORT)bitsPerSample);
417  wav->header.numChannels     = LittleEndian16((SHORT)numChannels);
418  wav->header.blockAlign      = LittleEndian16((SHORT)(numChannels * (bitsPerSample >> 3)));
419  wav->header.sampleRate      = LittleEndian32(sampleRate);
420  wav->header.bytesPerSecond  = LittleEndian32(sampleRate * wav->header.blockAlign);
421  FDKstrcpy(wav->header.dataType, "data");
422  wav->header.dataSize        = LittleEndian32(0x7fffffff - 36);
423
424
425  size = sizeof(WAV_HEADER);
426  if (FDKfwrite(&wav->header, 1, size, wav->fp) != size)
427  {
428      FDKprintfErr("WAV_OutputOpen(): error writing to output file %s\n", outputFilename);
429      goto bail;
430  }
431
432
433  wav->header.dataSize = wav->header.riffSize = 0;
434
435  *pWav = wav;
436
437  return 0;
438
439bail:
440  if (wav) {
441    if (wav->fp) {
442      FDKfclose(wav->fp);
443    }
444    FDKfree(wav);
445  }
446
447  pWav = NULL;
448
449  return -1;
450}
451
452
453/**
454 * WAV_OutputWrite
455 * \brief Write data to WAV file asociated to WAV handle
456 *
457 * \param wav handle of wave file
458 * \param sampleBuffer pointer to audio samples, right justified integer values
459 * \param nBufBits size in bits of each audio sample in sampleBuffer
460 * \param nSigBits amount of significant bits of each nBufBits in sampleBuffer
461 *
462 * \return value:    0: ok
463 *                  -1: error
464 */
465INT WAV_OutputWrite(HANDLE_WAV wav, void *sampleBuffer, UINT numberOfSamples, int nBufBits, int nSigBits)
466{
467    SCHAR *bptr = (SCHAR*)sampleBuffer;
468    SHORT *sptr = (SHORT*)sampleBuffer;
469    LONG  *lptr = (LONG*)sampleBuffer;
470    LONG tmp;
471
472    int bps = Unpack(wav->header.bitsPerSample);
473    UINT i;
474
475    /* Pack samples if required */
476    if (bps == nBufBits && bps == nSigBits) {
477      if (FDKfwrite_EL(sampleBuffer, (bps>>3), numberOfSamples, wav->fp) != numberOfSamples)
478      {
479        FDKprintfErr("WAV_OutputWrite(): error: unable to write to file %d\n", wav->fp);
480        return -1;
481      }
482    } else  {
483      for (i=0; i<numberOfSamples; i++)
484      {
485        int result;
486        int shift;
487
488        switch (nBufBits) {
489          case 8:  tmp = *bptr++; break;
490          case 16: tmp = *sptr++; break;
491          case 32: tmp = *lptr++; break;
492          default: return -1;
493        }
494        /* Adapt sample size */
495        shift = (nBufBits-nSigBits)-(32-bps);
496
497        /* Correct alignment difference between 32 bit data buffer "tmp" and 24 bits to be written. */
498        if ( !IS_LITTLE_ENDIAN() && bps == 24) {
499          shift += 8;
500        }
501
502        if (shift < 0)
503          tmp >>= -shift;
504        else
505          tmp <<= shift;
506
507        /* Write sample */
508        result=FDKfwrite_EL(&tmp, bps>>3, 1, wav->fp);
509        if (result <= 0) {
510          FDKprintfErr("WAV_OutputWrite(): error: unable to write to file %d\n", wav->fp);
511          return -1;
512        }
513      }
514    }
515
516    wav->header.dataSize += (numberOfSamples * (bps>>3));
517    return 0;
518}
519
520
521/**
522 * WAV_OutputClose
523 * \brief Close WAV Output handle
524 * \param pWav pointer to WAV handle. *pWav is set to NULL.
525 */
526void WAV_OutputClose(HANDLE_WAV *pWav)
527{
528  HANDLE_WAV wav = *pWav;
529  UINT size = 0;
530
531  if ( wav == NULL ) {
532      return;
533  }
534
535  wav->header.dataSize = LittleEndian32(wav->header.dataSize);
536  wav->header.riffSize = LittleEndian32(wav->header.dataSize + 36);
537
538  if (wav->fp != NULL)
539  {
540    if (FDKfseek(wav->fp, 0, FDKSEEK_SET)) {
541       FDKprintf("WAV_OutputClose(): fseek() failed.\n");
542    }
543
544  size = sizeof(WAV_HEADER);
545    if (FDKfwrite(&wav->header.riffType, 1, size, wav->fp) != size)
546    {
547        FDKprintfErr("WAV_OutputClose(): unable to write header\n");
548	}
549
550    if (FDKfclose(wav->fp))
551    {
552        FDKprintfErr("WAV_OutputClose(): unable to close wav file\n");
553    }
554    wav->fp = NULL;
555  }
556
557  FDKfree(wav);
558  *pWav = NULL;
559}
560
561