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 decoder library *************************
96
97   Author(s):
98
99   Description: SAC Dec M1 and M2 calculation
100
101*******************************************************************************/
102
103#include "sac_calcM1andM2.h"
104#include "sac_bitdec.h"
105#include "sac_process.h"
106#include "sac_rom.h"
107#include "sac_smoothing.h"
108#include "FDK_trigFcts.h"
109
110/* assorted definitions and constants */
111
112#define ABS_THR2 1.0e-9
113#define SQRT2_FDK \
114  ((FIXP_DBL)FL2FXCONST_DBL(0.70710678118f)) /* FDKsqrt(2.0) scaled by 0.5 */
115
116static void param2UMX_PS__FDK(spatialDec* self,
117                              FIXP_DBL H11[MAX_PARAMETER_BANDS],
118                              FIXP_DBL H12[MAX_PARAMETER_BANDS],
119                              FIXP_DBL H21[MAX_PARAMETER_BANDS],
120                              FIXP_DBL H22[MAX_PARAMETER_BANDS],
121                              FIXP_DBL c_l[MAX_PARAMETER_BANDS],
122                              FIXP_DBL c_r[MAX_PARAMETER_BANDS], int ottBoxIndx,
123                              int parameterSetIndx, int resBands);
124
125static void param2UMX_PS_Core__FDK(
126    const SCHAR cld[MAX_PARAMETER_BANDS], const SCHAR icc[MAX_PARAMETER_BANDS],
127    const int numOttBands, const int resBands,
128    FIXP_DBL H11[MAX_PARAMETER_BANDS], FIXP_DBL H12[MAX_PARAMETER_BANDS],
129    FIXP_DBL H21[MAX_PARAMETER_BANDS], FIXP_DBL H22[MAX_PARAMETER_BANDS],
130    FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS]);
131
132static void param2UMX_PS_IPD_OPD__FDK(
133    spatialDec* self, const SPATIAL_BS_FRAME* frame,
134    FIXP_DBL H11re[MAX_PARAMETER_BANDS], FIXP_DBL H12re[MAX_PARAMETER_BANDS],
135    FIXP_DBL H21re[MAX_PARAMETER_BANDS], FIXP_DBL H22re[MAX_PARAMETER_BANDS],
136    FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS],
137    int ottBoxIndx, int parameterSetIndx, int residualBands);
138
139static void param2UMX_Prediction__FDK(
140    spatialDec* self, FIXP_DBL H11re[MAX_PARAMETER_BANDS],
141    FIXP_DBL H11im[MAX_PARAMETER_BANDS], FIXP_DBL H12re[MAX_PARAMETER_BANDS],
142    FIXP_DBL H12im[MAX_PARAMETER_BANDS], FIXP_DBL H21re[MAX_PARAMETER_BANDS],
143    FIXP_DBL H21im[MAX_PARAMETER_BANDS], FIXP_DBL H22re[MAX_PARAMETER_BANDS],
144    FIXP_DBL H22im[MAX_PARAMETER_BANDS], int ottBoxIndx, int parameterSetIndx,
145    int resBands);
146
147/* static void SpatialDecCalculateM0(spatialDec* self,int ps); */
148static SACDEC_ERROR SpatialDecCalculateM1andM2_212(
149    spatialDec* self, int ps, const SPATIAL_BS_FRAME* frame);
150
151/*******************************************************************************
152 Functionname: SpatialDecGetResidualIndex
153 *******************************************************************************
154
155 Description:
156
157 Arguments:
158
159 Input:
160
161 Output:
162
163*******************************************************************************/
164int SpatialDecGetResidualIndex(spatialDec* self, int row) {
165  return row2residual[self->treeConfig][row];
166}
167
168/*******************************************************************************
169 Functionname: UpdateAlpha
170 *******************************************************************************
171
172 Description:
173
174 Arguments:
175
176 Input:
177
178 Output:
179
180*******************************************************************************/
181static void updateAlpha(spatialDec* self) {
182  int nChIn = self->numInputChannels;
183  int ch;
184
185  for (ch = 0; ch < nChIn; ch++) {
186    FIXP_DBL alpha = /* FL2FXCONST_DBL(1.0f) */ (FIXP_DBL)MAXVAL_DBL;
187
188    self->arbdmxAlphaPrev__FDK[ch] = self->arbdmxAlpha__FDK[ch];
189
190    self->arbdmxAlpha__FDK[ch] = alpha;
191  }
192}
193
194/*******************************************************************************
195 Functionname: SpatialDecCalculateM1andM2
196 *******************************************************************************
197 Description:
198 Arguments:
199*******************************************************************************/
200SACDEC_ERROR SpatialDecCalculateM1andM2(spatialDec* self, int ps,
201                                        const SPATIAL_BS_FRAME* frame) {
202  SACDEC_ERROR err = MPS_OK;
203
204  if ((self->arbitraryDownmix != 0) && (ps == 0)) {
205    updateAlpha(self);
206  }
207
208  self->pActivM2ParamBands = NULL;
209
210  switch (self->upmixType) {
211    case UPMIXTYPE_BYPASS:
212    case UPMIXTYPE_NORMAL:
213      switch (self->treeConfig) {
214        case TREE_212:
215          err = SpatialDecCalculateM1andM2_212(self, ps, frame);
216          break;
217        default:
218          err = MPS_WRONG_TREECONFIG;
219      };
220      break;
221
222    default:
223      err = MPS_WRONG_TREECONFIG;
224  }
225
226  if (err != MPS_OK) {
227    goto bail;
228  }
229
230bail:
231  return err;
232}
233
234/*******************************************************************************
235 Functionname: SpatialDecCalculateM1andM2_212
236 *******************************************************************************
237
238 Description:
239
240 Arguments:
241
242 Return:
243
244*******************************************************************************/
245static SACDEC_ERROR SpatialDecCalculateM1andM2_212(
246    spatialDec* self, int ps, const SPATIAL_BS_FRAME* frame) {
247  SACDEC_ERROR err = MPS_OK;
248  int pb;
249
250  FIXP_DBL H11re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)};
251  FIXP_DBL H12re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)};
252  FIXP_DBL H21re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)};
253  FIXP_DBL H22re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)};
254  FIXP_DBL H11im[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)};
255  FIXP_DBL H21im[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)};
256
257  INT phaseCoding = self->phaseCoding;
258
259  switch (phaseCoding) {
260    case 1:
261      /* phase coding: yes; residuals: no */
262      param2UMX_PS_IPD_OPD__FDK(self, frame, H11re, H12re, H21re, H22re, NULL,
263                                NULL, 0, ps, self->residualBands[0]);
264      break;
265    case 3:
266      /* phase coding: yes; residuals: yes */
267      param2UMX_Prediction__FDK(self, H11re, H11im, H12re, NULL, H21re, H21im,
268                                H22re, NULL, 0, ps, self->residualBands[0]);
269      break;
270    default:
271      if (self->residualCoding) {
272        /* phase coding: no; residuals: yes */
273        param2UMX_Prediction__FDK(self, H11re, NULL, H12re, NULL, H21re, NULL,
274                                  H22re, NULL, 0, ps, self->residualBands[0]);
275      } else {
276        /* phase coding: no; residuals: no */
277        param2UMX_PS__FDK(self, H11re, H12re, H21re, H22re, NULL, NULL, 0, ps,
278                          0);
279      }
280      break;
281  }
282
283  for (pb = 0; pb < self->numParameterBands; pb++) {
284    self->M2Real__FDK[0][0][pb] = (H11re[pb]);
285    self->M2Real__FDK[0][1][pb] = (H12re[pb]);
286
287    self->M2Real__FDK[1][0][pb] = (H21re[pb]);
288    self->M2Real__FDK[1][1][pb] = (H22re[pb]);
289  }
290  if (phaseCoding == 3) {
291    for (pb = 0; pb < self->numParameterBands; pb++) {
292      self->M2Imag__FDK[0][0][pb] = (H11im[pb]);
293      self->M2Imag__FDK[1][0][pb] = (H21im[pb]);
294      self->M2Imag__FDK[0][1][pb] = (FIXP_DBL)0;  // H12im[pb];
295      self->M2Imag__FDK[1][1][pb] = (FIXP_DBL)0;  // H22im[pb];
296    }
297  }
298
299  if (self->phaseCoding == 1) {
300    SpatialDecSmoothOPD(
301        self, frame,
302        ps); /* INPUT: PhaseLeft, PhaseRight, (opdLeftState, opdRightState) */
303  }
304
305  return err;
306}
307
308/*******************************************************************************
309 Functionname: param2UMX_PS_Core
310 *******************************************************************************
311
312 Description:
313
314 Arguments:
315
316 Return:
317
318*******************************************************************************/
319static void param2UMX_PS_Core__FDK(
320    const SCHAR cld[MAX_PARAMETER_BANDS], const SCHAR icc[MAX_PARAMETER_BANDS],
321    const int numOttBands, const int resBands,
322    FIXP_DBL H11[MAX_PARAMETER_BANDS], FIXP_DBL H12[MAX_PARAMETER_BANDS],
323    FIXP_DBL H21[MAX_PARAMETER_BANDS], FIXP_DBL H22[MAX_PARAMETER_BANDS],
324    FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS]) {
325  int band;
326
327  if ((c_l != NULL) && (c_r != NULL)) {
328    for (band = 0; band < numOttBands; band++) {
329      SpatialDequantGetCLDValues(cld[band], &c_l[band], &c_r[band]);
330    }
331  }
332
333  band = 0;
334  FDK_ASSERT(resBands == 0);
335  for (; band < numOttBands; band++) {
336    /* compute mixing variables: */
337    const int idx1 = cld[band];
338    const int idx2 = icc[band];
339    H11[band] = FX_CFG2FX_DBL(H11_nc[idx1][idx2]);
340    H21[band] = FX_CFG2FX_DBL(H11_nc[30 - idx1][idx2]);
341    H12[band] = FX_CFG2FX_DBL(H12_nc[idx1][idx2]);
342    H22[band] = FX_CFG2FX_DBL(-H12_nc[30 - idx1][idx2]);
343  }
344}
345
346/*******************************************************************************
347 Functionname: param2UMX_PS
348 *******************************************************************************
349
350 Description:
351
352 Arguments:
353
354 Return:
355
356*******************************************************************************/
357static void param2UMX_PS__FDK(spatialDec* self,
358                              FIXP_DBL H11[MAX_PARAMETER_BANDS],
359                              FIXP_DBL H12[MAX_PARAMETER_BANDS],
360                              FIXP_DBL H21[MAX_PARAMETER_BANDS],
361                              FIXP_DBL H22[MAX_PARAMETER_BANDS],
362                              FIXP_DBL c_l[MAX_PARAMETER_BANDS],
363                              FIXP_DBL c_r[MAX_PARAMETER_BANDS], int ottBoxIndx,
364                              int parameterSetIndx, int residualBands) {
365  int band;
366  param2UMX_PS_Core__FDK(self->ottCLD__FDK[ottBoxIndx][parameterSetIndx],
367                         self->ottICC__FDK[ottBoxIndx][parameterSetIndx],
368                         self->numOttBands[ottBoxIndx], residualBands, H11, H12,
369                         H21, H22, c_l, c_r);
370
371  for (band = self->numOttBands[ottBoxIndx]; band < self->numParameterBands;
372       band++) {
373    H11[band] = H21[band] = H12[band] = H22[band] = FL2FXCONST_DBL(0.f);
374  }
375}
376
377#define N_CLD (31)
378#define N_IPD (16)
379
380static const FIXP_DBL sinIpd_tab[N_IPD] = {
381    FIXP_DBL(0x00000000), FIXP_DBL(0x30fbc54e), FIXP_DBL(0x5a827999),
382    FIXP_DBL(0x7641af3d), FIXP_DBL(0x7fffffff), FIXP_DBL(0x7641af3d),
383    FIXP_DBL(0x5a82799a), FIXP_DBL(0x30fbc54d), FIXP_DBL(0xffffffff),
384    FIXP_DBL(0xcf043ab3), FIXP_DBL(0xa57d8666), FIXP_DBL(0x89be50c3),
385    FIXP_DBL(0x80000000), FIXP_DBL(0x89be50c3), FIXP_DBL(0xa57d8666),
386    FIXP_DBL(0xcf043ab2),
387};
388
389/* cosIpd[i] = sinIpd[(i+4)&15] */
390#define SIN_IPD(a) (sinIpd_tab[(a)])
391#define COS_IPD(a) (sinIpd_tab[((a) + 4) & 15])  //(cosIpd_tab[(a)])
392
393static const FIXP_SGL sqrt_one_minus_ICC2[8] = {
394    FL2FXCONST_SGL(0.0f),
395    FL2FXCONST_SGL(0.349329357483736f),
396    FL2FXCONST_SGL(0.540755219669676f),
397    FL2FXCONST_SGL(0.799309172723546f),
398    FL2FXCONST_SGL(0.929968187843004f),
399    FX_DBL2FXCONST_SGL(MAXVAL_DBL),
400    FL2FXCONST_SGL(0.80813303360276f),
401    FL2FXCONST_SGL(0.141067359796659f),
402};
403
404/* exponent of sqrt(CLD) */
405static const SCHAR sqrt_CLD_e[N_CLD] = {
406    -24, -7, -6, -5, -4, -4, -3, -3, -2, -2, -1, -1, 0, 0, 0, 1,
407    1,   1,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  7, 8, 25};
408
409static const FIXP_DBL sqrt_CLD_m[N_CLD] = {
410    FL2FXCONST_DBL(0.530542153566195f),
411    FL2FXCONST_DBL(0.719796896243647f),
412    FL2FXCONST_DBL(0.64f),
413    FL2FXCONST_DBL(0.569049411212455f),
414    FL2FXCONST_DBL(0.505964425626941f),
415    FL2FXCONST_DBL(0.899746120304559f),
416    FL2FXCONST_DBL(0.635462587779425f),
417    FL2FXCONST_DBL(0.897614763441571f),
418    FL2FXCONST_DBL(0.633957276984445f),
419    FL2FXCONST_DBL(0.895488455427336f),
420    FL2FXCONST_DBL(0.632455532033676f),
421    FL2FXCONST_DBL(0.796214341106995f),
422    FL2FXCONST_DBL(0.501187233627272f),
423    FL2FXCONST_DBL(0.630957344480193f),
424    FL2FXCONST_DBL(0.794328234724281f),
425    FL2FXCONST_DBL(0.5f),
426    FL2FXCONST_DBL(0.629462705897084f),
427    FL2FXCONST_DBL(0.792446596230557f),
428    FL2FXCONST_DBL(0.99763115748444f),
429    FL2FXCONST_DBL(0.627971607877395f),
430    FL2FXCONST_DBL(0.790569415042095f),
431    FL2FXCONST_DBL(0.558354490188704f),
432    FL2FXCONST_DBL(0.788696680600242f),
433    FL2FXCONST_DBL(0.557031836333591f),
434    FL2FXCONST_DBL(0.786828382371355f),
435    FL2FXCONST_DBL(0.555712315637163f),
436    FL2FXCONST_DBL(0.988211768802619f),
437    FL2FXCONST_DBL(0.87865832060992f),
438    FL2FXCONST_DBL(0.78125f),
439    FL2FXCONST_DBL(0.694640394546454f),
440    FL2FXCONST_DBL(0.942432183077448f),
441};
442
443static const FIXP_DBL CLD_m[N_CLD] = {
444    FL2FXCONST_DBL(0.281474976710656f),
445    FL2FXCONST_DBL(0.518107571841987f),
446    FL2FXCONST_DBL(0.4096f),
447    FL2FXCONST_DBL(0.323817232401242f),
448    FL2FXCONST_DBL(0.256f),
449    FL2FXCONST_DBL(0.809543081003105f),
450    FL2FXCONST_DBL(0.403812700467324f),
451    FL2FXCONST_DBL(0.805712263548267f),
452    FL2FXCONST_DBL(0.401901829041533f),
453    FL2FXCONST_DBL(0.801899573803636f),
454    FL2FXCONST_DBL(0.4f),
455    FL2FXCONST_DBL(0.633957276984445f),
456    FL2FXCONST_DBL(0.251188643150958f),
457    FL2FXCONST_DBL(0.398107170553497f),
458    FL2FXCONST_DBL(0.630957344480193f),
459    FL2FXCONST_DBL(0.25f),
460    FL2FXCONST_DBL(0.396223298115278f),
461    FL2FXCONST_DBL(0.627971607877395f),
462    FL2FXCONST_DBL(0.995267926383743f),
463    FL2FXCONST_DBL(0.394348340300121f),
464    FL2FXCONST_DBL(0.625f),
465    FL2FXCONST_DBL(0.311759736713887f),
466    FL2FXCONST_DBL(0.62204245398984f),
467    FL2FXCONST_DBL(0.310284466689172f),
468    FL2FXCONST_DBL(0.619098903305123f),
469    FL2FXCONST_DBL(0.308816177750818f),
470    FL2FXCONST_DBL(0.9765625f),
471    FL2FXCONST_DBL(0.772040444377046f),
472    FL2FXCONST_DBL(0.6103515625f),
473    FL2FXCONST_DBL(0.482525277735654f),
474    FL2FXCONST_DBL(0.888178419700125),
475};
476
477static FIXP_DBL dequantIPD_CLD_ICC_splitAngle__FDK_Function(INT ipdIdx,
478                                                            INT cldIdx,
479                                                            INT iccIdx) {
480  FIXP_DBL cld;
481  SpatialDequantGetCLD2Values(cldIdx, &cld);
482
483  /*const FIXP_DBL one_m = (FIXP_DBL)MAXVAL_DBL;
484  const int one_e = 0;*/
485  const FIXP_DBL one_m = FL2FXCONST_DBL(0.5f);
486  const int one_e = 1;
487  /* iidLin = sqrt(cld); */
488  FIXP_DBL iidLin_m = sqrt_CLD_m[cldIdx];
489  int iidLin_e = sqrt_CLD_e[cldIdx];
490  /* iidLin2 = cld; */
491  FIXP_DBL iidLin2_m = CLD_m[cldIdx];
492  int iidLin2_e = sqrt_CLD_e[cldIdx] << 1;
493  /* iidLin21 = iidLin2 + 1.0f; */
494  int iidLin21_e;
495  FIXP_DBL iidLin21_m =
496      fAddNorm(iidLin2_m, iidLin2_e, one_m, one_e, &iidLin21_e);
497  /* iidIcc2 = iidLin * icc * 2.0f; */
498  FIXP_CFG icc = dequantICC__FDK[iccIdx];
499  FIXP_DBL temp1_m, temp1c_m;
500  int temp1_e, temp1c_e;
501  temp1_m = fMult(iidLin_m, icc);
502  temp1_e = iidLin_e + 1;
503
504  FIXP_DBL cosIpd, sinIpd;
505  cosIpd = COS_IPD(ipdIdx);
506  sinIpd = SIN_IPD(ipdIdx);
507
508  temp1c_m = fMult(temp1_m, cosIpd);
509  temp1c_e = temp1_e;  //+cosIpd_e;
510
511  int temp2_e, temp3_e, inv_temp3_e, ratio_e;
512  FIXP_DBL temp2_m =
513      fAddNorm(iidLin21_m, iidLin21_e, temp1c_m, temp1c_e, &temp2_e);
514  FIXP_DBL temp3_m =
515      fAddNorm(iidLin21_m, iidLin21_e, temp1_m, temp1_e, &temp3_e);
516  /* calculate 1/temp3 needed later */
517  inv_temp3_e = temp3_e;
518  FIXP_DBL inv_temp3_m = invFixp(temp3_m, &inv_temp3_e);
519  FIXP_DBL ratio_m =
520      fAddNorm(fMult(inv_temp3_m, temp2_m), (inv_temp3_e + temp2_e),
521               FL2FXCONST_DBL(1e-9f), 0, &ratio_e);
522
523  int weight2_e, tempb_atan2_e;
524  FIXP_DBL weight2_m =
525      fPow(ratio_m, ratio_e, FL2FXCONST_DBL(0.5f), -1, &weight2_e);
526  /* atan2(w2*sinIpd, w1*iidLin + w2*cosIpd) = atan2(w2*sinIpd, (2 - w2)*iidLin
527   * + w2*cosIpd) = atan2(w2*sinIpd, 2*iidLin + w2*(cosIpd - iidLin)); */
528  /* tmpa_atan2 = w2*sinIpd; tmpb_atan2 = 2*iidLin + w2*(cosIpd - iidLin); */
529  FIXP_DBL tempb_atan2_m = iidLin_m;
530  tempb_atan2_e = iidLin_e + 1;
531  int add_tmp1_e = 0;
532  FIXP_DBL add_tmp1_m = fAddNorm(cosIpd, 0, -iidLin_m, iidLin_e, &add_tmp1_e);
533  FIXP_DBL add_tmp2_m = fMult(add_tmp1_m, weight2_m);
534  int add_tmp2_e = add_tmp1_e + weight2_e;
535  tempb_atan2_m = fAddNorm(tempb_atan2_m, tempb_atan2_e, add_tmp2_m, add_tmp2_e,
536                           &tempb_atan2_e);
537
538  FIXP_DBL tempa_atan2_m = fMult(weight2_m, sinIpd);
539  int tempa_atan2_e = weight2_e;  // + sinIpd_e;
540
541  if (tempa_atan2_e > tempb_atan2_e) {
542    tempb_atan2_m = (tempb_atan2_m >> (tempa_atan2_e - tempb_atan2_e));
543    tempb_atan2_e = tempa_atan2_e;
544  } else if (tempb_atan2_e > tempa_atan2_e) {
545    tempa_atan2_m = (tempa_atan2_m >> (tempb_atan2_e - tempa_atan2_e));
546  }
547
548  return fixp_atan2(tempa_atan2_m, tempb_atan2_m);
549}
550
551static void calculateOpd(spatialDec* self, INT ottBoxIndx, INT parameterSetIndx,
552                         FIXP_DBL opd[MAX_PARAMETER_BANDS]) {
553  INT band;
554
555  for (band = 0; band < self->numOttBandsIPD; band++) {
556    INT idxCld = self->ottCLD__FDK[ottBoxIndx][parameterSetIndx][band];
557    INT idxIpd = self->ottIPD__FDK[ottBoxIndx][parameterSetIndx][band];
558    INT idxIcc = self->ottICC__FDK[ottBoxIndx][parameterSetIndx][band];
559    FIXP_DBL cld, ipd;
560
561    ipd = FX_CFG2FX_DBL(dequantIPD__FDK[idxIpd]);
562
563    SpatialDequantGetCLD2Values(idxCld, &cld);
564
565    /* ipd(idxIpd==8) == PI */
566    if ((cld == FL2FXCONST_DBL(0.0f)) && (idxIpd == 8)) {
567      opd[2 * band] = FL2FXCONST_DBL(0.0f);
568    } else {
569      opd[2 * band] = (dequantIPD_CLD_ICC_splitAngle__FDK_Function(
570                           idxIpd, idxCld, idxIcc) >>
571                       (IPD_SCALE - AT2O_SF));
572    }
573    opd[2 * band + 1] = opd[2 * band] - ipd;
574  }
575}
576
577/* wrap phase in rad to the range of 0 <= x < 2*pi */
578static FIXP_DBL wrapPhase(FIXP_DBL phase) {
579  while (phase < (FIXP_DBL)0) phase += PIx2__IPD;
580  while (phase >= PIx2__IPD) phase -= PIx2__IPD;
581  FDK_ASSERT((phase >= (FIXP_DBL)0) && (phase < PIx2__IPD));
582
583  return phase;
584}
585
586/*******************************************************************************
587 Functionname: param2UMX_PS_IPD
588 *******************************************************************************
589
590 Description:
591
592 Arguments:
593
594 Return:
595
596*******************************************************************************/
597static void param2UMX_PS_IPD_OPD__FDK(
598    spatialDec* self, const SPATIAL_BS_FRAME* frame,
599    FIXP_DBL H11[MAX_PARAMETER_BANDS], FIXP_DBL H12[MAX_PARAMETER_BANDS],
600    FIXP_DBL H21[MAX_PARAMETER_BANDS], FIXP_DBL H22[MAX_PARAMETER_BANDS],
601    FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS],
602    int ottBoxIndx, int parameterSetIndx, int residualBands) {
603  INT band;
604  FIXP_DBL opd[2 * MAX_PARAMETER_BANDS];
605  INT numOttBands = self->numOttBands[ottBoxIndx];
606  INT numIpdBands;
607
608  numIpdBands = frame->phaseMode ? self->numOttBandsIPD : 0;
609
610  FDK_ASSERT(self->residualCoding == 0);
611
612  param2UMX_PS_Core__FDK(self->ottCLD__FDK[ottBoxIndx][parameterSetIndx],
613                         self->ottICC__FDK[ottBoxIndx][parameterSetIndx],
614                         self->numOttBands[ottBoxIndx], residualBands, H11, H12,
615                         H21, H22, c_l, c_r);
616
617  for (band = self->numOttBands[ottBoxIndx]; band < self->numParameterBands;
618       band++) {
619    H11[band] = H21[band] = H12[band] = H22[band] = FL2FXCONST_DBL(0.f);
620  }
621
622  if (frame->phaseMode) {
623    calculateOpd(self, ottBoxIndx, parameterSetIndx, opd);
624
625    for (band = 0; band < numIpdBands; band++) {
626      self->PhaseLeft__FDK[band] = wrapPhase(opd[2 * band]);
627      self->PhaseRight__FDK[band] = wrapPhase(opd[2 * band + 1]);
628    }
629  }
630
631  for (band = numIpdBands; band < numOttBands; band++) {
632    self->PhaseLeft__FDK[band] = FL2FXCONST_DBL(0.0f);
633    self->PhaseRight__FDK[band] = FL2FXCONST_DBL(0.0f);
634  }
635}
636
637FDK_INLINE void param2UMX_Prediction_Core__FDK(
638    FIXP_DBL* H11re, FIXP_DBL* H11im, FIXP_DBL* H12re, FIXP_DBL* H12im,
639    FIXP_DBL* H21re, FIXP_DBL* H21im, FIXP_DBL* H22re, FIXP_DBL* H22im,
640    int cldIdx, int iccIdx, int ipdIdx, int band, int numOttBandsIPD,
641    int resBands) {
642#define MAX_WEIGHT (1.2f)
643  FDK_ASSERT((H12im == NULL) && (H22im == NULL)); /* always == 0 */
644
645  if ((band < numOttBandsIPD) && (cldIdx == 15) && (iccIdx == 0) &&
646      (ipdIdx == 8)) {
647    const FIXP_DBL gain =
648        FL2FXCONST_DBL(0.5f / MAX_WEIGHT) >> SCALE_PARAM_M2_212_PRED;
649
650    *H11re = gain;
651    if (band < resBands) {
652      *H21re = gain;
653      *H12re = gain;
654      *H22re = -gain;
655    } else {
656      *H21re = -gain;
657      *H12re = (FIXP_DBL)0;
658      *H22re = (FIXP_DBL)0;
659    }
660    if ((H11im != NULL) &&
661        (H21im != NULL) /*&& (H12im!=NULL) && (H22im!=NULL)*/) {
662      *H11im = (FIXP_DBL)0;
663      *H21im = (FIXP_DBL)0;
664      /* *H12im = (FIXP_DBL)0; */
665      /* *H22im = (FIXP_DBL)0; */
666    }
667  } else {
668    const FIXP_DBL one_m = (FIXP_DBL)MAXVAL_DBL;
669    const int one_e = 0;
670    /* iidLin = sqrt(cld); */
671    FIXP_DBL iidLin_m = sqrt_CLD_m[cldIdx];
672    int iidLin_e = sqrt_CLD_e[cldIdx];
673    /* iidLin2 = cld; */
674    FIXP_DBL iidLin2_m = CLD_m[cldIdx];
675    int iidLin2_e = sqrt_CLD_e[cldIdx] << 1;
676    /* iidLin21 = iidLin2 + 1.0f; */
677    int iidLin21_e;
678    FIXP_DBL iidLin21_m =
679        fAddNorm(iidLin2_m, iidLin2_e, one_m, one_e, &iidLin21_e);
680    /* iidIcc2 = iidLin * icc * 2.0f; */
681    FIXP_CFG icc = dequantICC__FDK[iccIdx];
682    int iidIcc2_e = iidLin_e + 1;
683    FIXP_DBL iidIcc2_m = fMult(iidLin_m, icc);
684    FIXP_DBL temp_m, sqrt_temp_m, inv_temp_m, weight_m;
685    int temp_e, sqrt_temp_e, inv_temp_e, weight_e, scale;
686    FIXP_DBL cosIpd, sinIpd;
687
688    cosIpd = COS_IPD((band < numOttBandsIPD) ? ipdIdx : 0);
689    sinIpd = SIN_IPD((band < numOttBandsIPD) ? ipdIdx : 0);
690
691    /* temp    = iidLin21 + iidIcc2 * cosIpd; */
692    temp_m = fAddNorm(iidLin21_m, iidLin21_e, fMult(iidIcc2_m, cosIpd),
693                      iidIcc2_e, &temp_e);
694
695    /* calculate 1/temp needed later */
696    inv_temp_e = temp_e;
697    inv_temp_m = invFixp(temp_m, &inv_temp_e);
698
699    /* 1/weight = sqrt(temp) * 1/sqrt(iidLin21) */
700    if (temp_e & 1) {
701      sqrt_temp_m = temp_m >> 1;
702      sqrt_temp_e = (temp_e + 1) >> 1;
703    } else {
704      sqrt_temp_m = temp_m;
705      sqrt_temp_e = temp_e >> 1;
706    }
707    sqrt_temp_m = sqrtFixp(sqrt_temp_m);
708    if (iidLin21_e & 1) {
709      iidLin21_e += 1;
710      iidLin21_m >>= 1;
711    }
712    /* weight_[m,e] is actually 1/weight in the next few lines */
713    weight_m = invSqrtNorm2(iidLin21_m, &weight_e);
714    weight_e -= iidLin21_e >> 1;
715    weight_m = fMult(sqrt_temp_m, weight_m);
716    weight_e += sqrt_temp_e;
717    scale = fNorm(weight_m);
718    weight_m = scaleValue(weight_m, scale);
719    weight_e -= scale;
720    /* weight = 0.5 * max(1/weight, 1/maxWeight) */
721    if ((weight_e < 0) ||
722        ((weight_e == 0) && (weight_m < FL2FXCONST_DBL(1.f / MAX_WEIGHT)))) {
723      weight_m = FL2FXCONST_DBL(1.f / MAX_WEIGHT);
724      weight_e = 0;
725    }
726    weight_e -= 1;
727
728    {
729      FIXP_DBL alphaRe_m, alphaIm_m, accu_m;
730      int alphaRe_e, alphaIm_e, accu_e;
731      /* alphaRe = (1.0f - iidLin2) / temp; */
732      alphaRe_m = fAddNorm(one_m, one_e, -iidLin2_m, iidLin2_e, &alphaRe_e);
733      alphaRe_m = fMult(alphaRe_m, inv_temp_m);
734      alphaRe_e += inv_temp_e;
735
736      /* H11re = weight - alphaRe * weight; */
737      /* H21re = weight + alphaRe * weight; */
738      accu_m = fMult(alphaRe_m, weight_m);
739      accu_e = alphaRe_e + weight_e;
740      {
741        int accu2_e;
742        FIXP_DBL accu2_m;
743        accu2_m = fAddNorm(weight_m, weight_e, -accu_m, accu_e, &accu2_e);
744        *H11re = scaleValue(accu2_m, accu2_e - SCALE_PARAM_M2_212_PRED);
745        accu2_m = fAddNorm(weight_m, weight_e, accu_m, accu_e, &accu2_e);
746        *H21re = scaleValue(accu2_m, accu2_e - SCALE_PARAM_M2_212_PRED);
747      }
748
749      if ((H11im != NULL) &&
750          (H21im != NULL) /*&& (H12im != NULL) && (H22im != NULL)*/) {
751        /* alphaIm = -iidIcc2 * sinIpd / temp; */
752        alphaIm_m = fMult(-iidIcc2_m, sinIpd);
753        alphaIm_m = fMult(alphaIm_m, inv_temp_m);
754        alphaIm_e = iidIcc2_e + inv_temp_e;
755        /* H11im = -alphaIm * weight; */
756        /* H21im =  alphaIm * weight; */
757        accu_m = fMult(alphaIm_m, weight_m);
758        accu_e = alphaIm_e + weight_e;
759        accu_m = scaleValue(accu_m, accu_e - SCALE_PARAM_M2_212_PRED);
760        *H11im = -accu_m;
761        *H21im = accu_m;
762
763        /* *H12im = (FIXP_DBL)0; */
764        /* *H22im = (FIXP_DBL)0; */
765      }
766    }
767    if (band < resBands) {
768      FIXP_DBL weight =
769          scaleValue(weight_m, weight_e - SCALE_PARAM_M2_212_PRED);
770      *H12re = weight;
771      *H22re = -weight;
772    } else {
773      /* beta = 2.0f * iidLin * (float) sqrt(1.0f - icc * icc) * weight / temp;
774       */
775      FIXP_DBL beta_m;
776      int beta_e;
777      beta_m = FX_SGL2FX_DBL(sqrt_one_minus_ICC2[iccIdx]);
778      beta_e = 1; /* multipication with 2.0f */
779      beta_m = fMult(beta_m, weight_m);
780      beta_e += weight_e;
781      beta_m = fMult(beta_m, iidLin_m);
782      beta_e += iidLin_e;
783      beta_m = fMult(beta_m, inv_temp_m);
784      beta_e += inv_temp_e;
785
786      beta_m = scaleValue(beta_m, beta_e - SCALE_PARAM_M2_212_PRED);
787      *H12re = beta_m;
788      *H22re = -beta_m;
789    }
790  }
791}
792
793static void param2UMX_Prediction__FDK(spatialDec* self, FIXP_DBL* H11re,
794                                      FIXP_DBL* H11im, FIXP_DBL* H12re,
795                                      FIXP_DBL* H12im, FIXP_DBL* H21re,
796                                      FIXP_DBL* H21im, FIXP_DBL* H22re,
797                                      FIXP_DBL* H22im, int ottBoxIndx,
798                                      int parameterSetIndx, int resBands) {
799  int band;
800  FDK_ASSERT((H12im == NULL) && (H22im == NULL)); /* always == 0 */
801
802  for (band = 0; band < self->numParameterBands; band++) {
803    int cldIdx = self->ottCLD__FDK[ottBoxIndx][parameterSetIndx][band];
804    int iccIdx = self->ottICC__FDK[ottBoxIndx][parameterSetIndx][band];
805    int ipdIdx = self->ottIPD__FDK[ottBoxIndx][parameterSetIndx][band];
806
807    param2UMX_Prediction_Core__FDK(
808        &H11re[band], (H11im ? &H11im[band] : NULL), &H12re[band], NULL,
809        &H21re[band], (H21im ? &H21im[band] : NULL), &H22re[band], NULL, cldIdx,
810        iccIdx, ipdIdx, band, self->numOttBandsIPD, resBands);
811  }
812}
813
814/*******************************************************************************
815 Functionname:  initM1andM2
816 *******************************************************************************
817
818 Description:
819
820 Arguments:
821
822 Return:
823
824*******************************************************************************/
825
826SACDEC_ERROR initM1andM2(spatialDec* self, int initStatesFlag,
827                         int configChanged) {
828  SACDEC_ERROR err = MPS_OK;
829
830  self->bOverwriteM1M2prev = (configChanged && !initStatesFlag) ? 1 : 0;
831
832  { self->numM2rows = self->numOutputChannels; }
833
834  if (initStatesFlag) {
835    int i, j, k;
836
837    for (i = 0; i < self->numM2rows; i++) {
838      for (j = 0; j < self->numVChannels; j++) {
839        for (k = 0; k < MAX_PARAMETER_BANDS; k++) {
840          self->M2Real__FDK[i][j][k] = FL2FXCONST_DBL(0);
841          self->M2RealPrev__FDK[i][j][k] = FL2FXCONST_DBL(0);
842        }
843      }
844    }
845  }
846
847  return err;
848}
849