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/*********************** MPEG surround encoder library *************************
96
97   Author(s):   M. Multrus
98
99   Description: Parameter Extraction
100
101*******************************************************************************/
102
103/* Includes ******************************************************************/
104#include "sacenc_paramextract.h"
105#include "sacenc_tree.h"
106#include "sacenc_vectorfunctions.h"
107
108/* Defines *******************************************************************/
109#define LOG10_2_10 (3.01029995664f) /* 10.0f*log10(2.f) */
110#define SCALE_CLDE_SF (7)           /* maxVal in Quant tab is +/-  50 */
111#define SCALE_CLDD_SF (8)           /* maxVal in Quant tab is +/- 150 */
112
113/* Data Types ****************************************************************/
114typedef struct T_TTO_BOX {
115  FIXP_DBL pCld__FDK[MAX_NUM_PARAM_BANDS];
116  FIXP_DBL pIcc__FDK[MAX_NUM_PARAM_BANDS];
117  FIXP_DBL pCldQuant__FDK[MAX_NUM_PARAM_BANDS];
118
119  const FIXP_DBL *pIccQuantTable__FDK;
120  const FIXP_DBL *pCldQuantTableDec__FDK;
121  const FIXP_DBL *pCldQuantTableEnc__FDK;
122
123  SCHAR pCldEbQIdx[MAX_NUM_PARAM_BANDS];
124  SCHAR pIccDownmixIdx[MAX_NUM_PARAM_BANDS];
125
126  UCHAR *pParameterBand2HybridBandOffset;
127  const INT *pSubbandImagSign;
128  UCHAR nHybridBandsMax;
129  UCHAR nParameterBands;
130  UCHAR bFrameKeep;
131
132  UCHAR iccCorrelationCoherenceBorder;
133  BOX_QUANTMODE boxQuantMode;
134
135  UCHAR nIccQuantSteps;
136  UCHAR nIccQuantOffset;
137
138  UCHAR nCldQuantSteps;
139  UCHAR nCldQuantOffset;
140
141  UCHAR bUseCoarseQuantCld;
142  UCHAR bUseCoarseQuantIcc;
143
144} TTO_BOX;
145
146struct BOX_SUBBAND_SETUP {
147  BOX_SUBBAND_CONFIG subbandConfig;
148  UCHAR nParameterBands;
149  const UCHAR *pSubband2ParameterIndexLd;
150  UCHAR iccCorrelationCoherenceBorder;
151};
152
153/* Constants *****************************************************************/
154static const UCHAR subband2Parameter4_Ld[NUM_QMF_BANDS] = {
155    0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
156    2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
157    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};
158
159static const UCHAR subband2Parameter5_Ld[NUM_QMF_BANDS] = {
160    0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
161    3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
162    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
163
164static const UCHAR subband2Parameter7_Ld[NUM_QMF_BANDS] = {
165    0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
166    5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
167    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6};
168
169static const UCHAR subband2Parameter9_Ld[NUM_QMF_BANDS] = {
170    0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
171    7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
172    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};
173
174static const UCHAR subband2Parameter12_Ld[NUM_QMF_BANDS] = {
175    0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  7,  7,  7,  8,  8,
176    8,  8,  9,  9,  9,  9,  9,  10, 10, 10, 10, 10, 10, 10, 10, 10,
177    10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
178    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11};
179
180static const UCHAR subband2Parameter15_Ld[NUM_QMF_BANDS] = {
181    0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  9,  10, 10, 10, 11, 11,
182    11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13,
183    13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
184    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14};
185
186static const UCHAR subband2Parameter23_Ld[NUM_QMF_BANDS] = {
187    0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 12, 13, 13,
188    14, 14, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19, 19,
189    19, 19, 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21,
190    22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22};
191
192static const INT subbandImagSign_Ld[NUM_QMF_BANDS] = {
193    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
194    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
195    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
196};
197
198#define SCALE_CLDE(a) (FL2FXCONST_DBL(a / (float)(1 << SCALE_CLDE_SF)))
199static const FIXP_DBL cldQuantTableFineEnc__FDK[MAX_CLD_QUANT_FINE] = {
200    SCALE_CLDE(-50.0), SCALE_CLDE(-45.0), SCALE_CLDE(-40.0), SCALE_CLDE(-35.0),
201    SCALE_CLDE(-30.0), SCALE_CLDE(-25.0), SCALE_CLDE(-22.0), SCALE_CLDE(-19.0),
202    SCALE_CLDE(-16.0), SCALE_CLDE(-13.0), SCALE_CLDE(-10.0), SCALE_CLDE(-8.0),
203    SCALE_CLDE(-6.0),  SCALE_CLDE(-4.0),  SCALE_CLDE(-2.0),  SCALE_CLDE(0.0),
204    SCALE_CLDE(2.0),   SCALE_CLDE(4.0),   SCALE_CLDE(6.0),   SCALE_CLDE(8.0),
205    SCALE_CLDE(10.0),  SCALE_CLDE(13.0),  SCALE_CLDE(16.0),  SCALE_CLDE(19.0),
206    SCALE_CLDE(22.0),  SCALE_CLDE(25.0),  SCALE_CLDE(30.0),  SCALE_CLDE(35.0),
207    SCALE_CLDE(40.0),  SCALE_CLDE(45.0),  SCALE_CLDE(50.0)};
208
209static const FIXP_DBL cldQuantTableCoarseEnc__FDK[MAX_CLD_QUANT_COARSE] = {
210    SCALE_CLDE(-50.0), SCALE_CLDE(-35.0), SCALE_CLDE(-25.0), SCALE_CLDE(-19.0),
211    SCALE_CLDE(-13.0), SCALE_CLDE(-8.0),  SCALE_CLDE(-4.0),  SCALE_CLDE(0.0),
212    SCALE_CLDE(4.0),   SCALE_CLDE(8.0),   SCALE_CLDE(13.0),  SCALE_CLDE(19.0),
213    SCALE_CLDE(25.0),  SCALE_CLDE(35.0),  SCALE_CLDE(50.0)};
214
215#define SCALE_CLDD(a) (FL2FXCONST_DBL(a / (float)(1 << SCALE_CLDD_SF)))
216static const FIXP_DBL cldQuantTableFineDec__FDK[MAX_CLD_QUANT_FINE] = {
217    SCALE_CLDD(-150.0), SCALE_CLDD(-45.0), SCALE_CLDD(-40.0), SCALE_CLDD(-35.0),
218    SCALE_CLDD(-30.0),  SCALE_CLDD(-25.0), SCALE_CLDD(-22.0), SCALE_CLDD(-19.0),
219    SCALE_CLDD(-16.0),  SCALE_CLDD(-13.0), SCALE_CLDD(-10.0), SCALE_CLDD(-8.0),
220    SCALE_CLDD(-6.0),   SCALE_CLDD(-4.0),  SCALE_CLDD(-2.0),  SCALE_CLDD(0.0),
221    SCALE_CLDD(2.0),    SCALE_CLDD(4.0),   SCALE_CLDD(6.0),   SCALE_CLDD(8.0),
222    SCALE_CLDD(10.0),   SCALE_CLDD(13.0),  SCALE_CLDD(16.0),  SCALE_CLDD(19.0),
223    SCALE_CLDD(22.0),   SCALE_CLDD(25.0),  SCALE_CLDD(30.0),  SCALE_CLDD(35.0),
224    SCALE_CLDD(40.0),   SCALE_CLDD(45.0),  SCALE_CLDD(150.0)};
225
226static const FIXP_DBL cldQuantTableCoarseDec__FDK[MAX_CLD_QUANT_COARSE] = {
227    SCALE_CLDD(-150.0), SCALE_CLDD(-35.0), SCALE_CLDD(-25.0), SCALE_CLDD(-19.0),
228    SCALE_CLDD(-13.0),  SCALE_CLDD(-8.0),  SCALE_CLDD(-4.0),  SCALE_CLDD(0.0),
229    SCALE_CLDD(4.0),    SCALE_CLDD(8.0),   SCALE_CLDD(13.0),  SCALE_CLDD(19.0),
230    SCALE_CLDD(25.0),   SCALE_CLDD(35.0),  SCALE_CLDD(150.0)};
231
232#define SCALE_ICC(a) (FL2FXCONST_DBL(a))
233static const FIXP_DBL iccQuantTableFine__FDK[MAX_ICC_QUANT_FINE] = {
234    SCALE_ICC(0.99999999953), SCALE_ICC(0.937f),   SCALE_ICC(0.84118f),
235    SCALE_ICC(0.60092f),      SCALE_ICC(0.36764f), SCALE_ICC(0.0f),
236    SCALE_ICC(-0.589f),       SCALE_ICC(-0.99f)};
237
238static const FIXP_DBL iccQuantTableCoarse__FDK[MAX_ICC_QUANT_COARSE] = {
239    SCALE_ICC(0.99999999953), SCALE_ICC(0.84118f), SCALE_ICC(0.36764f),
240    SCALE_ICC(-0.5890f)};
241
242static const BOX_SUBBAND_SETUP boxSubbandSetup[] = {
243    {BOX_SUBBANDS_4, 4, subband2Parameter4_Ld, 1},
244    {BOX_SUBBANDS_5, 5, subband2Parameter5_Ld, 2},
245    {BOX_SUBBANDS_7, 7, subband2Parameter7_Ld, 3},
246    {BOX_SUBBANDS_9, 9, subband2Parameter9_Ld, 4},
247    {BOX_SUBBANDS_12, 12, subband2Parameter12_Ld, 4},
248    {BOX_SUBBANDS_15, 15, subband2Parameter15_Ld, 5},
249    {BOX_SUBBANDS_23, 23, subband2Parameter23_Ld, 8}};
250
251/* Function / Class Declarations *********************************************/
252
253/* Function / Class Definition ***********************************************/
254static const BOX_SUBBAND_SETUP *getBoxSubbandSetup(
255    const BOX_SUBBAND_CONFIG subbandConfig) {
256  int i;
257  const BOX_SUBBAND_SETUP *setup = NULL;
258
259  for (i = 0; i < (int)(sizeof(boxSubbandSetup) / sizeof(BOX_SUBBAND_SETUP));
260       i++) {
261    if (boxSubbandSetup[i].subbandConfig == subbandConfig) {
262      setup = &boxSubbandSetup[i];
263      break;
264    }
265  }
266  return setup;
267}
268
269static inline void ApplyBBCuesFDK(FIXP_DBL *const pData,
270                                  const INT nParamBands) {
271  int i, s;
272  FIXP_DBL tmp, invParamBands;
273
274  invParamBands = fDivNormHighPrec((FIXP_DBL)1, (FIXP_DBL)nParamBands, &s);
275  s = -s;
276
277  tmp = fMult(pData[0], invParamBands) >> s;
278  for (i = 1; i < nParamBands; i++) {
279    tmp += fMult(pData[i], invParamBands) >> s;
280  }
281
282  for (i = 0; i < nParamBands; i++) {
283    pData[i] = tmp;
284  }
285}
286
287static INT getNumberParameterBands(const BOX_SUBBAND_CONFIG subbandConfig) {
288  const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig);
289  return ((setup == NULL) ? 0 : setup->nParameterBands);
290}
291
292static const UCHAR *getSubband2ParameterIndex(
293    const BOX_SUBBAND_CONFIG subbandConfig) {
294  const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig);
295
296  return ((setup == NULL) ? NULL : (setup->pSubband2ParameterIndexLd));
297}
298
299void fdk_sacenc_calcParameterBand2HybridBandOffset(
300    const BOX_SUBBAND_CONFIG subbandConfig, const INT nHybridBands,
301    UCHAR *pParameterBand2HybridBandOffset) {
302  const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig);
303  const UCHAR *pSubband2ParameterIndex;
304
305  int i, pb;
306
307  pSubband2ParameterIndex = setup->pSubband2ParameterIndexLd;
308
309  for (pb = 0, i = 0; i < nHybridBands - 1; i++) {
310    if (pSubband2ParameterIndex[i + 1] - pSubband2ParameterIndex[i]) {
311      pParameterBand2HybridBandOffset[pb++] = (i + 1);
312    }
313  }
314  pParameterBand2HybridBandOffset[pb++] = (i + 1);
315}
316
317const INT *fdk_sacenc_getSubbandImagSign() {
318  const INT *pImagSign = NULL;
319
320  pImagSign = subbandImagSign_Ld;
321
322  return (pImagSign);
323}
324
325static INT getIccCorrelationCoherenceBorder(
326    const BOX_SUBBAND_CONFIG subbandConfig, const INT bUseCoherenceOnly) {
327  const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig);
328  return (
329      (setup == NULL)
330          ? 0
331          : ((bUseCoherenceOnly) ? 0 : setup->iccCorrelationCoherenceBorder));
332}
333
334FDK_SACENC_ERROR fdk_sacenc_createTtoBox(HANDLE_TTO_BOX *hTtoBox) {
335  FDK_SACENC_ERROR error = SACENC_OK;
336
337  if (NULL == hTtoBox) {
338    error = SACENC_INVALID_HANDLE;
339  } else {
340    FDK_ALLOCATE_MEMORY_1D(*hTtoBox, 1, TTO_BOX);
341  }
342  return error;
343
344bail:
345  fdk_sacenc_destroyTtoBox(hTtoBox);
346  return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error);
347}
348
349FDK_SACENC_ERROR fdk_sacenc_initTtoBox(HANDLE_TTO_BOX hTtoBox,
350                                       const TTO_BOX_CONFIG *const ttoBoxConfig,
351                                       UCHAR *pParameterBand2HybridBandOffset) {
352  FDK_SACENC_ERROR error = SACENC_OK;
353
354  if ((hTtoBox == NULL) || (ttoBoxConfig == NULL) ||
355      (pParameterBand2HybridBandOffset == NULL)) {
356    error = SACENC_INVALID_HANDLE;
357  } else {
358    FDKmemclear(hTtoBox, sizeof(TTO_BOX));
359
360    hTtoBox->bUseCoarseQuantCld = ttoBoxConfig->bUseCoarseQuantCld;
361    hTtoBox->bUseCoarseQuantIcc = ttoBoxConfig->bUseCoarseQuantIcc;
362    hTtoBox->boxQuantMode = ttoBoxConfig->boxQuantMode;
363    hTtoBox->iccCorrelationCoherenceBorder = getIccCorrelationCoherenceBorder(
364        ttoBoxConfig->subbandConfig, ttoBoxConfig->bUseCoherenceIccOnly);
365    hTtoBox->nHybridBandsMax = ttoBoxConfig->nHybridBandsMax;
366    hTtoBox->nParameterBands =
367        getNumberParameterBands(ttoBoxConfig->subbandConfig);
368    hTtoBox->bFrameKeep = ttoBoxConfig->bFrameKeep;
369
370    hTtoBox->nIccQuantSteps =
371        fdk_sacenc_getNumberIccQuantLevels(hTtoBox->bUseCoarseQuantIcc);
372    hTtoBox->nIccQuantOffset =
373        fdk_sacenc_getIccQuantOffset(hTtoBox->bUseCoarseQuantIcc);
374
375    hTtoBox->pIccQuantTable__FDK = hTtoBox->bUseCoarseQuantIcc
376                                       ? iccQuantTableCoarse__FDK
377                                       : iccQuantTableFine__FDK;
378    hTtoBox->pCldQuantTableDec__FDK = hTtoBox->bUseCoarseQuantCld
379                                          ? cldQuantTableCoarseDec__FDK
380                                          : cldQuantTableFineDec__FDK;
381    hTtoBox->pCldQuantTableEnc__FDK = hTtoBox->bUseCoarseQuantCld
382                                          ? cldQuantTableCoarseEnc__FDK
383                                          : cldQuantTableFineEnc__FDK;
384
385    hTtoBox->nCldQuantSteps =
386        fdk_sacenc_getNumberCldQuantLevels(hTtoBox->bUseCoarseQuantCld);
387    hTtoBox->nCldQuantOffset =
388        fdk_sacenc_getCldQuantOffset(hTtoBox->bUseCoarseQuantCld);
389
390    /* sanity */
391    if (NULL == (hTtoBox->pParameterBand2HybridBandOffset =
392                     pParameterBand2HybridBandOffset)) {
393      error = SACENC_INIT_ERROR;
394      goto bail;
395    }
396
397    if (NULL == (hTtoBox->pSubbandImagSign = fdk_sacenc_getSubbandImagSign())) {
398      error = SACENC_INIT_ERROR;
399    }
400
401    if ((hTtoBox->boxQuantMode != BOX_QUANTMODE_FINE) &&
402        (hTtoBox->boxQuantMode != BOX_QUANTMODE_EBQ1) &&
403        (hTtoBox->boxQuantMode != BOX_QUANTMODE_EBQ2)) {
404      error = SACENC_INIT_ERROR;
405      goto bail;
406    }
407  }
408bail:
409  return error;
410}
411
412FDK_SACENC_ERROR fdk_sacenc_destroyTtoBox(HANDLE_TTO_BOX *hTtoBox) {
413  FDK_SACENC_ERROR error = SACENC_OK;
414
415  if (*hTtoBox != NULL) {
416    FDKfree(*hTtoBox);
417    *hTtoBox = NULL;
418  }
419
420  return error;
421}
422
423static FDK_SACENC_ERROR calculateIccFDK(const INT nParamBand,
424                                        const INT correlationCoherenceBorder,
425                                        const FIXP_DBL *const pPwr1,
426                                        const FIXP_DBL *const pPwr2,
427                                        const FIXP_DBL *const pProdReal,
428                                        FIXP_DBL const *const pProdImag,
429                                        FIXP_DBL *const pIcc) {
430  FDK_SACENC_ERROR error = SACENC_OK;
431
432  if ((pPwr1 == NULL) || (pPwr2 == NULL) || (pProdReal == NULL) ||
433      (pProdImag == NULL) || (pIcc == NULL)) {
434    error = SACENC_INVALID_HANDLE;
435  } else {
436    /* sanity check border */
437    if (correlationCoherenceBorder > nParamBand) {
438      error = SACENC_INVALID_CONFIG;
439    } else {
440      /* correlation */
441      FDKcalcCorrelationVec(pIcc, pProdReal, pPwr1, pPwr2,
442                            correlationCoherenceBorder);
443
444      /* coherence */
445      calcCoherenceVec(&pIcc[correlationCoherenceBorder],
446                       &pProdReal[correlationCoherenceBorder],
447                       &pProdImag[correlationCoherenceBorder],
448                       &pPwr1[correlationCoherenceBorder],
449                       &pPwr2[correlationCoherenceBorder], 0, 0,
450                       nParamBand - correlationCoherenceBorder);
451
452    } /* valid configuration */
453  }   /* valid handle */
454
455  return error;
456}
457
458static void QuantizeCoefFDK(const FIXP_DBL *const input, const INT nBands,
459                            const FIXP_DBL *const quantTable,
460                            const INT idxOffset, const INT nQuantSteps,
461                            SCHAR *const quantOut) {
462  int band;
463  const int reverse = (quantTable[0] > quantTable[1]);
464
465  for (band = 0; band < nBands; band++) {
466    FIXP_DBL qVal;
467    FIXP_DBL curVal = input[band];
468
469    int lower = 0;
470    int upper = nQuantSteps - 1;
471
472    if (reverse) {
473      while (upper - lower > 1) {
474        int idx = (lower + upper) >> 1;
475        qVal = quantTable[idx];
476        if (curVal >= qVal) {
477          upper = idx;
478        } else {
479          lower = idx;
480        }
481      } /* while */
482
483      if ((curVal - quantTable[lower]) >= (quantTable[upper] - curVal)) {
484        quantOut[band] = lower - idxOffset;
485      } else {
486        quantOut[band] = upper - idxOffset;
487      }
488    } /* if reverse */
489    else {
490      while (upper - lower > 1) {
491        int idx = (lower + upper) >> 1;
492        qVal = quantTable[idx];
493        if (curVal <= qVal) {
494          upper = idx;
495        } else {
496          lower = idx;
497        }
498      } /* while */
499
500      if ((curVal - quantTable[lower]) <= (quantTable[upper] - curVal)) {
501        quantOut[band] = lower - idxOffset;
502      } else {
503        quantOut[band] = upper - idxOffset;
504      }
505    } /* else reverse */
506  }   /* for band */
507}
508
509static void deQuantizeCoefFDK(const SCHAR *const input, const INT nBands,
510                              const FIXP_DBL *const quantTable,
511                              const INT idxOffset, FIXP_DBL *const dequantOut) {
512  int band;
513
514  for (band = 0; band < nBands; band++) {
515    dequantOut[band] = quantTable[input[band] + idxOffset];
516  }
517}
518
519static void CalculateCldFDK(FIXP_DBL *const pCld, const FIXP_DBL *const pPwr1,
520                            const FIXP_DBL *const pPwr2, const INT scaleCh1,
521                            const INT *const pbScaleCh1, const INT scaleCh2,
522                            const INT *const pbScaleCh2, const int nParamBand) {
523  INT i;
524  FIXP_DBL ldPwr1, ldPwr2, cld;
525  FIXP_DBL maxPwr = FL2FXCONST_DBL(
526      30.0f /
527      (1 << (LD_DATA_SHIFT +
528             1))); /* consider SACENC_FLOAT_EPSILON in power calculation */
529
530  for (i = 0; i < nParamBand; i++) {
531    ldPwr1 =
532        (CalcLdData(pPwr1[i]) >> 1) + ((FIXP_DBL)(scaleCh1 + pbScaleCh1[i])
533                                       << (DFRACT_BITS - 1 - LD_DATA_SHIFT));
534    ldPwr2 =
535        (CalcLdData(pPwr2[i]) >> 1) + ((FIXP_DBL)(scaleCh2 + pbScaleCh2[i])
536                                       << (DFRACT_BITS - 1 - LD_DATA_SHIFT));
537
538    ldPwr1 = fixMax(fixMin(ldPwr1, maxPwr), -maxPwr);
539    ldPwr2 = fixMax(fixMin(ldPwr2, maxPwr), -maxPwr);
540
541    /* ldPwr1 and ldPwr2 are scaled by LD_DATA_SHIFT and additional 1 bit; 1 bit
542     * scale by fMultDiv2() */
543    cld = fMultDiv2(FL2FXCONST_DBL(LOG10_2_10 / (1 << SCALE_CLDE_SF)),
544                    ldPwr1 - ldPwr2);
545
546    cld =
547        fixMin(cld, (FIXP_DBL)(((FIXP_DBL)MAXVAL_DBL) >> (LD_DATA_SHIFT + 2)));
548    cld =
549        fixMax(cld, (FIXP_DBL)(((FIXP_DBL)MINVAL_DBL) >> (LD_DATA_SHIFT + 2)));
550    pCld[i] = cld << (LD_DATA_SHIFT + 2);
551  }
552}
553
554FDK_SACENC_ERROR fdk_sacenc_applyTtoBox(
555    HANDLE_TTO_BOX hTtoBox, const INT nTimeSlots, const INT startTimeSlot,
556    const INT nHybridBands, const FIXP_DPK *const *const ppHybridData1__FDK,
557    const FIXP_DPK *const *const ppHybridData2__FDK, SCHAR *const pIccIdx,
558    UCHAR *const pbIccQuantCoarse, SCHAR *const pCldIdx,
559    UCHAR *const pbCldQuantCoarse, const INT bUseBBCues, INT *scaleCh1,
560    INT *scaleCh2) {
561  FDK_SACENC_ERROR error = SACENC_OK;
562
563  C_ALLOC_SCRATCH_START(powerHybridData1__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
564  C_ALLOC_SCRATCH_START(powerHybridData2__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
565  C_ALLOC_SCRATCH_START(prodHybridDataReal__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
566  C_ALLOC_SCRATCH_START(prodHybridDataImag__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
567
568  C_ALLOC_SCRATCH_START(IccDownmix__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
569  C_ALLOC_SCRATCH_START(IccDownmixQuant__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
570  C_ALLOC_SCRATCH_START(pbScaleCh1, INT, MAX_NUM_PARAM_BANDS)
571  C_ALLOC_SCRATCH_START(pbScaleCh2, INT, MAX_NUM_PARAM_BANDS)
572
573  if ((hTtoBox == NULL) || (pCldIdx == NULL) || (pbCldQuantCoarse == NULL) ||
574      (ppHybridData1__FDK == NULL) || (ppHybridData2__FDK == NULL) ||
575      (pIccIdx == NULL) || (pbIccQuantCoarse == NULL)) {
576    error = SACENC_INVALID_HANDLE;
577  } else {
578    int j, pb;
579    const int nParamBands = hTtoBox->nParameterBands;
580    const int bUseEbQ = (hTtoBox->boxQuantMode == BOX_QUANTMODE_EBQ1) ||
581                        (hTtoBox->boxQuantMode == BOX_QUANTMODE_EBQ2);
582
583    /* sanity check */
584    if ((nHybridBands < 0) || (nHybridBands > hTtoBox->nHybridBandsMax)) {
585      error = SACENC_INVALID_CONFIG;
586      goto bail;
587    }
588
589    int outScale;    /* scalefactor will not be evaluated */
590    int inScale = 5; /* scale factor determined empirically */
591
592    /* calculate the headroom of the hybrid data for each parameter band */
593    FDKcalcPbScaleFactor(ppHybridData1__FDK,
594                         hTtoBox->pParameterBand2HybridBandOffset, pbScaleCh1,
595                         startTimeSlot, nTimeSlots, nParamBands);
596    FDKcalcPbScaleFactor(ppHybridData2__FDK,
597                         hTtoBox->pParameterBand2HybridBandOffset, pbScaleCh2,
598                         startTimeSlot, nTimeSlots, nParamBands);
599
600    for (j = 0, pb = 0; pb < nParamBands; pb++) {
601      FIXP_DBL data1, data2;
602      data1 = data2 = (FIXP_DBL)0;
603      for (; j < hTtoBox->pParameterBand2HybridBandOffset[pb]; j++) {
604        data1 += sumUpCplxPow2Dim2(ppHybridData1__FDK, SUM_UP_STATIC_SCALE,
605                                   inScale + pbScaleCh1[pb], &outScale,
606                                   startTimeSlot, nTimeSlots, j, j + 1);
607        data2 += sumUpCplxPow2Dim2(ppHybridData2__FDK, SUM_UP_STATIC_SCALE,
608                                   inScale + pbScaleCh2[pb], &outScale,
609                                   startTimeSlot, nTimeSlots, j, j + 1);
610      } /* for j */
611      powerHybridData1__FDK[pb] = data1;
612      powerHybridData2__FDK[pb] = data2;
613    } /* pb */
614
615    {
616      for (j = 0, pb = 0; pb < nParamBands; pb++) {
617        FIXP_DBL dataReal, dataImag;
618        dataReal = dataImag = (FIXP_DBL)0;
619        for (; j < hTtoBox->pParameterBand2HybridBandOffset[pb]; j++) {
620          FIXP_DPK scalarProd;
621          cplx_cplxScalarProduct(&scalarProd, ppHybridData1__FDK,
622                                 ppHybridData2__FDK, inScale + pbScaleCh1[pb],
623                                 inScale + pbScaleCh2[pb], &outScale,
624                                 startTimeSlot, nTimeSlots, j, j + 1);
625          dataReal += scalarProd.v.re;
626          if (hTtoBox->pSubbandImagSign[j] < 0) {
627            dataImag -= scalarProd.v.im;
628          } else {
629            dataImag += scalarProd.v.im;
630          }
631        } /* for j */
632        prodHybridDataReal__FDK[pb] = dataReal;
633        prodHybridDataImag__FDK[pb] = dataImag;
634      } /* pb */
635
636      if (SACENC_OK != (error = calculateIccFDK(
637                            nParamBands, hTtoBox->iccCorrelationCoherenceBorder,
638                            powerHybridData1__FDK, powerHybridData2__FDK,
639                            prodHybridDataReal__FDK, prodHybridDataImag__FDK,
640                            hTtoBox->pIcc__FDK))) {
641        goto bail;
642      }
643
644      /* calculate correlation based Icc for downmix */
645      if (SACENC_OK != (error = calculateIccFDK(
646                            nParamBands, nParamBands, powerHybridData1__FDK,
647                            powerHybridData2__FDK, prodHybridDataReal__FDK,
648                            prodHybridDataImag__FDK, IccDownmix__FDK))) {
649        goto bail;
650      }
651    }
652
653    if (!bUseEbQ) {
654      CalculateCldFDK(hTtoBox->pCld__FDK, powerHybridData1__FDK,
655                      powerHybridData2__FDK, *scaleCh1 + inScale + 1,
656                      pbScaleCh1, *scaleCh2 + inScale + 1, pbScaleCh2,
657                      nParamBands);
658    }
659
660    if (bUseBBCues) {
661      ApplyBBCuesFDK(&hTtoBox->pCld__FDK[0], nParamBands);
662
663      { ApplyBBCuesFDK(&hTtoBox->pIcc__FDK[0], nParamBands); }
664
665    } /* bUseBBCues */
666
667    /* quantize/de-quantize icc */
668    {
669      QuantizeCoefFDK(hTtoBox->pIcc__FDK, nParamBands,
670                      hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset,
671                      hTtoBox->nIccQuantSteps, pIccIdx);
672      QuantizeCoefFDK(IccDownmix__FDK, nParamBands,
673                      hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset,
674                      hTtoBox->nIccQuantSteps, hTtoBox->pIccDownmixIdx);
675      deQuantizeCoefFDK(hTtoBox->pIccDownmixIdx, nParamBands,
676                        hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset,
677                        IccDownmixQuant__FDK);
678
679      *pbIccQuantCoarse = hTtoBox->bUseCoarseQuantIcc;
680    }
681
682    /* quantize/de-quantize cld */
683    if (!bUseEbQ) {
684      QuantizeCoefFDK(hTtoBox->pCld__FDK, nParamBands,
685                      hTtoBox->pCldQuantTableEnc__FDK, hTtoBox->nCldQuantOffset,
686                      hTtoBox->nCldQuantSteps, pCldIdx);
687      deQuantizeCoefFDK(pCldIdx, nParamBands, hTtoBox->pCldQuantTableDec__FDK,
688                        hTtoBox->nCldQuantOffset, hTtoBox->pCldQuant__FDK);
689    } else {
690      FDKmemcpy(pCldIdx, hTtoBox->pCldEbQIdx, nParamBands * sizeof(SCHAR));
691    }
692    *pbCldQuantCoarse = hTtoBox->bUseCoarseQuantCld;
693
694  } /* valid handle */
695
696bail:
697  C_ALLOC_SCRATCH_END(pbScaleCh2, INT, MAX_NUM_PARAM_BANDS)
698  C_ALLOC_SCRATCH_END(pbScaleCh1, INT, MAX_NUM_PARAM_BANDS)
699  C_ALLOC_SCRATCH_END(IccDownmixQuant__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
700  C_ALLOC_SCRATCH_END(IccDownmix__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
701
702  C_ALLOC_SCRATCH_END(prodHybridDataImag__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
703  C_ALLOC_SCRATCH_END(prodHybridDataReal__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
704  C_ALLOC_SCRATCH_END(powerHybridData2__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
705  C_ALLOC_SCRATCH_END(powerHybridData1__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS)
706
707  return error;
708}
709
710INT fdk_sacenc_subband2ParamBand(const BOX_SUBBAND_CONFIG boxSubbandConfig,
711                                 const INT nSubband) {
712  INT nParamBand = -1;
713  const UCHAR *pSubband2ParameterIndex =
714      getSubband2ParameterIndex(boxSubbandConfig);
715
716  if (pSubband2ParameterIndex != NULL) {
717    const int hybrid_resolution = 64;
718
719    if ((nSubband > -1) && (nSubband < hybrid_resolution)) {
720      nParamBand = pSubband2ParameterIndex[nSubband];
721    }
722  }
723
724  return nParamBand;
725}
726