Home | History | Annotate | Download | only in src
      1 /* -----------------------------------------------------------------------------
      2 Software License for The Fraunhofer FDK AAC Codec Library for Android
      3 
      4  Copyright  1995 - 2018 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 /**************************** AAC decoder library ******************************
     96 
     97    Author(s):   Josef Hoepfl
     98 
     99    Description: joint stereo processing
    100 
    101 *******************************************************************************/
    102 
    103 #include "stereo.h"
    104 
    105 #include "aac_rom.h"
    106 #include "FDK_bitstream.h"
    107 #include "channelinfo.h"
    108 #include "FDK_audio.h"
    109 
    110 enum { L = 0, R = 1 };
    111 
    112 #include "block.h"
    113 
    114 int CJointStereo_Read(HANDLE_FDK_BITSTREAM bs,
    115                       CJointStereoData *pJointStereoData,
    116                       const int windowGroups,
    117                       const int scaleFactorBandsTransmitted,
    118                       const int max_sfb_ste_clear,
    119                       CJointStereoPersistentData *pJointStereoPersistentData,
    120                       CCplxPredictionData *cplxPredictionData,
    121                       int cplxPredictionActiv, int scaleFactorBandsTotal,
    122                       int windowSequence, const UINT flags) {
    123   int group, band;
    124 
    125   pJointStereoData->MsMaskPresent = (UCHAR)FDKreadBits(bs, 2);
    126 
    127   FDKmemclear(pJointStereoData->MsUsed,
    128               scaleFactorBandsTransmitted * sizeof(UCHAR));
    129 
    130   pJointStereoData->cplx_pred_flag = 0;
    131   if (cplxPredictionActiv) {
    132     cplxPredictionData->pred_dir = 0;
    133     cplxPredictionData->complex_coef = 0;
    134     cplxPredictionData->use_prev_frame = 0;
    135     cplxPredictionData->igf_pred_dir = 0;
    136   }
    137 
    138   switch (pJointStereoData->MsMaskPresent) {
    139     case 0: /* no M/S */
    140       /* all flags are already cleared */
    141       break;
    142 
    143     case 1: /* read ms_used */
    144       for (group = 0; group < windowGroups; group++) {
    145         for (band = 0; band < scaleFactorBandsTransmitted; band++) {
    146           pJointStereoData->MsUsed[band] |= (FDKreadBits(bs, 1) << group);
    147         }
    148       }
    149       break;
    150 
    151     case 2: /* full spectrum M/S */
    152       for (band = 0; band < scaleFactorBandsTransmitted; band++) {
    153         pJointStereoData->MsUsed[band] = 255; /* set all flags to 1 */
    154       }
    155       break;
    156 
    157     case 3:
    158       /* M/S coding is disabled, complex stereo prediction is enabled */
    159       if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) {
    160         if (cplxPredictionActiv) { /* 'if (stereoConfigIndex == 0)' */
    161 
    162           pJointStereoData->cplx_pred_flag = 1;
    163 
    164           /* cplx_pred_data()  cp. ISO/IEC FDIS 23003-3:2011(E)  Table 26 */
    165           int cplx_pred_all = 0; /* local use only */
    166           cplx_pred_all = FDKreadBits(bs, 1);
    167 
    168           if (cplx_pred_all) {
    169             for (group = 0; group < windowGroups; group++) {
    170               UCHAR groupmask = ((UCHAR)1 << group);
    171               for (band = 0; band < scaleFactorBandsTransmitted; band++) {
    172                 pJointStereoData->MsUsed[band] |= groupmask;
    173               }
    174             }
    175           } else {
    176             for (group = 0; group < windowGroups; group++) {
    177               for (band = 0; band < scaleFactorBandsTransmitted;
    178                    band += SFB_PER_PRED_BAND) {
    179                 pJointStereoData->MsUsed[band] |= (FDKreadBits(bs, 1) << group);
    180                 if ((band + 1) < scaleFactorBandsTotal) {
    181                   pJointStereoData->MsUsed[band + 1] |=
    182                       (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group));
    183                 }
    184               }
    185             }
    186           }
    187         } else {
    188           return -1;
    189         }
    190       }
    191       break;
    192   }
    193 
    194   if (cplxPredictionActiv) {
    195     /* If all sfb are MS-ed then no complex prediction */
    196     if (pJointStereoData->MsMaskPresent == 3) {
    197       if (pJointStereoData->cplx_pred_flag) {
    198         int delta_code_time = 0;
    199 
    200         /* set pointer to Huffman codebooks */
    201         const CodeBookDescription *hcb = &AACcodeBookDescriptionTable[BOOKSCL];
    202         /* set predictors to zero in case of a transition from long to short
    203          * window sequences and vice versa */
    204         if (((windowSequence == BLOCK_SHORT) &&
    205              (pJointStereoPersistentData->winSeqPrev != BLOCK_SHORT)) ||
    206             ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) &&
    207              (windowSequence != BLOCK_SHORT))) {
    208           FDKmemclear(pJointStereoPersistentData->alpha_q_re_prev,
    209                       JointStereoMaximumGroups * JointStereoMaximumBands *
    210                           sizeof(SHORT));
    211           FDKmemclear(pJointStereoPersistentData->alpha_q_im_prev,
    212                       JointStereoMaximumGroups * JointStereoMaximumBands *
    213                           sizeof(SHORT));
    214         }
    215         {
    216           FDKmemclear(cplxPredictionData->alpha_q_re,
    217                       JointStereoMaximumGroups * JointStereoMaximumBands *
    218                           sizeof(SHORT));
    219           FDKmemclear(cplxPredictionData->alpha_q_im,
    220                       JointStereoMaximumGroups * JointStereoMaximumBands *
    221                           sizeof(SHORT));
    222         }
    223 
    224         /* 0 = mid->side prediction, 1 = side->mid prediction */
    225         cplxPredictionData->pred_dir = FDKreadBits(bs, 1);
    226         cplxPredictionData->complex_coef = FDKreadBits(bs, 1);
    227 
    228         if (cplxPredictionData->complex_coef) {
    229           if (flags & AC_INDEP) {
    230             cplxPredictionData->use_prev_frame = 0;
    231           } else {
    232             cplxPredictionData->use_prev_frame = FDKreadBits(bs, 1);
    233           }
    234         }
    235 
    236         if (flags & AC_INDEP) {
    237           delta_code_time = 0;
    238         } else {
    239           delta_code_time = FDKreadBits(bs, 1);
    240         }
    241 
    242         {
    243           int last_alpha_q_re = 0, last_alpha_q_im = 0;
    244 
    245           for (group = 0; group < windowGroups; group++) {
    246             for (band = 0; band < scaleFactorBandsTransmitted;
    247                  band += SFB_PER_PRED_BAND) {
    248               if (delta_code_time == 1) {
    249                 if (group > 0) {
    250                   last_alpha_q_re =
    251                       cplxPredictionData->alpha_q_re[group - 1][band];
    252                   last_alpha_q_im =
    253                       cplxPredictionData->alpha_q_im[group - 1][band];
    254                 } else if ((windowSequence == BLOCK_SHORT) &&
    255                            (pJointStereoPersistentData->winSeqPrev ==
    256                             BLOCK_SHORT)) {
    257                   /* Included for error-robustness */
    258                   if (pJointStereoPersistentData->winGroupsPrev == 0) return -1;
    259 
    260                   last_alpha_q_re =
    261                       pJointStereoPersistentData->alpha_q_re_prev
    262                           [pJointStereoPersistentData->winGroupsPrev - 1][band];
    263                   last_alpha_q_im =
    264                       pJointStereoPersistentData->alpha_q_im_prev
    265                           [pJointStereoPersistentData->winGroupsPrev - 1][band];
    266                 } else {
    267                   last_alpha_q_re =
    268                       pJointStereoPersistentData->alpha_q_re_prev[group][band];
    269                   last_alpha_q_im =
    270                       pJointStereoPersistentData->alpha_q_im_prev[group][band];
    271                 }
    272 
    273               } else {
    274                 if (band > 0) {
    275                   last_alpha_q_re =
    276                       cplxPredictionData->alpha_q_re[group][band - 1];
    277                   last_alpha_q_im =
    278                       cplxPredictionData->alpha_q_im[group][band - 1];
    279                 } else {
    280                   last_alpha_q_re = 0;
    281                   last_alpha_q_im = 0;
    282                 }
    283 
    284               } /* if (delta_code_time == 1) */
    285 
    286               if (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group)) {
    287                 int dpcm_alpha_re, dpcm_alpha_im;
    288 
    289                 dpcm_alpha_re = CBlock_DecodeHuffmanWord(bs, hcb);
    290                 dpcm_alpha_re -= 60;
    291                 dpcm_alpha_re *= -1;
    292 
    293                 cplxPredictionData->alpha_q_re[group][band] =
    294                     dpcm_alpha_re + last_alpha_q_re;
    295 
    296                 if (cplxPredictionData->complex_coef) {
    297                   dpcm_alpha_im = CBlock_DecodeHuffmanWord(bs, hcb);
    298                   dpcm_alpha_im -= 60;
    299                   dpcm_alpha_im *= -1;
    300 
    301                   cplxPredictionData->alpha_q_im[group][band] =
    302                       dpcm_alpha_im + last_alpha_q_im;
    303                 } else {
    304                   cplxPredictionData->alpha_q_im[group][band] = 0;
    305                 }
    306 
    307               } else {
    308                 cplxPredictionData->alpha_q_re[group][band] = 0;
    309                 cplxPredictionData->alpha_q_im[group][band] = 0;
    310               } /* if (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group)) */
    311 
    312               if ((band + 1) <
    313                   scaleFactorBandsTransmitted) { /* <= this should be the
    314                                                     correct way (cp.
    315                                                     ISO_IEC_FDIS_23003-0(E) */
    316                 /*    7.7.2.3.2 Decoding of prediction coefficients) */
    317                 cplxPredictionData->alpha_q_re[group][band + 1] =
    318                     cplxPredictionData->alpha_q_re[group][band];
    319                 cplxPredictionData->alpha_q_im[group][band + 1] =
    320                     cplxPredictionData->alpha_q_im[group][band];
    321               } /* if ((band+1)<scaleFactorBandsTotal) */
    322 
    323               pJointStereoPersistentData->alpha_q_re_prev[group][band] =
    324                   cplxPredictionData->alpha_q_re[group][band];
    325               pJointStereoPersistentData->alpha_q_im_prev[group][band] =
    326                   cplxPredictionData->alpha_q_im[group][band];
    327             }
    328 
    329             for (band = scaleFactorBandsTransmitted; band < max_sfb_ste_clear;
    330                  band++) {
    331               cplxPredictionData->alpha_q_re[group][band] = 0;
    332               cplxPredictionData->alpha_q_im[group][band] = 0;
    333               pJointStereoPersistentData->alpha_q_re_prev[group][band] = 0;
    334               pJointStereoPersistentData->alpha_q_im_prev[group][band] = 0;
    335             }
    336           }
    337         }
    338       }
    339     } else {
    340       for (group = 0; group < windowGroups; group++) {
    341         for (band = 0; band < max_sfb_ste_clear; band++) {
    342           pJointStereoPersistentData->alpha_q_re_prev[group][band] = 0;
    343           pJointStereoPersistentData->alpha_q_im_prev[group][band] = 0;
    344         }
    345       }
    346     }
    347 
    348     pJointStereoPersistentData->winGroupsPrev = windowGroups;
    349   }
    350 
    351   return 0;
    352 }
    353 
    354 static void CJointStereo_filterAndAdd(
    355     FIXP_DBL *in, int len, int windowLen, const FIXP_FILT *coeff, FIXP_DBL *out,
    356     UCHAR isCurrent /* output values with even index get a
    357                        positve addon (=1) or a negative addon
    358                        (=0) */
    359 ) {
    360   int i, j;
    361 
    362   int indices_1[] = {2, 1, 0, 1, 2, 3};
    363   int indices_2[] = {1, 0, 0, 2, 3, 4};
    364   int indices_3[] = {0, 0, 1, 3, 4, 5};
    365 
    366   int subtr_1[] = {6, 5, 4, 2, 1, 1};
    367   int subtr_2[] = {5, 4, 3, 1, 1, 2};
    368   int subtr_3[] = {4, 3, 2, 1, 2, 3};
    369 
    370   if (isCurrent == 1) {
    371     /* exploit the symmetry of the table: coeff[6] = - coeff[0],
    372                                           coeff[5] = - coeff[1],
    373                                           coeff[4] = - coeff[2],
    374                                           coeff[3] = 0
    375     */
    376 
    377     for (i = 0; i < 3; i++) {
    378       out[0] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[i]]) >> SR_FNA_OUT;
    379       out[0] +=
    380           (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[5 - i]]) >> SR_FNA_OUT;
    381     }
    382 
    383     for (i = 0; i < 3; i++) {
    384       out[1] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[i]]) >> SR_FNA_OUT;
    385       out[1] +=
    386           (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[5 - i]]) >> SR_FNA_OUT;
    387     }
    388 
    389     for (i = 0; i < 3; i++) {
    390       out[2] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[i]]) >> SR_FNA_OUT;
    391       out[2] +=
    392           (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[5 - i]]) >> SR_FNA_OUT;
    393     }
    394 
    395     for (j = 3; j < (len - 3); j++) {
    396       for (i = 0; i < 3; i++) {
    397         out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i]) >> SR_FNA_OUT;
    398         out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i]) >> SR_FNA_OUT;
    399       }
    400     }
    401 
    402     for (i = 0; i < 3; i++) {
    403       out[len - 3] -=
    404           (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[i]]) >> SR_FNA_OUT;
    405       out[len - 3] +=
    406           (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[5 - i]]) >> SR_FNA_OUT;
    407     }
    408 
    409     for (i = 0; i < 3; i++) {
    410       out[len - 2] -=
    411           (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[i]]) >> SR_FNA_OUT;
    412       out[len - 2] +=
    413           (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[5 - i]]) >> SR_FNA_OUT;
    414     }
    415 
    416     for (i = 0; i < 3; i++) {
    417       out[len - 1] -=
    418           (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[i]]) >> SR_FNA_OUT;
    419       out[len - 1] +=
    420           (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[5 - i]]) >> SR_FNA_OUT;
    421     }
    422 
    423   } else {
    424     /* exploit the symmetry of the table: coeff[6] = coeff[0],
    425                                           coeff[5] = coeff[1],
    426                                           coeff[4] = coeff[2]
    427     */
    428 
    429     for (i = 0; i < 3; i++) {
    430       out[0] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[i]] >> SR_FNA_OUT);
    431       out[0] -=
    432           (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[5 - i]] >> SR_FNA_OUT);
    433     }
    434     out[0] -= (FIXP_DBL)fMultDiv2(coeff[3], in[0] >> SR_FNA_OUT);
    435 
    436     for (i = 0; i < 3; i++) {
    437       out[1] += (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[i]] >> SR_FNA_OUT);
    438       out[1] +=
    439           (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[5 - i]] >> SR_FNA_OUT);
    440     }
    441     out[1] += (FIXP_DBL)fMultDiv2(coeff[3], in[1] >> SR_FNA_OUT);
    442 
    443     for (i = 0; i < 3; i++) {
    444       out[2] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[i]] >> SR_FNA_OUT);
    445       out[2] -=
    446           (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[5 - i]] >> SR_FNA_OUT);
    447     }
    448     out[2] -= (FIXP_DBL)fMultDiv2(coeff[3], in[2] >> SR_FNA_OUT);
    449 
    450     for (j = 3; j < (len - 4); j++) {
    451       for (i = 0; i < 3; i++) {
    452         out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i] >> SR_FNA_OUT);
    453         out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i] >> SR_FNA_OUT);
    454       }
    455       out[j] += (FIXP_DBL)fMultDiv2(coeff[3], in[j] >> SR_FNA_OUT);
    456 
    457       j++;
    458 
    459       for (i = 0; i < 3; i++) {
    460         out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i] >> SR_FNA_OUT);
    461         out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i] >> SR_FNA_OUT);
    462       }
    463       out[j] -= (FIXP_DBL)fMultDiv2(coeff[3], in[j] >> SR_FNA_OUT);
    464     }
    465 
    466     for (i = 0; i < 3; i++) {
    467       out[len - 3] +=
    468           (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[i]] >> SR_FNA_OUT);
    469       out[len - 3] +=
    470           (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[5 - i]] >> SR_FNA_OUT);
    471     }
    472     out[len - 3] += (FIXP_DBL)fMultDiv2(coeff[3], in[len - 3] >> SR_FNA_OUT);
    473 
    474     for (i = 0; i < 3; i++) {
    475       out[len - 2] -=
    476           (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[i]] >> SR_FNA_OUT);
    477       out[len - 2] -=
    478           (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[5 - i]] >> SR_FNA_OUT);
    479     }
    480     out[len - 2] -= (FIXP_DBL)fMultDiv2(coeff[3], in[len - 2] >> SR_FNA_OUT);
    481 
    482     for (i = 0; i < 3; i++) {
    483       out[len - 1] +=
    484           (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[i]] >> SR_FNA_OUT);
    485       out[len - 1] +=
    486           (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[5 - i]] >> SR_FNA_OUT);
    487     }
    488     out[len - 1] += (FIXP_DBL)fMultDiv2(coeff[3], in[len - 1] >> SR_FNA_OUT);
    489   }
    490 }
    491 
    492 static inline void CJointStereo_GenerateMSOutput(FIXP_DBL *pSpecLCurrBand,
    493                                                  FIXP_DBL *pSpecRCurrBand,
    494                                                  UINT leftScale,
    495                                                  UINT rightScale,
    496                                                  UINT nSfbBands) {
    497   unsigned int i;
    498 
    499   FIXP_DBL leftCoefficient0;
    500   FIXP_DBL leftCoefficient1;
    501   FIXP_DBL leftCoefficient2;
    502   FIXP_DBL leftCoefficient3;
    503 
    504   FIXP_DBL rightCoefficient0;
    505   FIXP_DBL rightCoefficient1;
    506   FIXP_DBL rightCoefficient2;
    507   FIXP_DBL rightCoefficient3;
    508 
    509   for (i = nSfbBands; i > 0; i -= 4) {
    510     leftCoefficient0 = pSpecLCurrBand[i - 4];
    511     leftCoefficient1 = pSpecLCurrBand[i - 3];
    512     leftCoefficient2 = pSpecLCurrBand[i - 2];
    513     leftCoefficient3 = pSpecLCurrBand[i - 1];
    514 
    515     rightCoefficient0 = pSpecRCurrBand[i - 4];
    516     rightCoefficient1 = pSpecRCurrBand[i - 3];
    517     rightCoefficient2 = pSpecRCurrBand[i - 2];
    518     rightCoefficient3 = pSpecRCurrBand[i - 1];
    519 
    520     /* MS output generation */
    521     leftCoefficient0 >>= leftScale;
    522     leftCoefficient1 >>= leftScale;
    523     leftCoefficient2 >>= leftScale;
    524     leftCoefficient3 >>= leftScale;
    525 
    526     rightCoefficient0 >>= rightScale;
    527     rightCoefficient1 >>= rightScale;
    528     rightCoefficient2 >>= rightScale;
    529     rightCoefficient3 >>= rightScale;
    530 
    531     pSpecLCurrBand[i - 4] = leftCoefficient0 + rightCoefficient0;
    532     pSpecLCurrBand[i - 3] = leftCoefficient1 + rightCoefficient1;
    533     pSpecLCurrBand[i - 2] = leftCoefficient2 + rightCoefficient2;
    534     pSpecLCurrBand[i - 1] = leftCoefficient3 + rightCoefficient3;
    535 
    536     pSpecRCurrBand[i - 4] = leftCoefficient0 - rightCoefficient0;
    537     pSpecRCurrBand[i - 3] = leftCoefficient1 - rightCoefficient1;
    538     pSpecRCurrBand[i - 2] = leftCoefficient2 - rightCoefficient2;
    539     pSpecRCurrBand[i - 1] = leftCoefficient3 - rightCoefficient3;
    540   }
    541 }
    542 
    543 void CJointStereo_ApplyMS(
    544     CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
    545     CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2],
    546     FIXP_DBL *spectrumL, FIXP_DBL *spectrumR, SHORT *SFBleftScale,
    547     SHORT *SFBrightScale, SHORT *specScaleL, SHORT *specScaleR,
    548     const SHORT *pScaleFactorBandOffsets, const UCHAR *pWindowGroupLength,
    549     const int windowGroups, const int max_sfb_ste_outside,
    550     const int scaleFactorBandsTransmittedL,
    551     const int scaleFactorBandsTransmittedR, FIXP_DBL *store_dmx_re_prev,
    552     SHORT *store_dmx_re_prev_e, const int mainband_flag) {
    553   int window, group, band;
    554   UCHAR groupMask;
    555   CJointStereoData *pJointStereoData =
    556       &pAacDecoderChannelInfo[L]->pComData->jointStereoData;
    557   CCplxPredictionData *cplxPredictionData =
    558       pAacDecoderChannelInfo[L]->pComStaticData->cplxPredictionData;
    559 
    560   int max_sfb_ste =
    561       fMax(scaleFactorBandsTransmittedL, scaleFactorBandsTransmittedR);
    562   int min_sfb_ste =
    563       fMin(scaleFactorBandsTransmittedL, scaleFactorBandsTransmittedR);
    564   int scaleFactorBandsTransmitted = min_sfb_ste;
    565 
    566   if (pJointStereoData->cplx_pred_flag) {
    567     int windowLen, groupwin, frameMaxScale;
    568     CJointStereoPersistentData *pJointStereoPersistentData =
    569         &pAacDecoderStaticChannelInfo[L]
    570              ->pCpeStaticData->jointStereoPersistentData;
    571     FIXP_DBL *const staticSpectralCoeffsL =
    572         pAacDecoderStaticChannelInfo[L]
    573             ->pCpeStaticData->jointStereoPersistentData.spectralCoeffs[L];
    574     FIXP_DBL *const staticSpectralCoeffsR =
    575         pAacDecoderStaticChannelInfo[L]
    576             ->pCpeStaticData->jointStereoPersistentData.spectralCoeffs[R];
    577     SHORT *const staticSpecScaleL =
    578         pAacDecoderStaticChannelInfo[L]
    579             ->pCpeStaticData->jointStereoPersistentData.specScale[L];
    580     SHORT *const staticSpecScaleR =
    581         pAacDecoderStaticChannelInfo[L]
    582             ->pCpeStaticData->jointStereoPersistentData.specScale[R];
    583 
    584     FIXP_DBL *dmx_re =
    585         pAacDecoderStaticChannelInfo[L]
    586             ->pCpeStaticData->jointStereoPersistentData.scratchBuffer;
    587     FIXP_DBL *dmx_re_prev =
    588         pAacDecoderStaticChannelInfo[L]
    589             ->pCpeStaticData->jointStereoPersistentData.scratchBuffer +
    590         1024;
    591 
    592     /* When MS is applied over the main band this value gets computed. Otherwise
    593      * (for the tiles) it uses the assigned value */
    594     SHORT dmx_re_prev_e = *store_dmx_re_prev_e;
    595 
    596     const FIXP_FILT *pCoeff;
    597     const FIXP_FILT *pCoeffPrev;
    598     int coeffPointerOffset;
    599 
    600     int previousShape = (int)pJointStereoPersistentData->winShapePrev;
    601     int currentShape = (int)pAacDecoderChannelInfo[L]->icsInfo.WindowShape;
    602 
    603     /* complex stereo prediction */
    604 
    605     /* 0. preparations */
    606 
    607     /* 0.0. get scratch buffer for downmix MDST */
    608     C_AALLOC_SCRATCH_START(dmx_im, FIXP_DBL, 1024);
    609 
    610     /* 0.1. window lengths */
    611 
    612     /* get length of short window for current configuration */
    613     windowLen =
    614         pAacDecoderChannelInfo[L]->granuleLength; /* framelength 768 => 96,
    615                                                      framelength 1024 => 128 */
    616 
    617     /* if this is no short-block set length for long-block */
    618     if (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence != BLOCK_SHORT) {
    619       windowLen *= 8;
    620     }
    621 
    622     /* 0.2. set pointer to filter-coefficients for MDST excitation including
    623      * previous frame portions */
    624     /*      cp. ISO/IEC FDIS 23003-3:2011(E) table 125 */
    625 
    626     /* set pointer to default-position */
    627     pCoeffPrev = mdst_filt_coef_prev[previousShape];
    628 
    629     if (cplxPredictionData->complex_coef == 1) {
    630       switch (pAacDecoderChannelInfo[L]
    631                   ->icsInfo.WindowSequence) { /* current window sequence */
    632         case BLOCK_SHORT:
    633         case BLOCK_LONG:
    634           pCoeffPrev = mdst_filt_coef_prev[previousShape];
    635           break;
    636 
    637         case BLOCK_START:
    638           if ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) ||
    639               (pJointStereoPersistentData->winSeqPrev == BLOCK_START)) {
    640             /* a stop-start-sequence can only follow on an eight-short-sequence
    641              * or a start-sequence */
    642             pCoeffPrev = mdst_filt_coef_prev[2 + previousShape];
    643           } else {
    644             pCoeffPrev = mdst_filt_coef_prev[previousShape];
    645           }
    646           break;
    647 
    648         case BLOCK_STOP:
    649           pCoeffPrev = mdst_filt_coef_prev[2 + previousShape];
    650           break;
    651 
    652         default:
    653           pCoeffPrev = mdst_filt_coef_prev[previousShape];
    654           break;
    655       }
    656     }
    657 
    658     /* 0.3. set pointer to filter-coefficients for MDST excitation */
    659 
    660     /* define offset of pointer to filter-coefficients for MDST exitation
    661      * employing only the current frame */
    662     if ((previousShape == SHAPE_SINE) && (currentShape == SHAPE_SINE)) {
    663       coeffPointerOffset = 0;
    664     } else if ((previousShape == SHAPE_SINE) && (currentShape == SHAPE_KBD)) {
    665       coeffPointerOffset = 2;
    666     } else if ((previousShape == SHAPE_KBD) && (currentShape == SHAPE_KBD)) {
    667       coeffPointerOffset = 1;
    668     } else /* if ( (previousShape == SHAPE_KBD) && (currentShape == SHAPE_SINE)
    669               ) */
    670     {
    671       coeffPointerOffset = 3;
    672     }
    673 
    674     /* set pointer to filter-coefficient table cp. ISO/IEC FDIS 23003-3:2011(E)
    675      * table 124 */
    676     switch (pAacDecoderChannelInfo[L]
    677                 ->icsInfo.WindowSequence) { /* current window sequence */
    678       case BLOCK_SHORT:
    679       case BLOCK_LONG:
    680         pCoeff = mdst_filt_coef_curr[coeffPointerOffset];
    681         break;
    682 
    683       case BLOCK_START:
    684         if ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) ||
    685             (pJointStereoPersistentData->winSeqPrev == BLOCK_START)) {
    686           /* a stop-start-sequence can only follow on an eight-short-sequence or
    687            * a start-sequence */
    688           pCoeff = mdst_filt_coef_curr[12 + coeffPointerOffset];
    689         } else {
    690           pCoeff = mdst_filt_coef_curr[4 + coeffPointerOffset];
    691         }
    692         break;
    693 
    694       case BLOCK_STOP:
    695         pCoeff = mdst_filt_coef_curr[8 + coeffPointerOffset];
    696         break;
    697 
    698       default:
    699         pCoeff = mdst_filt_coef_curr[coeffPointerOffset];
    700     }
    701 
    702     /* 0.4. find maximum common (l/r) band-scaling-factor for whole sequence
    703      * (all windows) */
    704     frameMaxScale = 0;
    705     for (window = 0, group = 0; group < windowGroups; group++) {
    706       for (groupwin = 0; groupwin < pWindowGroupLength[group];
    707            groupwin++, window++) {
    708         SHORT *leftScale = &SFBleftScale[window * 16];
    709         SHORT *rightScale = &SFBrightScale[window * 16];
    710         int windowMaxScale = 0;
    711 
    712         /* find maximum scaling factor of all bands in this window */
    713         for (band = 0; band < min_sfb_ste; band++) {
    714           int lScale = leftScale[band];
    715           int rScale = rightScale[band];
    716           int commonScale = ((lScale > rScale) ? lScale : rScale);
    717           windowMaxScale =
    718               (windowMaxScale < commonScale) ? commonScale : windowMaxScale;
    719         }
    720         if (scaleFactorBandsTransmittedL >
    721             min_sfb_ste) { /* i.e. scaleFactorBandsTransmittedL == max_sfb_ste
    722                             */
    723           for (; band < max_sfb_ste; band++) {
    724             int lScale = leftScale[band];
    725             windowMaxScale =
    726                 (windowMaxScale < lScale) ? lScale : windowMaxScale;
    727           }
    728         } else {
    729           if (scaleFactorBandsTransmittedR >
    730               min_sfb_ste) { /* i.e. scaleFactorBandsTransmittedR == max_sfb_ste
    731                               */
    732             for (; band < max_sfb_ste; band++) {
    733               int rScale = rightScale[band];
    734               windowMaxScale =
    735                   (windowMaxScale < rScale) ? rScale : windowMaxScale;
    736             }
    737           }
    738         }
    739 
    740         /* find maximum common SF of all windows */
    741         frameMaxScale =
    742             (frameMaxScale < windowMaxScale) ? windowMaxScale : frameMaxScale;
    743       }
    744     }
    745 
    746     /* add some headroom for overflow protection during filter and add operation
    747      */
    748     frameMaxScale += 2;
    749 
    750     /* process on window-basis (i.e. iterate over all groups and corresponding
    751      * windows) */
    752     for (window = 0, group = 0; group < windowGroups; group++) {
    753       groupMask = 1 << group;
    754 
    755       for (groupwin = 0; groupwin < pWindowGroupLength[group];
    756            groupwin++, window++) {
    757         /* initialize the MDST with zeros */
    758         FDKmemclear(&dmx_im[windowLen * window], windowLen * sizeof(FIXP_DBL));
    759 
    760         /* 1. calculate the previous downmix MDCT. We do this once just for the
    761          * Main band. */
    762         if (cplxPredictionData->complex_coef == 1) {
    763           if ((cplxPredictionData->use_prev_frame == 1) && (mainband_flag)) {
    764             /* if this is a long-block or the first window of a short-block
    765                calculate the downmix MDCT of the previous frame.
    766                use_prev_frame is assumed not to change during a frame!
    767             */
    768 
    769             /* first determine shiftfactors to scale left and right channel */
    770             if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence !=
    771                  BLOCK_SHORT) ||
    772                 (window == 0)) {
    773               int index_offset = 0;
    774               int srLeftChan = 0;
    775               int srRightChan = 0;
    776               if (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence ==
    777                   BLOCK_SHORT) {
    778                 /* use the last window of the previous frame for MDCT
    779                  * calculation if this is a short-block. */
    780                 index_offset = windowLen * 7;
    781                 if (staticSpecScaleL[7] > staticSpecScaleR[7]) {
    782                   srRightChan = staticSpecScaleL[7] - staticSpecScaleR[7];
    783                   dmx_re_prev_e = staticSpecScaleL[7];
    784                 } else {
    785                   srLeftChan = staticSpecScaleR[7] - staticSpecScaleL[7];
    786                   dmx_re_prev_e = staticSpecScaleR[7];
    787                 }
    788               } else {
    789                 if (staticSpecScaleL[0] > staticSpecScaleR[0]) {
    790                   srRightChan = staticSpecScaleL[0] - staticSpecScaleR[0];
    791                   dmx_re_prev_e = staticSpecScaleL[0];
    792                 } else {
    793                   srLeftChan = staticSpecScaleR[0] - staticSpecScaleL[0];
    794                   dmx_re_prev_e = staticSpecScaleR[0];
    795                 }
    796               }
    797 
    798               /* now scale channels and determine downmix MDCT of previous frame
    799                */
    800               if (pAacDecoderStaticChannelInfo[L]
    801                       ->pCpeStaticData->jointStereoPersistentData
    802                       .clearSpectralCoeffs == 1) {
    803                 FDKmemclear(dmx_re_prev, windowLen * sizeof(FIXP_DBL));
    804                 dmx_re_prev_e = 0;
    805               } else {
    806                 if (cplxPredictionData->pred_dir == 0) {
    807                   for (int i = 0; i < windowLen; i++) {
    808                     dmx_re_prev[i] =
    809                         ((staticSpectralCoeffsL[index_offset + i] >>
    810                           srLeftChan) +
    811                          (staticSpectralCoeffsR[index_offset + i] >>
    812                           srRightChan)) >>
    813                         1;
    814                   }
    815                 } else {
    816                   for (int i = 0; i < windowLen; i++) {
    817                     dmx_re_prev[i] =
    818                         ((staticSpectralCoeffsL[index_offset + i] >>
    819                           srLeftChan) -
    820                          (staticSpectralCoeffsR[index_offset + i] >>
    821                           srRightChan)) >>
    822                         1;
    823                   }
    824                 }
    825               }
    826 
    827               /* In case that we use INF we have to preserve the state of the
    828               "dmx_re_prev" (original or computed). This is necessary because we
    829               have to apply MS over the separate IGF tiles. */
    830               FDKmemcpy(store_dmx_re_prev, &dmx_re_prev[0],
    831                         windowLen * sizeof(FIXP_DBL));
    832 
    833               /* Particular exponent of the computed/original "dmx_re_prev" must
    834                * be kept for the tile MS calculations if necessary.*/
    835               *store_dmx_re_prev_e = dmx_re_prev_e;
    836 
    837             } /* if ( (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence !=
    838                  BLOCK_SHORT) || (window == 0) ) */
    839 
    840           } /* if ( pJointStereoData->use_prev_frame == 1 ) */
    841 
    842         } /* if ( pJointStereoData->complex_coef == 1 ) */
    843 
    844         /* 2. calculate downmix MDCT of current frame */
    845 
    846         /* set pointer to scale-factor-bands of current window */
    847         SHORT *leftScale = &SFBleftScale[window * 16];
    848         SHORT *rightScale = &SFBrightScale[window * 16];
    849 
    850         specScaleL[window] = specScaleR[window] = frameMaxScale;
    851 
    852         /* adapt scaling-factors to previous frame */
    853         if (cplxPredictionData->use_prev_frame == 1) {
    854           if (window == 0) {
    855             if (dmx_re_prev_e < frameMaxScale) {
    856               if (mainband_flag == 0) {
    857                 scaleValues(dmx_re_prev, store_dmx_re_prev, windowLen,
    858                             -(frameMaxScale - dmx_re_prev_e));
    859               } else {
    860                 for (int i = 0; i < windowLen; i++) {
    861                   dmx_re_prev[i] >>= (frameMaxScale - dmx_re_prev_e);
    862                 }
    863               }
    864             } else {
    865               if (mainband_flag == 0) {
    866                 FDKmemcpy(dmx_re_prev, store_dmx_re_prev,
    867                           windowLen * sizeof(FIXP_DBL));
    868               }
    869               specScaleL[0] = dmx_re_prev_e;
    870               specScaleR[0] = dmx_re_prev_e;
    871             }
    872           } else { /* window != 0 */
    873             FDK_ASSERT(pAacDecoderChannelInfo[L]->icsInfo.WindowSequence ==
    874                        BLOCK_SHORT);
    875             if (specScaleL[window - 1] < frameMaxScale) {
    876               for (int i = 0; i < windowLen; i++) {
    877                 dmx_re[windowLen * (window - 1) + i] >>=
    878                     (frameMaxScale - specScaleL[window - 1]);
    879               }
    880             } else {
    881               specScaleL[window] = specScaleL[window - 1];
    882               specScaleR[window] = specScaleR[window - 1];
    883             }
    884           }
    885         } /* if ( pJointStereoData->use_prev_frame == 1 ) */
    886 
    887         /* scaling factors of both channels ought to be equal now */
    888         FDK_ASSERT(specScaleL[window] == specScaleR[window]);
    889 
    890         /* rescale signal and calculate downmix MDCT */
    891         for (band = 0; band < max_sfb_ste; band++) {
    892           /* first adapt scaling of current band to scaling of current window =>
    893            * shift signal right */
    894           int lScale = leftScale[band];
    895           int rScale = rightScale[band];
    896 
    897           lScale = fMin(DFRACT_BITS - 1, specScaleL[window] - lScale);
    898           rScale = fMin(DFRACT_BITS - 1,
    899                         specScaleL[window] - rScale); /* L or R doesn't
    900                                                          matter,
    901                                                          specScales are
    902                                                          equal at this
    903                                                          point */
    904 
    905           /* Write back to sfb scale to cover the case when max_sfb_ste <
    906            * max_sfb */
    907           leftScale[band] = rightScale[band] = specScaleL[window];
    908 
    909           for (int i = pScaleFactorBandOffsets[band];
    910                i < pScaleFactorBandOffsets[band + 1]; i++) {
    911             spectrumL[windowLen * window + i] >>= lScale;
    912             spectrumR[windowLen * window + i] >>= rScale;
    913           }
    914 
    915           /* now calculate downmix MDCT */
    916           if (pJointStereoData->MsUsed[band] & groupMask) {
    917             for (int i = pScaleFactorBandOffsets[band];
    918                  i < pScaleFactorBandOffsets[band + 1]; i++) {
    919               dmx_re[windowLen * window + i] =
    920                   spectrumL[windowLen * window + i];
    921             }
    922           } else {
    923             if (cplxPredictionData->pred_dir == 0) {
    924               for (int i = pScaleFactorBandOffsets[band];
    925                    i < pScaleFactorBandOffsets[band + 1]; i++) {
    926                 dmx_re[windowLen * window + i] =
    927                     (spectrumL[windowLen * window + i] +
    928                      spectrumR[windowLen * window + i]) >>
    929                     1;
    930               }
    931             } else {
    932               for (int i = pScaleFactorBandOffsets[band];
    933                    i < pScaleFactorBandOffsets[band + 1]; i++) {
    934                 dmx_re[windowLen * window + i] =
    935                     (spectrumL[windowLen * window + i] -
    936                      spectrumR[windowLen * window + i]) >>
    937                     1;
    938               }
    939             }
    940           }
    941 
    942         } /* for ( band=0; band<max_sfb_ste; band++ ) */
    943         /* Clean until the end */
    944         for (int i = pScaleFactorBandOffsets[max_sfb_ste_outside];
    945              i < windowLen; i++) {
    946           dmx_re[windowLen * window + i] = (FIXP_DBL)0;
    947         }
    948 
    949         /* 3. calculate MDST-portion corresponding to the current frame. */
    950         if (cplxPredictionData->complex_coef == 1) {
    951           {
    952             /* 3.1 move pointer in filter-coefficient table in case of short
    953              * window sequence */
    954             /*     (other coefficients are utilized for the last 7 short
    955              * windows)            */
    956             if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence ==
    957                  BLOCK_SHORT) &&
    958                 (window != 0)) {
    959               pCoeff = mdst_filt_coef_curr[currentShape];
    960               pCoeffPrev = mdst_filt_coef_prev[currentShape];
    961             }
    962 
    963             /* The length of the filter processing must be extended because of
    964              * filter boundary problems */
    965             int extended_band = fMin(
    966                 pScaleFactorBandOffsets[max_sfb_ste_outside] + 7, windowLen);
    967 
    968             /* 3.2. estimate downmix MDST from current frame downmix MDCT */
    969             if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence ==
    970                  BLOCK_SHORT) &&
    971                 (window != 0)) {
    972               CJointStereo_filterAndAdd(&dmx_re[windowLen * window],
    973                                         extended_band, windowLen, pCoeff,
    974                                         &dmx_im[windowLen * window], 1);
    975 
    976               CJointStereo_filterAndAdd(&dmx_re[windowLen * (window - 1)],
    977                                         extended_band, windowLen, pCoeffPrev,
    978                                         &dmx_im[windowLen * window], 0);
    979             } else {
    980               CJointStereo_filterAndAdd(dmx_re, extended_band, windowLen,
    981                                         pCoeff, dmx_im, 1);
    982 
    983               if (cplxPredictionData->use_prev_frame == 1) {
    984                 CJointStereo_filterAndAdd(dmx_re_prev, extended_band, windowLen,
    985                                           pCoeffPrev,
    986                                           &dmx_im[windowLen * window], 0);
    987               }
    988             }
    989 
    990           } /* if(pAacDecoderChannelInfo[L]->transform_splitting_active) */
    991         }   /* if ( pJointStereoData->complex_coef == 1 ) */
    992 
    993         /* 4. upmix process */
    994         INT pred_dir = cplxPredictionData->pred_dir ? -1 : 1;
    995         /* 0.1 in Q-3.34 */
    996         const FIXP_DBL pointOne = 0x66666666; /* 0.8 */
    997         /* Shift value for the downmix */
    998         const INT shift_dmx = SF_FNA_COEFFS + 1;
    999 
   1000         for (band = 0; band < max_sfb_ste_outside; band++) {
   1001           if (pJointStereoData->MsUsed[band] & groupMask) {
   1002             FIXP_SGL tempRe =
   1003                 (FIXP_SGL)cplxPredictionData->alpha_q_re[group][band];
   1004             FIXP_SGL tempIm =
   1005                 (FIXP_SGL)cplxPredictionData->alpha_q_im[group][band];
   1006 
   1007             /* Find the minimum common headroom for alpha_re and alpha_im */
   1008             int alpha_re_headroom = CountLeadingBits((INT)tempRe) - 16;
   1009             if (tempRe == (FIXP_SGL)0) alpha_re_headroom = 15;
   1010             int alpha_im_headroom = CountLeadingBits((INT)tempIm) - 16;
   1011             if (tempIm == (FIXP_SGL)0) alpha_im_headroom = 15;
   1012             int val = fMin(alpha_re_headroom, alpha_im_headroom);
   1013 
   1014             /* Multiply alpha by 0.1 with maximum precision */
   1015             FDK_ASSERT(val >= 0);
   1016             FIXP_DBL alpha_re_tmp = fMult((FIXP_SGL)(tempRe << val), pointOne);
   1017             FIXP_DBL alpha_im_tmp = fMult((FIXP_SGL)(tempIm << val), pointOne);
   1018 
   1019             /* Calculate alpha exponent */
   1020             /* (Q-3.34 * Q15.0) shifted left by "val" */
   1021             int alpha_re_exp = -3 + 15 - val;
   1022 
   1023             int help3_shift = alpha_re_exp + 1;
   1024 
   1025             FIXP_DBL *p2CoeffL = &(
   1026                 spectrumL[windowLen * window + pScaleFactorBandOffsets[band]]);
   1027             FIXP_DBL *p2CoeffR = &(
   1028                 spectrumR[windowLen * window + pScaleFactorBandOffsets[band]]);
   1029             FIXP_DBL *p2dmxIm =
   1030                 &(dmx_im[windowLen * window + pScaleFactorBandOffsets[band]]);
   1031             FIXP_DBL *p2dmxRe =
   1032                 &(dmx_re[windowLen * window + pScaleFactorBandOffsets[band]]);
   1033 
   1034             for (int i = pScaleFactorBandOffsets[band];
   1035                  i < pScaleFactorBandOffsets[band + 1]; i++) {
   1036               /* Calculating helper term:
   1037                     side = specR[i] - alpha_re[i] * dmx_re[i] - alpha_im[i] *
   1038                 dmx_im[i];
   1039 
   1040                 Here "dmx_re" may be the same as "specL" or alternatively keep
   1041                 the downmix. "dmx_re" and "specL" are two different pointers
   1042                 pointing to separate arrays, which may or may not contain the
   1043                 same data (with different scaling).
   1044               */
   1045 
   1046               /* help1: alpha_re[i] * dmx_re[i] */
   1047               FIXP_DBL help1 = fMultDiv2(alpha_re_tmp, *p2dmxRe++);
   1048 
   1049               /* tmp: dmx_im[i] */
   1050               FIXP_DBL tmp = (*p2dmxIm++) << shift_dmx;
   1051 
   1052               /* help2: alpha_im[i] * dmx_im[i] */
   1053               FIXP_DBL help2 = fMultDiv2(alpha_im_tmp, tmp);
   1054 
   1055               /* help3: alpha_re[i] * dmx_re[i] + alpha_im[i] * dmx_im[i] */
   1056               FIXP_DBL help3 = help1 + help2;
   1057 
   1058               /* side (= help4) = specR[i] - (dmx_re[i] * specL[i] + alpha_im[i]
   1059                * * dmx_im[i]) */
   1060               FIXP_DBL help4 = *p2CoeffR - scaleValue(help3, help3_shift);
   1061 
   1062               /* We calculate the left and right output by using the helper
   1063                * function */
   1064               /* specR[i] = -/+ (specL[i] - side); */
   1065               *p2CoeffR =
   1066                   (FIXP_DBL)((LONG)(*p2CoeffL - help4) * (LONG)pred_dir);
   1067               p2CoeffR++;
   1068 
   1069               /* specL[i] = specL[i] + side; */
   1070               *p2CoeffL = *p2CoeffL + help4;
   1071               p2CoeffL++;
   1072             }
   1073           }
   1074 
   1075         } /* for ( band=0; band < max_sfb_ste; band++ ) */
   1076       }   /* for ( groupwin=0; groupwin<pWindowGroupLength[group]; groupwin++,
   1077              window++ ) */
   1078 
   1079     } /* for ( window = 0, group = 0; group < windowGroups; group++ ) */
   1080 
   1081     /* free scratch buffer */
   1082     C_AALLOC_SCRATCH_END(dmx_im, FIXP_DBL, 1024);
   1083 
   1084   } else {
   1085     /* MS stereo */
   1086 
   1087     for (window = 0, group = 0; group < windowGroups; group++) {
   1088       groupMask = 1 << group;
   1089 
   1090       for (int groupwin = 0; groupwin < pWindowGroupLength[group];
   1091            groupwin++, window++) {
   1092         FIXP_DBL *leftSpectrum, *rightSpectrum;
   1093         SHORT *leftScale = &SFBleftScale[window * 16];
   1094         SHORT *rightScale = &SFBrightScale[window * 16];
   1095 
   1096         leftSpectrum =
   1097             SPEC(spectrumL, window, pAacDecoderChannelInfo[L]->granuleLength);
   1098         rightSpectrum =
   1099             SPEC(spectrumR, window, pAacDecoderChannelInfo[R]->granuleLength);
   1100 
   1101         for (band = 0; band < max_sfb_ste_outside; band++) {
   1102           if (pJointStereoData->MsUsed[band] & groupMask) {
   1103             int lScale = leftScale[band];
   1104             int rScale = rightScale[band];
   1105             int commonScale = lScale > rScale ? lScale : rScale;
   1106             unsigned int offsetCurrBand, offsetNextBand;
   1107 
   1108             /* ISO/IEC 14496-3 Chapter 4.6.8.1.1 :
   1109                M/S joint channel coding can only be used if common_window is 1.
   1110              */
   1111             FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) ==
   1112                        GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo));
   1113             FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) ==
   1114                        GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo));
   1115 
   1116             commonScale++;
   1117             leftScale[band] = commonScale;
   1118             rightScale[band] = commonScale;
   1119 
   1120             lScale = fMin(DFRACT_BITS - 1, commonScale - lScale);
   1121             rScale = fMin(DFRACT_BITS - 1, commonScale - rScale);
   1122 
   1123             FDK_ASSERT(lScale >= 0 && rScale >= 0);
   1124 
   1125             offsetCurrBand = pScaleFactorBandOffsets[band];
   1126             offsetNextBand = pScaleFactorBandOffsets[band + 1];
   1127 
   1128             CJointStereo_GenerateMSOutput(&(leftSpectrum[offsetCurrBand]),
   1129                                           &(rightSpectrum[offsetCurrBand]),
   1130                                           lScale, rScale,
   1131                                           offsetNextBand - offsetCurrBand);
   1132           }
   1133         }
   1134         if (scaleFactorBandsTransmittedL > scaleFactorBandsTransmitted) {
   1135           for (; band < scaleFactorBandsTransmittedL; band++) {
   1136             if (pJointStereoData->MsUsed[band] & groupMask) {
   1137               rightScale[band] = leftScale[band];
   1138 
   1139               for (int index = pScaleFactorBandOffsets[band];
   1140                    index < pScaleFactorBandOffsets[band + 1]; index++) {
   1141                 FIXP_DBL leftCoefficient = leftSpectrum[index];
   1142                 /* FIXP_DBL rightCoefficient = (FIXP_DBL)0; */
   1143                 rightSpectrum[index] = leftCoefficient;
   1144               }
   1145             }
   1146           }
   1147         } else if (scaleFactorBandsTransmittedR > scaleFactorBandsTransmitted) {
   1148           for (; band < scaleFactorBandsTransmittedR; band++) {
   1149             if (pJointStereoData->MsUsed[band] & groupMask) {
   1150               leftScale[band] = rightScale[band];
   1151 
   1152               for (int index = pScaleFactorBandOffsets[band];
   1153                    index < pScaleFactorBandOffsets[band + 1]; index++) {
   1154                 /* FIXP_DBL leftCoefficient  = (FIXP_DBL)0; */
   1155                 FIXP_DBL rightCoefficient = rightSpectrum[index];
   1156 
   1157                 leftSpectrum[index] = rightCoefficient;
   1158                 rightSpectrum[index] = -rightCoefficient;
   1159               }
   1160             }
   1161           }
   1162         }
   1163       }
   1164     }
   1165 
   1166     /* Reset MsUsed flags if no explicit signalling was transmitted. Necessary
   1167        for intensity coding. PNS correlation signalling was mapped before
   1168        calling CJointStereo_ApplyMS(). */
   1169     if (pJointStereoData->MsMaskPresent == 2) {
   1170       FDKmemclear(pJointStereoData->MsUsed,
   1171                   JointStereoMaximumBands * sizeof(UCHAR));
   1172     }
   1173   }
   1174 }
   1175 
   1176 void CJointStereo_ApplyIS(CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
   1177                           const SHORT *pScaleFactorBandOffsets,
   1178                           const UCHAR *pWindowGroupLength,
   1179                           const int windowGroups,
   1180                           const int scaleFactorBandsTransmitted) {
   1181   CJointStereoData *pJointStereoData =
   1182       &pAacDecoderChannelInfo[L]->pComData->jointStereoData;
   1183 
   1184   for (int window = 0, group = 0; group < windowGroups; group++) {
   1185     UCHAR *CodeBook;
   1186     SHORT *ScaleFactor;
   1187     UCHAR groupMask = 1 << group;
   1188 
   1189     CodeBook = &pAacDecoderChannelInfo[R]->pDynData->aCodeBook[group * 16];
   1190     ScaleFactor =
   1191         &pAacDecoderChannelInfo[R]->pDynData->aScaleFactor[group * 16];
   1192 
   1193     for (int groupwin = 0; groupwin < pWindowGroupLength[group];
   1194          groupwin++, window++) {
   1195       FIXP_DBL *leftSpectrum, *rightSpectrum;
   1196       SHORT *leftScale =
   1197           &pAacDecoderChannelInfo[L]->pDynData->aSfbScale[window * 16];
   1198       SHORT *rightScale =
   1199           &pAacDecoderChannelInfo[R]->pDynData->aSfbScale[window * 16];
   1200       int band;
   1201 
   1202       leftSpectrum = SPEC(pAacDecoderChannelInfo[L]->pSpectralCoefficient,
   1203                           window, pAacDecoderChannelInfo[L]->granuleLength);
   1204       rightSpectrum = SPEC(pAacDecoderChannelInfo[R]->pSpectralCoefficient,
   1205                            window, pAacDecoderChannelInfo[R]->granuleLength);
   1206 
   1207       for (band = 0; band < scaleFactorBandsTransmitted; band++) {
   1208         if ((CodeBook[band] == INTENSITY_HCB) ||
   1209             (CodeBook[band] == INTENSITY_HCB2)) {
   1210           int bandScale = -(ScaleFactor[band] + 100);
   1211 
   1212           int msb = bandScale >> 2;
   1213           int lsb = bandScale & 0x03;
   1214 
   1215           /* exponent of MantissaTable[lsb][0] is 1, thus msb+1 below. */
   1216           FIXP_DBL scale = MantissaTable[lsb][0];
   1217 
   1218           /* ISO/IEC 14496-3 Chapter 4.6.8.2.3 :
   1219              The use of intensity stereo coding is signaled by the use of the
   1220              pseudo codebooks INTENSITY_HCB and INTENSITY_HCB2 (15 and 14) only
   1221              in the right channel of a channel_pair_element() having a common
   1222              ics_info() (common_window == 1). */
   1223           FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) ==
   1224                      GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo));
   1225           FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) ==
   1226                      GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo));
   1227 
   1228           rightScale[band] = leftScale[band] + msb + 1;
   1229 
   1230           if (pJointStereoData->MsUsed[band] & groupMask) {
   1231             if (CodeBook[band] == INTENSITY_HCB) /* _NOT_ in-phase */
   1232             {
   1233               scale = -scale;
   1234             }
   1235           } else {
   1236             if (CodeBook[band] == INTENSITY_HCB2) /* out-of-phase */
   1237             {
   1238               scale = -scale;
   1239             }
   1240           }
   1241 
   1242           for (int index = pScaleFactorBandOffsets[band];
   1243                index < pScaleFactorBandOffsets[band + 1]; index++) {
   1244             rightSpectrum[index] = fMult(leftSpectrum[index], scale);
   1245           }
   1246         }
   1247       }
   1248     }
   1249   }
   1250 }
   1251