1/* -----------------------------------------------------------------------------
2Software License for The Fraunhofer FDK AAC Codec Library for Android
3
4© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5Forschung e.V. All rights reserved.
6
7 1.    INTRODUCTION
8The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10scheme for digital audio. This FDK AAC Codec software is intended to be used on
11a wide variety of Android devices.
12
13AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14general perceptual audio codecs. AAC-ELD is considered the best-performing
15full-bandwidth communications codec by independent studies and is widely
16deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17specifications.
18
19Patent licenses for necessary patent claims for the FDK AAC Codec (including
20those of Fraunhofer) may be obtained through Via Licensing
21(www.vialicensing.com) or through the respective patent owners individually for
22the purpose of encoding or decoding bit streams in products that are compliant
23with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24Android devices already license these patent claims through Via Licensing or
25directly from the patent owners, and therefore FDK AAC Codec software may
26already be covered under those patent licenses when it is used for those
27licensed purposes only.
28
29Commercially-licensed AAC software libraries, including floating-point versions
30with enhanced sound quality, are also available from Fraunhofer. Users are
31encouraged to check the Fraunhofer website for additional applications
32information and documentation.
33
342.    COPYRIGHT LICENSE
35
36Redistribution and use in source and binary forms, with or without modification,
37are permitted without payment of copyright license fees provided that you
38satisfy the following conditions:
39
40You must retain the complete text of this software license in redistributions of
41the FDK AAC Codec or your modifications thereto in source code form.
42
43You must retain the complete text of this software license in the documentation
44and/or other materials provided with redistributions of the FDK AAC Codec or
45your modifications thereto in binary form. You must make available free of
46charge copies of the complete source code of the FDK AAC Codec and your
47modifications thereto to recipients of copies in binary form.
48
49The name of Fraunhofer may not be used to endorse or promote products derived
50from this library without prior written permission.
51
52You may not charge copyright license fees for anyone to use, copy or distribute
53the FDK AAC Codec software or your modifications thereto.
54
55Your modified versions of the FDK AAC Codec must carry prominent notices stating
56that you changed the software and the date of any change. For modified versions
57of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59AAC Codec Library for Android."
60
613.    NO PATENT LICENSE
62
63NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65Fraunhofer provides no warranty of patent non-infringement with respect to this
66software.
67
68You may use this FDK AAC Codec software or modifications thereto only for
69purposes that are authorized by appropriate patent licenses.
70
714.    DISCLAIMER
72
73This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75including but not limited to the implied warranties of merchantability and
76fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78or consequential damages, including but not limited to procurement of substitute
79goods or services; loss of use, data, or profits, or business interruption,
80however caused and on any theory of liability, whether in contract, strict
81liability, or tort (including negligence), arising in any way out of the use of
82this software, even if advised of the possibility of such damage.
83
845.    CONTACT INFORMATION
85
86Fraunhofer Institute for Integrated Circuits IIS
87Attention: Audio and Multimedia Departments - FDK AAC LL
88Am Wolfsmantel 33
8991058 Erlangen, Germany
90
91www.iis.fraunhofer.de/amm
92amm-info@iis.fraunhofer.de
93----------------------------------------------------------------------------- */
94
95/**************************** AAC encoder library ******************************
96
97   Author(s):   M.Werner
98
99   Description: Quantization
100
101*******************************************************************************/
102
103#include "quantize.h"
104
105#include "aacEnc_rom.h"
106
107/*****************************************************************************
108
109    functionname: FDKaacEnc_quantizeLines
110    description: quantizes spectrum lines
111    returns:
112    input: global gain, number of lines to process, spectral data
113    output: quantized spectrum
114
115*****************************************************************************/
116static void FDKaacEnc_quantizeLines(INT gain, INT noOfLines,
117                                    const FIXP_DBL *mdctSpectrum,
118                                    SHORT *quaSpectrum, INT dZoneQuantEnable) {
119  int line;
120  FIXP_DBL k = FL2FXCONST_DBL(0.0f);
121  FIXP_QTD quantizer = FDKaacEnc_quantTableQ[(-gain) & 3];
122  INT quantizershift = ((-gain) >> 2) + 1;
123  const INT kShift = 16;
124
125  if (dZoneQuantEnable)
126    k = FL2FXCONST_DBL(0.23f) >> kShift;
127  else
128    k = FL2FXCONST_DBL(-0.0946f + 0.5f) >> kShift;
129
130  for (line = 0; line < noOfLines; line++) {
131    FIXP_DBL accu = fMultDiv2(mdctSpectrum[line], quantizer);
132
133    if (accu < FL2FXCONST_DBL(0.0f)) {
134      accu = -accu;
135      /* normalize */
136      INT accuShift = CntLeadingZeros(accu) - 1; /* CountLeadingBits() is not
137                                                    necessary here since test
138                                                    value is always > 0 */
139      accu <<= accuShift;
140      INT tabIndex =
141          (INT)(accu >> (DFRACT_BITS - 2 - MANT_DIGITS)) & (~MANT_SIZE);
142      INT totalShift = quantizershift - accuShift + 1;
143      accu = fMultDiv2(FDKaacEnc_mTab_3_4[tabIndex],
144                       FDKaacEnc_quantTableE[totalShift & 3]);
145      totalShift = (16 - 4) - (3 * (totalShift >> 2));
146      FDK_ASSERT(totalShift >= 0); /* MAX_QUANT_VIOLATION */
147      accu >>= fixMin(totalShift, DFRACT_BITS - 1);
148      quaSpectrum[line] =
149          (SHORT)(-((LONG)(k + accu) >> (DFRACT_BITS - 1 - 16)));
150    } else if (accu > FL2FXCONST_DBL(0.0f)) {
151      /* normalize */
152      INT accuShift = CntLeadingZeros(accu) - 1; /* CountLeadingBits() is not
153                                                    necessary here since test
154                                                    value is always > 0 */
155      accu <<= accuShift;
156      INT tabIndex =
157          (INT)(accu >> (DFRACT_BITS - 2 - MANT_DIGITS)) & (~MANT_SIZE);
158      INT totalShift = quantizershift - accuShift + 1;
159      accu = fMultDiv2(FDKaacEnc_mTab_3_4[tabIndex],
160                       FDKaacEnc_quantTableE[totalShift & 3]);
161      totalShift = (16 - 4) - (3 * (totalShift >> 2));
162      FDK_ASSERT(totalShift >= 0); /* MAX_QUANT_VIOLATION */
163      accu >>= fixMin(totalShift, DFRACT_BITS - 1);
164      quaSpectrum[line] = (SHORT)((LONG)(k + accu) >> (DFRACT_BITS - 1 - 16));
165    } else {
166      quaSpectrum[line] = 0;
167    }
168  }
169}
170
171/*****************************************************************************
172
173    functionname:iFDKaacEnc_quantizeLines
174    description: iquantizes spectrum lines
175                 mdctSpectrum = iquaSpectrum^4/3 *2^(0.25*gain)
176    input: global gain, number of lines to process,quantized spectrum
177    output: spectral data
178
179*****************************************************************************/
180static void FDKaacEnc_invQuantizeLines(INT gain, INT noOfLines,
181                                       SHORT *quantSpectrum,
182                                       FIXP_DBL *mdctSpectrum)
183
184{
185  INT iquantizermod;
186  INT iquantizershift;
187  INT line;
188
189  iquantizermod = gain & 3;
190  iquantizershift = gain >> 2;
191
192  for (line = 0; line < noOfLines; line++) {
193    if (quantSpectrum[line] < 0) {
194      FIXP_DBL accu;
195      INT ex, specExp, tabIndex;
196      FIXP_DBL s, t;
197
198      accu = (FIXP_DBL)-quantSpectrum[line];
199
200      ex = CountLeadingBits(accu);
201      accu <<= ex;
202      specExp = (DFRACT_BITS - 1) - ex;
203
204      FDK_ASSERT(specExp < 14); /* this fails if abs(value) > 8191 */
205
206      tabIndex = (INT)(accu >> (DFRACT_BITS - 2 - MANT_DIGITS)) & (~MANT_SIZE);
207
208      /* calculate "mantissa" ^4/3 */
209      s = FDKaacEnc_mTab_4_3Elc[tabIndex];
210
211      /* get approperiate exponent multiplier for specExp^3/4 combined with
212       * scfMod */
213      t = FDKaacEnc_specExpMantTableCombElc[iquantizermod][specExp];
214
215      /* multiply "mantissa" ^4/3 with exponent multiplier */
216      accu = fMult(s, t);
217
218      /* get approperiate exponent shifter */
219      specExp = FDKaacEnc_specExpTableComb[iquantizermod][specExp] -
220                1; /* -1 to avoid overflows in accu */
221
222      if ((-iquantizershift - specExp) < 0)
223        accu <<= -(-iquantizershift - specExp);
224      else
225        accu >>= -iquantizershift - specExp;
226
227      mdctSpectrum[line] = -accu;
228    } else if (quantSpectrum[line] > 0) {
229      FIXP_DBL accu;
230      INT ex, specExp, tabIndex;
231      FIXP_DBL s, t;
232
233      accu = (FIXP_DBL)(INT)quantSpectrum[line];
234
235      ex = CountLeadingBits(accu);
236      accu <<= ex;
237      specExp = (DFRACT_BITS - 1) - ex;
238
239      FDK_ASSERT(specExp < 14); /* this fails if abs(value) > 8191 */
240
241      tabIndex = (INT)(accu >> (DFRACT_BITS - 2 - MANT_DIGITS)) & (~MANT_SIZE);
242
243      /* calculate "mantissa" ^4/3 */
244      s = FDKaacEnc_mTab_4_3Elc[tabIndex];
245
246      /* get approperiate exponent multiplier for specExp^3/4 combined with
247       * scfMod */
248      t = FDKaacEnc_specExpMantTableCombElc[iquantizermod][specExp];
249
250      /* multiply "mantissa" ^4/3 with exponent multiplier */
251      accu = fMult(s, t);
252
253      /* get approperiate exponent shifter */
254      specExp = FDKaacEnc_specExpTableComb[iquantizermod][specExp] -
255                1; /* -1 to avoid overflows in accu */
256
257      if ((-iquantizershift - specExp) < 0)
258        accu <<= -(-iquantizershift - specExp);
259      else
260        accu >>= -iquantizershift - specExp;
261
262      mdctSpectrum[line] = accu;
263    } else {
264      mdctSpectrum[line] = FL2FXCONST_DBL(0.0f);
265    }
266  }
267}
268
269/*****************************************************************************
270
271    functionname: FDKaacEnc_QuantizeSpectrum
272    description: quantizes the entire spectrum
273    returns:
274    input: number of scalefactor bands to be quantized, ...
275    output: quantized spectrum
276
277*****************************************************************************/
278void FDKaacEnc_QuantizeSpectrum(INT sfbCnt, INT maxSfbPerGroup, INT sfbPerGroup,
279                                const INT *sfbOffset,
280                                const FIXP_DBL *mdctSpectrum, INT globalGain,
281                                const INT *scalefactors,
282                                SHORT *quantizedSpectrum,
283                                INT dZoneQuantEnable) {
284  INT sfbOffs, sfb;
285
286  /* in FDKaacEnc_quantizeLines quaSpectrum is calculated with:
287        spec^(3/4) * 2^(-3/16*QSS) * 2^(3/4*scale) + k
288     simplify scaling calculation and reduce QSS before:
289        spec^(3/4) * 2^(-3/16*(QSS - 4*scale)) */
290
291  for (sfbOffs = 0; sfbOffs < sfbCnt; sfbOffs += sfbPerGroup)
292    for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
293      INT scalefactor = scalefactors[sfbOffs + sfb];
294
295      FDKaacEnc_quantizeLines(
296          globalGain - scalefactor, /* QSS */
297          sfbOffset[sfbOffs + sfb + 1] - sfbOffset[sfbOffs + sfb],
298          mdctSpectrum + sfbOffset[sfbOffs + sfb],
299          quantizedSpectrum + sfbOffset[sfbOffs + sfb], dZoneQuantEnable);
300    }
301}
302
303/*****************************************************************************
304
305    functionname: FDKaacEnc_calcSfbDist
306    description: calculates distortion of quantized values
307    returns: distortion
308    input: gain, number of lines to process, spectral data
309    output:
310
311*****************************************************************************/
312FIXP_DBL FDKaacEnc_calcSfbDist(const FIXP_DBL *mdctSpectrum,
313                               SHORT *quantSpectrum, INT noOfLines, INT gain,
314                               INT dZoneQuantEnable) {
315  INT i, scale;
316  FIXP_DBL xfsf;
317  FIXP_DBL diff;
318  FIXP_DBL invQuantSpec;
319
320  xfsf = FL2FXCONST_DBL(0.0f);
321
322  for (i = 0; i < noOfLines; i++) {
323    /* quantization */
324    FDKaacEnc_quantizeLines(gain, 1, &mdctSpectrum[i], &quantSpectrum[i],
325                            dZoneQuantEnable);
326
327    if (fAbs(quantSpectrum[i]) > MAX_QUANT) {
328      return FL2FXCONST_DBL(0.0f);
329    }
330    /* inverse quantization */
331    FDKaacEnc_invQuantizeLines(gain, 1, &quantSpectrum[i], &invQuantSpec);
332
333    /* dist */
334    diff = fixp_abs(fixp_abs(invQuantSpec) - fixp_abs(mdctSpectrum[i] >> 1));
335
336    scale = CountLeadingBits(diff);
337    diff = scaleValue(diff, scale);
338    diff = fPow2(diff);
339    scale = fixMin(2 * (scale - 1), DFRACT_BITS - 1);
340
341    diff = scaleValue(diff, -scale);
342
343    xfsf = xfsf + diff;
344  }
345
346  xfsf = CalcLdData(xfsf);
347
348  return xfsf;
349}
350
351/*****************************************************************************
352
353    functionname: FDKaacEnc_calcSfbQuantEnergyAndDist
354    description: calculates energy and distortion of quantized values
355    returns:
356    input: gain, number of lines to process, quantized spectral data,
357           spectral data
358    output: energy, distortion
359
360*****************************************************************************/
361void FDKaacEnc_calcSfbQuantEnergyAndDist(FIXP_DBL *mdctSpectrum,
362                                         SHORT *quantSpectrum, INT noOfLines,
363                                         INT gain, FIXP_DBL *en,
364                                         FIXP_DBL *dist) {
365  INT i, scale;
366  FIXP_DBL invQuantSpec;
367  FIXP_DBL diff;
368
369  FIXP_DBL energy = FL2FXCONST_DBL(0.0f);
370  FIXP_DBL distortion = FL2FXCONST_DBL(0.0f);
371
372  for (i = 0; i < noOfLines; i++) {
373    if (fAbs(quantSpectrum[i]) > MAX_QUANT) {
374      *en = FL2FXCONST_DBL(0.0f);
375      *dist = FL2FXCONST_DBL(0.0f);
376      return;
377    }
378
379    /* inverse quantization */
380    FDKaacEnc_invQuantizeLines(gain, 1, &quantSpectrum[i], &invQuantSpec);
381
382    /* energy */
383    energy += fPow2(invQuantSpec);
384
385    /* dist */
386    diff = fixp_abs(fixp_abs(invQuantSpec) - fixp_abs(mdctSpectrum[i] >> 1));
387
388    scale = CountLeadingBits(diff);
389    diff = scaleValue(diff, scale);
390    diff = fPow2(diff);
391
392    scale = fixMin(2 * (scale - 1), DFRACT_BITS - 1);
393
394    diff = scaleValue(diff, -scale);
395
396    distortion += diff;
397  }
398
399  *en = CalcLdData(energy) + FL2FXCONST_DBL(0.03125f);
400  *dist = CalcLdData(distortion);
401}
402