1 
2 /* -----------------------------------------------------------------------------------------------------------
3 Software 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
9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
12 
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16 of the MPEG specifications.
17 
18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
24 
25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27 applications information and documentation.
28 
29 2.    COPYRIGHT LICENSE
30 
31 Redistribution and use in source and binary forms, with or without modification, are permitted without
32 payment of copyright license fees provided that you satisfy the following conditions:
33 
34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35 your modifications thereto in source code form.
36 
37 You must retain the complete text of this software license in the documentation and/or other materials
38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40 modifications thereto to recipients of copies in binary form.
41 
42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43 prior written permission.
44 
45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46 software or your modifications thereto.
47 
48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49 and 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 
53 3.    NO PATENT LICENSE
54 
55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57 respect to this software.
58 
59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60 by appropriate patent licenses.
61 
62 4.    DISCLAIMER
63 
64 This 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
66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69 or business interruption, however caused and on any theory of liability, whether in contract, strict
70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
71 advised of the possibility of such damage.
72 
73 5.    CONTACT INFORMATION
74 
75 Fraunhofer Institute for Integrated Circuits IIS
76 Attention: Audio and Multimedia Departments - FDK AAC LL
77 Am Wolfsmantel 33
78 91058 Erlangen, Germany
79 
80 www.iis.fraunhofer.de/amm
81 amm-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 */
CPns_ResetData(CPnsData * pPnsData,CPnsInterChannelData * pPnsInterChannelData)110 void 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 */
CPns_InitPns(CPnsData * pPnsData,CPnsInterChannelData * pPnsInterChannelData,INT * currentSeed,INT * randomSeed)129 void 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 */
CPns_IsPnsUsed(const CPnsData * pPnsData,const int group,const int band)151 int 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 */
CPns_SetCorrelation(CPnsData * pPnsData,const int group,const int band,const int outofphase)165 void 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 */
184 static
CPns_IsCorrelated(const CPnsData * pPnsData,const int group,const int band)185 int 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 */
203 static
CPns_IsOutOfPhase(const CPnsData * pPnsData,const int group,const int band)204 int 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 */
CPns_Read(CPnsData * pPnsData,HANDLE_FDK_BITSTREAM bs,const CodeBookDescription * hcb,SHORT * pScaleFactor,UCHAR global_gain,int band,int group)219 void 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  */
GenerateRandomVector(FIXP_DBL * RESTRICT spec,int size,int * pRandomState)257 static 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 
ScaleBand(FIXP_DBL * RESTRICT spec,int size,int scaleFactor,int specScale,int noise_e,int out_of_phase)292 static 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 */
CPns_Apply(const CPnsData * pPnsData,const CIcsInfo * pIcsInfo,SPECTRAL_PTR pSpectrum,const SHORT * pSpecScale,const SHORT * pScaleFactor,const SamplingRateInfo * pSamplingRateInfo,const INT granuleLength,const int channel)332 void 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