Home | History | Annotate | Download | only in src
      1 /* -----------------------------------------------------------------------------
      2 Software License for The Fraunhofer FDK AAC Codec Library for Android
      3 
      4  Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Frderung der angewandten
      5 Forschung e.V. All rights reserved.
      6 
      7  1.    INTRODUCTION
      8 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
      9 that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
     10 scheme for digital audio. This FDK AAC Codec software is intended to be used on
     11 a wide variety of Android devices.
     12 
     13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
     14 general perceptual audio codecs. AAC-ELD is considered the best-performing
     15 full-bandwidth communications codec by independent studies and is widely
     16 deployed. AAC has been standardized by ISO and IEC as part of the MPEG
     17 specifications.
     18 
     19 Patent licenses for necessary patent claims for the FDK AAC Codec (including
     20 those of Fraunhofer) may be obtained through Via Licensing
     21 (www.vialicensing.com) or through the respective patent owners individually for
     22 the purpose of encoding or decoding bit streams in products that are compliant
     23 with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
     24 Android devices already license these patent claims through Via Licensing or
     25 directly from the patent owners, and therefore FDK AAC Codec software may
     26 already be covered under those patent licenses when it is used for those
     27 licensed purposes only.
     28 
     29 Commercially-licensed AAC software libraries, including floating-point versions
     30 with enhanced sound quality, are also available from Fraunhofer. Users are
     31 encouraged to check the Fraunhofer website for additional applications
     32 information and documentation.
     33 
     34 2.    COPYRIGHT LICENSE
     35 
     36 Redistribution and use in source and binary forms, with or without modification,
     37 are permitted without payment of copyright license fees provided that you
     38 satisfy the following conditions:
     39 
     40 You must retain the complete text of this software license in redistributions of
     41 the FDK AAC Codec or your modifications thereto in source code form.
     42 
     43 You must retain the complete text of this software license in the documentation
     44 and/or other materials provided with redistributions of the FDK AAC Codec or
     45 your modifications thereto in binary form. You must make available free of
     46 charge copies of the complete source code of the FDK AAC Codec and your
     47 modifications thereto to recipients of copies in binary form.
     48 
     49 The name of Fraunhofer may not be used to endorse or promote products derived
     50 from this library without prior written permission.
     51 
     52 You may not charge copyright license fees for anyone to use, copy or distribute
     53 the FDK AAC Codec software or your modifications thereto.
     54 
     55 Your modified versions of the FDK AAC Codec must carry prominent notices stating
     56 that you changed the software and the date of any change. For modified versions
     57 of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
     58 must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
     59 AAC Codec Library for Android."
     60 
     61 3.    NO PATENT LICENSE
     62 
     63 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
     64 limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
     65 Fraunhofer provides no warranty of patent non-infringement with respect to this
     66 software.
     67 
     68 You may use this FDK AAC Codec software or modifications thereto only for
     69 purposes that are authorized by appropriate patent licenses.
     70 
     71 4.    DISCLAIMER
     72 
     73 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
     74 holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
     75 including but not limited to the implied warranties of merchantability and
     76 fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     77 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
     78 or consequential damages, including but not limited to procurement of substitute
     79 goods or services; loss of use, data, or profits, or business interruption,
     80 however caused and on any theory of liability, whether in contract, strict
     81 liability, or tort (including negligence), arising in any way out of the use of
     82 this software, even if advised of the possibility of such damage.
     83 
     84 5.    CONTACT INFORMATION
     85 
     86 Fraunhofer Institute for Integrated Circuits IIS
     87 Attention: Audio and Multimedia Departments - FDK AAC LL
     88 Am Wolfsmantel 33
     89 91058 Erlangen, Germany
     90 
     91 www.iis.fraunhofer.de/amm
     92 amm-info (at) 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 
    116 static 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 
    125 static 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 
    132 static 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 
    139 static 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); */
    148 static 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 *******************************************************************************/
    164 int 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 *******************************************************************************/
    181 static 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 *******************************************************************************/
    200 SACDEC_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 
    230 bail:
    231   return err;
    232 }
    233 
    234 /*******************************************************************************
    235  Functionname: SpatialDecCalculateM1andM2_212
    236  *******************************************************************************
    237 
    238  Description:
    239 
    240  Arguments:
    241 
    242  Return:
    243 
    244 *******************************************************************************/
    245 static 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 *******************************************************************************/
    319 static 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 *******************************************************************************/
    357 static 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 
    380 static 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 
    393 static 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) */
    405 static 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 
    409 static 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 
    443 static 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 
    477 static void calculateOpd(spatialDec* self, INT ottBoxIndx, INT parameterSetIndx,
    478                          FIXP_DBL opd[MAX_PARAMETER_BANDS]) {
    479   INT band;
    480 
    481   for (band = 0; band < self->numOttBandsIPD; band++) {
    482     INT idxCld = self->ottCLD__FDK[ottBoxIndx][parameterSetIndx][band];
    483     INT idxIpd = self->ottIPD__FDK[ottBoxIndx][parameterSetIndx][band];
    484     INT idxIcc = self->ottICC__FDK[ottBoxIndx][parameterSetIndx][band];
    485     FIXP_DBL cld, ipd;
    486 
    487     ipd = FX_CFG2FX_DBL(dequantIPD__FDK[idxIpd]);
    488 
    489     SpatialDequantGetCLD2Values(idxCld, &cld);
    490 
    491     /* ipd(idxIpd==8) == PI */
    492     if (((cld == FL2FXCONST_DBL(0.0f)) && (idxIpd == 8)) || (idxIpd == 0)) {
    493       opd[2 * band] = FL2FXCONST_DBL(0.0f);
    494     } else {
    495       FDK_ASSERT(idxIpd > 0);
    496       opd[2 * band] =
    497           dequantIPD_CLD_ICC_splitAngle__FDK[idxIpd - 1][idxCld][idxIcc];
    498     }
    499     opd[2 * band + 1] = opd[2 * band] - ipd;
    500   }
    501 }
    502 
    503 /* wrap phase in rad to the range of 0 <= x < 2*pi */
    504 static FIXP_DBL wrapPhase(FIXP_DBL phase) {
    505   while (phase < (FIXP_DBL)0) phase += PIx2__IPD;
    506   while (phase >= PIx2__IPD) phase -= PIx2__IPD;
    507   FDK_ASSERT((phase >= (FIXP_DBL)0) && (phase < PIx2__IPD));
    508 
    509   return phase;
    510 }
    511 
    512 /*******************************************************************************
    513  Functionname: param2UMX_PS_IPD
    514  *******************************************************************************
    515 
    516  Description:
    517 
    518  Arguments:
    519 
    520  Return:
    521 
    522 *******************************************************************************/
    523 static void param2UMX_PS_IPD_OPD__FDK(
    524     spatialDec* self, const SPATIAL_BS_FRAME* frame,
    525     FIXP_DBL H11[MAX_PARAMETER_BANDS], FIXP_DBL H12[MAX_PARAMETER_BANDS],
    526     FIXP_DBL H21[MAX_PARAMETER_BANDS], FIXP_DBL H22[MAX_PARAMETER_BANDS],
    527     FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS],
    528     int ottBoxIndx, int parameterSetIndx, int residualBands) {
    529   INT band;
    530   FIXP_DBL opd[2 * MAX_PARAMETER_BANDS];
    531   INT numOttBands = self->numOttBands[ottBoxIndx];
    532   INT numIpdBands;
    533 
    534   numIpdBands = frame->phaseMode ? self->numOttBandsIPD : 0;
    535 
    536   FDK_ASSERT(self->residualCoding == 0);
    537 
    538   param2UMX_PS_Core__FDK(self->ottCLD__FDK[ottBoxIndx][parameterSetIndx],
    539                          self->ottICC__FDK[ottBoxIndx][parameterSetIndx],
    540                          self->numOttBands[ottBoxIndx], residualBands, H11, H12,
    541                          H21, H22, c_l, c_r);
    542 
    543   for (band = self->numOttBands[ottBoxIndx]; band < self->numParameterBands;
    544        band++) {
    545     H11[band] = H21[band] = H12[band] = H22[band] = FL2FXCONST_DBL(0.f);
    546   }
    547 
    548   if (frame->phaseMode) {
    549     calculateOpd(self, ottBoxIndx, parameterSetIndx, opd);
    550 
    551     for (band = 0; band < numIpdBands; band++) {
    552       self->PhaseLeft__FDK[band] = wrapPhase(opd[2 * band]);
    553       self->PhaseRight__FDK[band] = wrapPhase(opd[2 * band + 1]);
    554     }
    555   }
    556 
    557   for (band = numIpdBands; band < numOttBands; band++) {
    558     self->PhaseLeft__FDK[band] = FL2FXCONST_DBL(0.0f);
    559     self->PhaseRight__FDK[band] = FL2FXCONST_DBL(0.0f);
    560   }
    561 }
    562 
    563 FDK_INLINE void param2UMX_Prediction_Core__FDK(
    564     FIXP_DBL* H11re, FIXP_DBL* H11im, FIXP_DBL* H12re, FIXP_DBL* H12im,
    565     FIXP_DBL* H21re, FIXP_DBL* H21im, FIXP_DBL* H22re, FIXP_DBL* H22im,
    566     int cldIdx, int iccIdx, int ipdIdx, int band, int numOttBandsIPD,
    567     int resBands) {
    568 #define MAX_WEIGHT (1.2f)
    569   FDK_ASSERT((H12im == NULL) && (H22im == NULL)); /* always == 0 */
    570 
    571   if ((band < numOttBandsIPD) && (cldIdx == 15) && (iccIdx == 0) &&
    572       (ipdIdx == 8)) {
    573     const FIXP_DBL gain =
    574         FL2FXCONST_DBL(0.5f / MAX_WEIGHT) >> SCALE_PARAM_M2_212_PRED;
    575 
    576     *H11re = gain;
    577     if (band < resBands) {
    578       *H21re = gain;
    579       *H12re = gain;
    580       *H22re = -gain;
    581     } else {
    582       *H21re = -gain;
    583       *H12re = (FIXP_DBL)0;
    584       *H22re = (FIXP_DBL)0;
    585     }
    586     if ((H11im != NULL) &&
    587         (H21im != NULL) /*&& (H12im!=NULL) && (H22im!=NULL)*/) {
    588       *H11im = (FIXP_DBL)0;
    589       *H21im = (FIXP_DBL)0;
    590       /* *H12im = (FIXP_DBL)0; */
    591       /* *H22im = (FIXP_DBL)0; */
    592     }
    593   } else {
    594     const FIXP_DBL one_m = (FIXP_DBL)MAXVAL_DBL;
    595     const int one_e = 0;
    596     /* iidLin = sqrt(cld); */
    597     FIXP_DBL iidLin_m = sqrt_CLD_m[cldIdx];
    598     int iidLin_e = sqrt_CLD_e[cldIdx];
    599     /* iidLin2 = cld; */
    600     FIXP_DBL iidLin2_m = CLD_m[cldIdx];
    601     int iidLin2_e = sqrt_CLD_e[cldIdx] << 1;
    602     /* iidLin21 = iidLin2 + 1.0f; */
    603     int iidLin21_e;
    604     FIXP_DBL iidLin21_m =
    605         fAddNorm(iidLin2_m, iidLin2_e, one_m, one_e, &iidLin21_e);
    606     /* iidIcc2 = iidLin * icc * 2.0f; */
    607     FIXP_CFG icc = dequantICC__FDK[iccIdx];
    608     int iidIcc2_e = iidLin_e + 1;
    609     FIXP_DBL iidIcc2_m = fMult(iidLin_m, icc);
    610     FIXP_DBL temp_m, sqrt_temp_m, inv_temp_m, weight_m;
    611     int temp_e, sqrt_temp_e, inv_temp_e, weight_e, scale;
    612     FIXP_DBL cosIpd, sinIpd;
    613 
    614     cosIpd = COS_IPD((band < numOttBandsIPD) ? ipdIdx : 0);
    615     sinIpd = SIN_IPD((band < numOttBandsIPD) ? ipdIdx : 0);
    616 
    617     /* temp    = iidLin21 + iidIcc2 * cosIpd; */
    618     temp_m = fAddNorm(iidLin21_m, iidLin21_e, fMult(iidIcc2_m, cosIpd),
    619                       iidIcc2_e, &temp_e);
    620 
    621     /* calculate 1/temp needed later */
    622     inv_temp_e = temp_e;
    623     inv_temp_m = invFixp(temp_m, &inv_temp_e);
    624 
    625     /* 1/weight = sqrt(temp) * 1/sqrt(iidLin21) */
    626     if (temp_e & 1) {
    627       sqrt_temp_m = temp_m >> 1;
    628       sqrt_temp_e = (temp_e + 1) >> 1;
    629     } else {
    630       sqrt_temp_m = temp_m;
    631       sqrt_temp_e = temp_e >> 1;
    632     }
    633     sqrt_temp_m = sqrtFixp(sqrt_temp_m);
    634     if (iidLin21_e & 1) {
    635       iidLin21_e += 1;
    636       iidLin21_m >>= 1;
    637     }
    638     /* weight_[m,e] is actually 1/weight in the next few lines */
    639     weight_m = invSqrtNorm2(iidLin21_m, &weight_e);
    640     weight_e -= iidLin21_e >> 1;
    641     weight_m = fMult(sqrt_temp_m, weight_m);
    642     weight_e += sqrt_temp_e;
    643     scale = fNorm(weight_m);
    644     weight_m = scaleValue(weight_m, scale);
    645     weight_e -= scale;
    646     /* weight = 0.5 * max(1/weight, 1/maxWeight) */
    647     if ((weight_e < 0) ||
    648         ((weight_e == 0) && (weight_m < FL2FXCONST_DBL(1.f / MAX_WEIGHT)))) {
    649       weight_m = FL2FXCONST_DBL(1.f / MAX_WEIGHT);
    650       weight_e = 0;
    651     }
    652     weight_e -= 1;
    653 
    654     {
    655       FIXP_DBL alphaRe_m, alphaIm_m, accu_m;
    656       int alphaRe_e, alphaIm_e, accu_e;
    657       /* alphaRe = (1.0f - iidLin2) / temp; */
    658       alphaRe_m = fAddNorm(one_m, one_e, -iidLin2_m, iidLin2_e, &alphaRe_e);
    659       alphaRe_m = fMult(alphaRe_m, inv_temp_m);
    660       alphaRe_e += inv_temp_e;
    661 
    662       /* H11re = weight - alphaRe * weight; */
    663       /* H21re = weight + alphaRe * weight; */
    664       accu_m = fMult(alphaRe_m, weight_m);
    665       accu_e = alphaRe_e + weight_e;
    666       {
    667         int accu2_e;
    668         FIXP_DBL accu2_m;
    669         accu2_m = fAddNorm(weight_m, weight_e, -accu_m, accu_e, &accu2_e);
    670         *H11re = scaleValue(accu2_m, accu2_e - SCALE_PARAM_M2_212_PRED);
    671         accu2_m = fAddNorm(weight_m, weight_e, accu_m, accu_e, &accu2_e);
    672         *H21re = scaleValue(accu2_m, accu2_e - SCALE_PARAM_M2_212_PRED);
    673       }
    674 
    675       if ((H11im != NULL) &&
    676           (H21im != NULL) /*&& (H12im != NULL) && (H22im != NULL)*/) {
    677         /* alphaIm = -iidIcc2 * sinIpd / temp; */
    678         alphaIm_m = fMult(-iidIcc2_m, sinIpd);
    679         alphaIm_m = fMult(alphaIm_m, inv_temp_m);
    680         alphaIm_e = iidIcc2_e + inv_temp_e;
    681         /* H11im = -alphaIm * weight; */
    682         /* H21im =  alphaIm * weight; */
    683         accu_m = fMult(alphaIm_m, weight_m);
    684         accu_e = alphaIm_e + weight_e;
    685         accu_m = scaleValue(accu_m, accu_e - SCALE_PARAM_M2_212_PRED);
    686         *H11im = -accu_m;
    687         *H21im = accu_m;
    688 
    689         /* *H12im = (FIXP_DBL)0; */
    690         /* *H22im = (FIXP_DBL)0; */
    691       }
    692     }
    693     if (band < resBands) {
    694       FIXP_DBL weight =
    695           scaleValue(weight_m, weight_e - SCALE_PARAM_M2_212_PRED);
    696       *H12re = weight;
    697       *H22re = -weight;
    698     } else {
    699       /* beta = 2.0f * iidLin * (float) sqrt(1.0f - icc * icc) * weight / temp;
    700        */
    701       FIXP_DBL beta_m;
    702       int beta_e;
    703       beta_m = FX_SGL2FX_DBL(sqrt_one_minus_ICC2[iccIdx]);
    704       beta_e = 1; /* multipication with 2.0f */
    705       beta_m = fMult(beta_m, weight_m);
    706       beta_e += weight_e;
    707       beta_m = fMult(beta_m, iidLin_m);
    708       beta_e += iidLin_e;
    709       beta_m = fMult(beta_m, inv_temp_m);
    710       beta_e += inv_temp_e;
    711 
    712       beta_m = scaleValue(beta_m, beta_e - SCALE_PARAM_M2_212_PRED);
    713       *H12re = beta_m;
    714       *H22re = -beta_m;
    715     }
    716   }
    717 }
    718 
    719 static void param2UMX_Prediction__FDK(spatialDec* self, FIXP_DBL* H11re,
    720                                       FIXP_DBL* H11im, FIXP_DBL* H12re,
    721                                       FIXP_DBL* H12im, FIXP_DBL* H21re,
    722                                       FIXP_DBL* H21im, FIXP_DBL* H22re,
    723                                       FIXP_DBL* H22im, int ottBoxIndx,
    724                                       int parameterSetIndx, int resBands) {
    725   int band;
    726   FDK_ASSERT((H12im == NULL) && (H22im == NULL)); /* always == 0 */
    727 
    728   for (band = 0; band < self->numParameterBands; band++) {
    729     int cldIdx = self->ottCLD__FDK[ottBoxIndx][parameterSetIndx][band];
    730     int iccIdx = self->ottICC__FDK[ottBoxIndx][parameterSetIndx][band];
    731     int ipdIdx = self->ottIPD__FDK[ottBoxIndx][parameterSetIndx][band];
    732 
    733     param2UMX_Prediction_Core__FDK(
    734         &H11re[band], (H11im ? &H11im[band] : NULL), &H12re[band], NULL,
    735         &H21re[band], (H21im ? &H21im[band] : NULL), &H22re[band], NULL, cldIdx,
    736         iccIdx, ipdIdx, band, self->numOttBandsIPD, resBands);
    737   }
    738 }
    739 
    740 /*******************************************************************************
    741  Functionname:  initM1andM2
    742  *******************************************************************************
    743 
    744  Description:
    745 
    746  Arguments:
    747 
    748  Return:
    749 
    750 *******************************************************************************/
    751 
    752 SACDEC_ERROR initM1andM2(spatialDec* self, int initStatesFlag,
    753                          int configChanged) {
    754   SACDEC_ERROR err = MPS_OK;
    755 
    756   self->bOverwriteM1M2prev = (configChanged && !initStatesFlag) ? 1 : 0;
    757 
    758   { self->numM2rows = self->numOutputChannels; }
    759 
    760   if (initStatesFlag) {
    761     int i, j, k;
    762 
    763     for (i = 0; i < self->numM2rows; i++) {
    764       for (j = 0; j < self->numVChannels; j++) {
    765         for (k = 0; k < MAX_PARAMETER_BANDS; k++) {
    766           self->M2Real__FDK[i][j][k] = FL2FXCONST_DBL(0);
    767           self->M2RealPrev__FDK[i][j][k] = FL2FXCONST_DBL(0);
    768         }
    769       }
    770     }
    771   }
    772 
    773   return err;
    774 }
    775