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/*****************************  MPEG-4 AAC Decoder  **************************
85
86   Author(s):   Josef Hoepfl
87   Description: perceptual noise substitution tool
88
89******************************************************************************/
90
91#include "aacdec_pns.h"
92
93
94#include "aac_ram.h"
95#include "aac_rom.h"
96#include "channelinfo.h"
97#include "block.h"
98#include "FDK_bitstream.h"
99
100#include "genericStds.h"
101
102
103#define NOISE_OFFSET 90           /* cf. ISO 14496-3 p. 175 */
104
105/*!
106  \brief Reset InterChannel and PNS data
107
108  The function resets the InterChannel and PNS data
109*/
110void CPns_ResetData(
111    CPnsData *pPnsData,
112    CPnsInterChannelData *pPnsInterChannelData
113    )
114{
115  /* Assign pointer always, since pPnsData is not persistent data */
116  pPnsData->pPnsInterChannelData = pPnsInterChannelData;
117  pPnsData->PnsActive = 0;
118  pPnsData->CurrentEnergy = 0;
119
120  FDKmemclear(pPnsData->pnsUsed,(8*16)*sizeof(UCHAR));
121  FDKmemclear(pPnsInterChannelData->correlated,(8*16)*sizeof(UCHAR));
122}
123
124/*!
125  \brief Initialize PNS data
126
127  The function initializes the PNS data
128*/
129void CPns_InitPns(
130    CPnsData *pPnsData,
131    CPnsInterChannelData *pPnsInterChannelData,
132    INT* currentSeed, INT* randomSeed)
133{
134  /* save pointer to inter channel data */
135  pPnsData->pPnsInterChannelData = pPnsInterChannelData;
136
137  /* use pointer because seed has to be
138     same, left and right channel ! */
139  pPnsData->currentSeed = currentSeed;
140  pPnsData->randomSeed  = randomSeed;
141}
142
143/*!
144  \brief Indicates if PNS is used
145
146  The function returns a value indicating whether PNS is used or not
147  acordding to the noise energy
148
149  \return  PNS used
150*/
151int CPns_IsPnsUsed (const CPnsData *pPnsData,
152                    const int group,
153                    const int band)
154{
155  unsigned pns_band = group*16+band;
156
157  return pPnsData->pnsUsed[pns_band] & (UCHAR)1;
158}
159
160/*!
161  \brief Set correlation
162
163  The function activates the noise correlation between the channel pair
164*/
165void CPns_SetCorrelation(CPnsData *pPnsData,
166                         const int group,
167                         const int band,
168                         const int outofphase)
169{
170  CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData;
171  unsigned pns_band = group*16+band;
172
173  pInterChannelData->correlated[pns_band] = (outofphase) ? 3 : 1;
174}
175
176/*!
177  \brief Indicates if correlation is used
178
179  The function indicates if the noise correlation between the channel pair
180  is activated
181
182  \return  PNS is correlated
183*/
184static
185int CPns_IsCorrelated(const CPnsData *pPnsData,
186                      const int group,
187                      const int band)
188{
189  CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData;
190  unsigned pns_band = group*16+band;
191
192  return (pInterChannelData->correlated[pns_band] & 0x01) ? 1 : 0;
193}
194
195/*!
196  \brief Indicates if correlated out of phase mode is used.
197
198  The function indicates if the noise correlation between the channel pair
199  is activated in out-of-phase mode.
200
201  \return  PNS is out-of-phase
202*/
203static
204int CPns_IsOutOfPhase(const CPnsData *pPnsData,
205                      const int group,
206                      const int band)
207{
208  CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData;
209  unsigned pns_band = group*16+band;
210
211  return (pInterChannelData->correlated[pns_band] & 0x02) ? 1 : 0;
212}
213
214/*!
215  \brief Read PNS information
216
217  The function reads the PNS information from the bitstream
218*/
219void CPns_Read (CPnsData *pPnsData,
220                HANDLE_FDK_BITSTREAM bs,
221                const CodeBookDescription *hcb,
222                SHORT *pScaleFactor,
223                UCHAR global_gain,
224                int band,
225                int group /* = 0 */)
226{
227  int delta ;
228  UINT pns_band = group*16+band;
229
230  if (pPnsData->PnsActive) {
231    /* Next PNS band case */
232    delta = CBlock_DecodeHuffmanWord (bs, hcb) - 60;
233  } else {
234    /* First PNS band case */
235    int noiseStartValue = FDKreadBits(bs,9);
236
237    delta = noiseStartValue - 256 ;
238    pPnsData->PnsActive = 1;
239    pPnsData->CurrentEnergy = global_gain - NOISE_OFFSET;
240  }
241
242  pPnsData->CurrentEnergy += delta ;
243  pScaleFactor[pns_band] = pPnsData->CurrentEnergy;
244
245  pPnsData->pnsUsed[pns_band] = 1;
246}
247
248
249/**
250 * \brief Generate a vector of noise of given length. The noise values are
251 *        scaled in order to yield a noise energy of 1.0
252 * \param spec pointer to were the noise values will be written to.
253 * \param size amount of noise values to be generated.
254 * \param pRandomState pointer to the state of the random generator being used.
255 * \return exponent of generated noise vector.
256 */
257static int GenerateRandomVector (FIXP_DBL *RESTRICT spec,
258                                  int size,
259                                  int *pRandomState)
260{
261  int i, invNrg_e = 0, nrg_e = 0;
262  FIXP_DBL invNrg_m, nrg_m = FL2FXCONST_DBL(0.0f) ;
263  FIXP_DBL *RESTRICT ptr = spec;
264  int randomState = *pRandomState;
265
266#define GEN_NOISE_NRG_SCALE 7
267
268  /* Generate noise and calculate energy. */
269  for (i=0; i<size; i++)
270  {
271    randomState = (1664525L * randomState) + 1013904223L; // Numerical Recipes
272    nrg_m = fPow2AddDiv2(nrg_m, (FIXP_DBL)randomState>>GEN_NOISE_NRG_SCALE);
273    *ptr++ = (FIXP_DBL)randomState;
274  }
275  nrg_e = GEN_NOISE_NRG_SCALE*2 + 1;
276
277  /* weight noise with = 1 / sqrt_nrg; */
278  invNrg_m = invSqrtNorm2(nrg_m<<1, &invNrg_e);
279  invNrg_e += -((nrg_e-1)>>1);
280
281  for (i=size; i--; )
282  {
283    spec[i] = fMult(spec[i], invNrg_m);
284  }
285
286  /* Store random state */
287  *pRandomState = randomState;
288
289  return invNrg_e;
290}
291
292static void ScaleBand (FIXP_DBL *RESTRICT spec, int size, int scaleFactor, int specScale, int noise_e, int out_of_phase)
293{
294  int i, shift, sfExponent;
295  FIXP_DBL sfMatissa;
296
297  /* Get gain from scale factor value = 2^(scaleFactor * 0.25) */
298  sfMatissa = MantissaTable[scaleFactor & 0x03][0];
299  /* sfExponent = (scaleFactor >> 2) + ExponentTable[scaleFactor & 0x03][0]; */
300  /* Note:  ExponentTable[scaleFactor & 0x03][0] is always 1. */
301  sfExponent = (scaleFactor >> 2) + 1;
302
303  if (out_of_phase != 0) {
304    sfMatissa = -sfMatissa;
305  }
306
307  /* +1 because of fMultDiv2 below. */
308  shift = sfExponent - specScale + 1 + noise_e;
309
310  /* Apply gain to noise values */
311  if (shift>=0) {
312    shift = fixMin( shift, DFRACT_BITS-1 );
313    for (i = size ; i-- != 0; ) {
314      spec [i] = fMultDiv2 (spec [i], sfMatissa) << shift;
315    }
316  } else {
317    shift = fixMin( -shift, DFRACT_BITS-1 );
318    for (i = size ; i-- != 0; ) {
319      spec [i] = fMultDiv2 (spec [i], sfMatissa) >> shift;
320    }
321  }
322}
323
324
325/*!
326  \brief Apply PNS
327
328  The function applies PNS (i.e. it generates noise) on the bands
329  flagged as noisy bands
330
331*/
332void CPns_Apply (const CPnsData *pPnsData,
333                 const CIcsInfo *pIcsInfo,
334                 SPECTRAL_PTR pSpectrum,
335                 const SHORT    *pSpecScale,
336                 const SHORT    *pScaleFactor,
337                 const SamplingRateInfo *pSamplingRateInfo,
338                 const INT granuleLength,
339                 const int channel)
340{
341  if (pPnsData->PnsActive) {
342    const short *BandOffsets = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo);
343
344    int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(pIcsInfo);
345
346    for (int window = 0, group = 0; group < GetWindowGroups(pIcsInfo); group++) {
347      for (int groupwin = 0; groupwin < GetWindowGroupLength(pIcsInfo, group); groupwin++, window++) {
348        FIXP_DBL *spectrum = SPEC(pSpectrum, window, granuleLength);
349
350        for (int band = 0 ; band < ScaleFactorBandsTransmitted; band++) {
351          if (CPns_IsPnsUsed (pPnsData, group, band)) {
352            UINT pns_band = group*16+band;
353
354            int bandWidth = BandOffsets [band + 1] - BandOffsets [band] ;
355            int noise_e;
356
357            FDK_ASSERT(bandWidth >= 0);
358
359            if (channel > 0 && CPns_IsCorrelated(pPnsData, group, band))
360            {
361              noise_e = GenerateRandomVector (spectrum + BandOffsets [band], bandWidth,
362                                    &pPnsData->randomSeed [pns_band]) ;
363            }
364            else
365            {
366              pPnsData->randomSeed [pns_band] = *pPnsData->currentSeed ;
367
368              noise_e = GenerateRandomVector (spectrum + BandOffsets [band], bandWidth,
369                                    pPnsData->currentSeed) ;
370            }
371
372            int outOfPhase  = CPns_IsOutOfPhase (pPnsData, group, band);
373
374            ScaleBand (spectrum + BandOffsets [band], bandWidth,
375                       pScaleFactor[pns_band],
376                       pSpecScale[window], noise_e, outOfPhase) ;
377          }
378        }
379      }
380    }
381  }
382}
383