Home | History | Annotate | Download | only in decoder
      1 /******************************************************************************
      2  *                                                                            *
      3  * Copyright (C) 2018 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at:
      8  *
      9  * http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  *****************************************************************************
     18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
     19 */
     20 #include <ixheaacd_type_def.h>
     21 #include "ixheaacd_bitbuffer.h"
     22 #include "ixheaacd_config.h"
     23 #include "ixheaacd_mps_polyphase.h"
     24 
     25 #include "ixheaacd_mps_dec.h"
     26 #include "ixheaacd_mps_interface.h"
     27 
     28 #include <ixheaacd_type_def.h>
     29 #include "ixheaacd_constants.h"
     30 #include <ixheaacd_basic_ops32.h>
     31 #include <ixheaacd_basic_ops40.h>
     32 
     33 #include <math.h>
     34 #include <memory.h>
     35 
     36 #include <assert.h>
     37 
     38 #undef ABS_THR
     39 #define ABS_THR 1.0e-9f
     40 
     41 #define ICC_FIX
     42 #define UNSINGULARIZE_FIX
     43 #define QUANTIZE_PARS_FIX
     44 
     45 #define PI 3.14159265358979f
     46 
     47 #define ONE_IN_Q28 (268435456)
     48 #define MINUS_ONE_IN_Q28 (-268435456)
     49 #define PI_Q28 (843314856)
     50 #define PI_Q27 (421657428)
     51 #define PI_BY_8_Q28 (105414352)
     52 
     53 extern const WORD32 ixheaacd_im_weight_Q28[16][8][31];
     54 extern const WORD32 ixheaacd_re_weight_Q28[16][8][31];
     55 extern const WORD32 ixheaacd_beta_Q28[16][8][31];
     56 extern const WORD32 ixheaacd_weight_Q28[16][8][31];
     57 extern const WORD32 ixheaacd_c_l_table_Q31[31];
     58 extern const WORD32 ixheaacd_sin_table_Q31[16][31];
     59 extern const WORD32 ixheaacd_cos_table_Q31[16][31];
     60 extern const WORD32 ixheaacd_atan_table_Q28[16][8][31];
     61 extern WORD32 ixheaacd_ipd_de_quant_table_q28[16];
     62 
     63 #define P_PI 3.1415926535897932
     64 #define PI_IN_Q28 843314880
     65 
     66 extern WORD32 ixheaacd_ipd_de_quant_table_q28[16];
     67 
     68 #define P_PI 3.1415926535897932
     69 #define PI_IN_Q28 843314880
     70 
     71 static WORD32 ixheaacd_mps_phase_wraping(WORD32 phase) {
     72   const WORD32 pi_2 = 2 * PI_IN_Q28;
     73 
     74   while (phase < 0) phase += pi_2;
     75   while (phase >= pi_2) phase -= pi_2;
     76   assert((phase >= 0) && (phase < pi_2));
     77 
     78   return phase;
     79 }
     80 
     81 static VOID ixheaacd_mps_buffer_pre_and_mix_matrix(
     82     ia_mps_dec_state_struct *self) {
     83   WORD32 pb, row, col;
     84 
     85   for (pb = 0; pb < self->bs_param_bands; pb++) {
     86     for (row = 0; row < MAX_M_INPUT; row++) {
     87       for (col = 0; col < MAX_M_OUTPUT; col++) {
     88         self->m1_param_re_prev[pb][row][col] =
     89             self->m1_param_re[self->num_parameter_sets_prev - 1][pb][row][col];
     90         self->m1_param_im_prev[pb][row][col] =
     91             self->m1_param_im[self->num_parameter_sets_prev - 1][pb][row][col];
     92         self->m2_decor_re_prev[pb][row][col] =
     93             self->m2_decor_re[self->num_parameter_sets_prev - 1][pb][row][col];
     94         self->m2_decor_im_prev[pb][row][col] =
     95             self->m2_decor_im[self->num_parameter_sets_prev - 1][pb][row][col];
     96         self->m2_resid_re_prev[pb][row][col] =
     97             self->m2_resid_re[self->num_parameter_sets_prev - 1][pb][row][col];
     98         self->m2_resid_im_prev[pb][row][col] =
     99             self->m2_resid_im[self->num_parameter_sets_prev - 1][pb][row][col];
    100       }
    101     }
    102   }
    103 
    104   for (pb = 0; pb < self->bs_param_bands; pb++) {
    105     self->phase_l_prev[pb] =
    106         self->phase_l[self->num_parameter_sets_prev - 1][pb];
    107     self->phase_r_prev[pb] =
    108         self->phase_r[self->num_parameter_sets_prev - 1][pb];
    109   }
    110 }
    111 
    112 VOID ixheaacd_fix_to_float_int(WORD32 *inp, FLOAT32 *out, WORD32 length,
    113                                FLOAT32 q_fac) {
    114   WORD32 i;
    115   FLOAT32 m_qfac = 1.0f / q_fac;
    116 
    117   for (i = 0; i < length; i++) out[i] = (FLOAT32)(inp[i]) * m_qfac;
    118 }
    119 
    120 VOID ixheaacd_pre_and_mix_matrix_calculation(ia_mps_dec_state_struct *self) {
    121   WORD32 ps, pb;
    122   ia_mps_bs_frame *curr_bit_stream = &(self->bs_frame);
    123   WORD32 h_imag[2 * MAX_PARAMETER_BANDS];
    124   WORD32
    125   h_real[6 * MAX_PARAMETER_BANDS];
    126 
    127   ixheaacd_mps_buffer_pre_and_mix_matrix(self);
    128 
    129   for (ps = 0; ps < self->num_parameter_sets; ps++) {
    130     WORD32 *h_im = &h_imag[0];
    131     WORD32 *h_re = &h_real[0];
    132     memset(h_real, 0, 6 * MAX_PARAMETER_BANDS * sizeof(WORD32));
    133     memset(h_imag, 0, 2 * MAX_PARAMETER_BANDS * sizeof(WORD32));
    134 
    135     switch (self->config->bs_phase_coding) {
    136       case 0:
    137         if (self->residual_coding) {
    138           ixheaacd_mps_par2umx_pred(self, curr_bit_stream, h_imag, h_real, ps,
    139                                     self->res_bands);
    140         } else {
    141           ixheaacd_mps_par2umx_ps(self, curr_bit_stream, h_real, ps);
    142         }
    143 
    144         break;
    145       case 1:
    146         ixheaacd_mps_par2umx_ps_ipd_opd(self, curr_bit_stream, h_real, ps);
    147         break;
    148       case 2:
    149         ixheaacd_mps_par2umx_pred(self, curr_bit_stream, h_imag, h_real, ps,
    150                                   self->res_bands);
    151         break;
    152     }
    153 
    154     for (pb = 0; pb < self->bs_param_bands; pb++) {
    155       self->m1_param_re[ps][pb][0][0] = 1073741824;
    156       self->m1_param_re[ps][pb][1][0] = 1073741824;
    157 
    158       self->m1_param_im[ps][pb][0][0] = 0;
    159       self->m1_param_im[ps][pb][1][0] = 0;
    160 
    161       self->m2_resid_re[ps][pb][0][0] = *h_re++;
    162       self->m2_resid_im[ps][pb][0][0] = *h_im++;
    163       self->m2_resid_im[ps][pb][0][1] = 0;
    164 
    165       self->m2_resid_re[ps][pb][1][0] = *h_re++;
    166       self->m2_resid_im[ps][pb][1][0] = *h_im++;
    167       self->m2_resid_im[ps][pb][1][1] = 0;
    168 
    169       self->m2_decor_re[ps][pb][0][0] = 0;
    170       self->m2_decor_im[ps][pb][0][0] = 0;
    171       self->m2_decor_re[ps][pb][0][1] = *h_re++;
    172       self->m2_decor_im[ps][pb][0][1] = 0;
    173 
    174       self->m2_decor_re[ps][pb][1][0] = 0;
    175       self->m2_decor_im[ps][pb][1][0] = 0;
    176       self->m2_decor_re[ps][pb][1][1] = *h_re++;
    177       self->m2_decor_im[ps][pb][1][1] = 0;
    178 
    179       self->m2_resid_re[ps][pb][0][1] = *h_re++;
    180       self->m2_resid_re[ps][pb][1][1] = *h_re++;
    181     }
    182   }
    183   ixheaacd_mps_smoothing_opd(self);
    184 
    185   ixheaacd_fix_to_float_int(&self->phase_l_fix[0][0], &self->phase_l[0][0],
    186                             MAX_PARAMETER_SETS_MPS * MAX_PARAMETER_BANDS,
    187                             268435456.0f);
    188   ixheaacd_fix_to_float_int(&self->phase_r_fix[0][0], &self->phase_r[0][0],
    189                             MAX_PARAMETER_SETS_MPS * MAX_PARAMETER_BANDS,
    190                             268435456.0f);
    191 }
    192 
    193 static VOID ixheaacd_mps_par2umx_ps_core(WORD32 cld[MAX_PARAMETER_BANDS],
    194                                          WORD32 icc[MAX_PARAMETER_BANDS],
    195                                          WORD32 ott_band_count,
    196                                          WORD32 *h_real) {
    197   WORD32 band;
    198   WORD32 c_l_temp, c_r_temp, cld_idx, icc_idx, temp;
    199 
    200   for (band = 0; band < ott_band_count; band++) {
    201     cld_idx = *cld++ + 15;
    202     icc_idx = *icc++;
    203 
    204     c_l_temp = (ixheaacd_c_l_table_Q31[cld_idx]);
    205     c_r_temp = (ixheaacd_c_l_table_Q31[30 - cld_idx]);
    206 
    207     temp = ixheaacd_cos_table_Q31[icc_idx][cld_idx];
    208     *h_real++ = ixheaacd_mult32(temp, c_l_temp) >> 2;
    209 
    210     temp = ixheaacd_cos_table_Q31[icc_idx][30 - cld_idx];
    211     *h_real++ = ixheaacd_mult32(temp, c_r_temp) >> 2;
    212 
    213     temp = ixheaacd_sin_table_Q31[icc_idx][cld_idx];
    214     *h_real++ = ixheaacd_mult32(temp, c_l_temp) >> 2;
    215 
    216     temp = -ixheaacd_sin_table_Q31[icc_idx][30 - cld_idx];
    217     *h_real++ = ixheaacd_mult32(temp, c_r_temp) >> 2;
    218 
    219     h_real += 2;
    220   }
    221 }
    222 
    223 VOID ixheaacd_mps_par2umx_ps(ia_mps_dec_state_struct *self,
    224                              ia_mps_bs_frame *curr_bit_stream, WORD32 *h_real,
    225                              WORD32 param_set_idx) {
    226   ixheaacd_mps_par2umx_ps_core(curr_bit_stream->cld_idx[param_set_idx],
    227                                curr_bit_stream->icc_idx[param_set_idx],
    228                                self->bs_param_bands, h_real);
    229 }
    230 
    231 static VOID ixheaacd_mps_opd_calc(ia_mps_dec_state_struct *self,
    232                                   ia_mps_bs_frame *curr_bit_stream,
    233                                   WORD32 param_set_idx,
    234                                   WORD32 opd[MAX_PARAMETER_BANDS]) {
    235   WORD32 band;
    236 
    237   for (band = 0; band < self->num_bands_ipd; band++) {
    238     WORD32 cld_idx = curr_bit_stream->cld_idx[param_set_idx][band] + 15;
    239     WORD32 ipd_idx = (curr_bit_stream->ipd_idx[param_set_idx][band]) & 15;
    240     WORD32 icc_idx = curr_bit_stream->icc_idx[param_set_idx][band];
    241 
    242     if ((cld_idx == 15) && (ipd_idx == 8))
    243       opd[band] = 0;
    244     else
    245       opd[band] = ixheaacd_atan_table_Q28[ipd_idx][icc_idx][cld_idx];
    246   }
    247 }
    248 
    249 VOID ixheaacd_mps_par2umx_ps_ipd_opd(ia_mps_dec_state_struct *self,
    250                                      ia_mps_bs_frame *curr_bit_stream,
    251                                      WORD32 *h_real, WORD32 param_set_idx) {
    252   WORD32 opd[MAX_PARAMETER_BANDS];
    253   WORD32 ott_band_count = self->bs_param_bands;
    254   WORD32 num_bands_ipd = self->num_bands_ipd;
    255   WORD32 band;
    256 
    257   ixheaacd_mps_par2umx_ps_core(curr_bit_stream->cld_idx[param_set_idx],
    258                                curr_bit_stream->icc_idx[param_set_idx],
    259                                ott_band_count, h_real);
    260 
    261   if (self->bs_phase_mode) {
    262     ixheaacd_mps_opd_calc(self, curr_bit_stream, param_set_idx, opd);
    263 
    264     for (band = 0; band < num_bands_ipd; band++) {
    265       WORD32 ipd_idx = curr_bit_stream->ipd_idx[param_set_idx][band] & 15;
    266       WORD32 ipd = ixheaacd_ipd_de_quant_table_q28[ipd_idx];
    267 
    268       self->phase_l_fix[param_set_idx][band] =
    269           ixheaacd_mps_phase_wraping(opd[band]);
    270       self->phase_r_fix[param_set_idx][band] =
    271           ixheaacd_mps_phase_wraping(opd[band] - ipd);
    272     }
    273   } else {
    274     num_bands_ipd = 0;
    275   }
    276 
    277   for (band = num_bands_ipd; band < ott_band_count; band++) {
    278     self->phase_l_fix[param_set_idx][band] = 0;
    279     self->phase_r_fix[param_set_idx][band] = 0;
    280   }
    281 }
    282 
    283 VOID ixheaacd_mps_par2umx_pred(ia_mps_dec_state_struct *self,
    284                                ia_mps_bs_frame *curr_bit_stream, WORD32 *h_imag,
    285                                WORD32 *h_real, WORD32 param_set_idx,
    286                                WORD32 res_bands) {
    287   WORD32 band;
    288 
    289   for (band = 0; band < self->bs_param_bands; band++) {
    290     WORD32 cld_idx = curr_bit_stream->cld_idx[param_set_idx][band] + 15;
    291     WORD32 icc_idx = curr_bit_stream->icc_idx[param_set_idx][band];
    292     WORD32 ipd_idx = curr_bit_stream->ipd_idx[param_set_idx][band] & 15;
    293 
    294     if ((band < self->num_bands_ipd) && (cld_idx == 15) && (icc_idx == 0) &&
    295         (ipd_idx == 8)) {
    296       WORD32 gain = 111848107;
    297       *h_imag++ = 0;
    298       *h_imag++ = 0;
    299 
    300       if (band < res_bands) {
    301         *h_real++ = gain;
    302         *h_real++ = gain;
    303         h_real += 2;
    304 
    305         *h_real++ = gain;
    306         *h_real++ = -gain;
    307       } else {
    308         *h_real++ = gain;
    309         *h_real++ = -gain;
    310 
    311         h_real += 4;
    312       }
    313     } else {
    314       WORD32 weight_fix, re_weight_fix, im_weight_fix;
    315 
    316       weight_fix = ixheaacd_weight_Q28[ipd_idx][icc_idx][cld_idx];
    317       re_weight_fix = ixheaacd_re_weight_Q28[ipd_idx][icc_idx][cld_idx];
    318       im_weight_fix = ixheaacd_im_weight_Q28[ipd_idx][icc_idx][cld_idx];
    319 
    320       if (band < self->num_bands_ipd) {
    321         weight_fix = ixheaacd_weight_Q28[ipd_idx][icc_idx][cld_idx];
    322         re_weight_fix = ixheaacd_re_weight_Q28[ipd_idx][icc_idx][cld_idx];
    323         im_weight_fix = ixheaacd_im_weight_Q28[ipd_idx][icc_idx][cld_idx];
    324       } else {
    325         weight_fix = ixheaacd_weight_Q28[0][icc_idx][cld_idx];
    326         re_weight_fix = ixheaacd_re_weight_Q28[0][icc_idx][cld_idx];
    327         im_weight_fix = ixheaacd_im_weight_Q28[0][icc_idx][cld_idx];
    328       }
    329 
    330       *h_real++ = weight_fix - re_weight_fix;
    331       *h_imag++ = -im_weight_fix;
    332       *h_real++ = weight_fix + re_weight_fix;
    333       *h_imag++ = im_weight_fix;
    334 
    335       if (band < res_bands) {
    336         h_real += 2;
    337 
    338         *h_real++ = weight_fix;
    339         *h_real++ = -weight_fix;
    340       } else {
    341         WORD32 beta = ixheaacd_beta_Q28[ipd_idx][icc_idx][cld_idx];
    342 
    343         *h_real++ = beta;
    344         *h_real++ = -beta;
    345         h_real += 2;
    346       }
    347     }
    348   }
    349 }
    350 
    351 VOID ixheaacd_mps_apply_pre_matrix(ia_mps_dec_state_struct *self) {
    352   WORD32 ts, qs, row, col = 0;
    353 
    354   ixheaacd_mps_upmix_interp(
    355       self->m1_param_re, self->r_out_re_scratch_m1, self->m1_param_re_prev,
    356       (self->dir_sig_count + self->decor_sig_count), 1, self);
    357   ixheaacd_mps_upmix_interp(
    358       self->m1_param_im, self->r_out_im_scratch_m1, self->m1_param_im_prev,
    359       (self->dir_sig_count + self->decor_sig_count), 1, self);
    360 
    361   ixheaacd_fix_to_float_int(
    362       (WORD32 *)(self->r_out_re_scratch_m1), (FLOAT32 *)(self->r_out_re_in_m1),
    363       MAX_TIME_SLOTS * MAX_PARAMETER_BANDS * MAX_M_OUTPUT * MAX_M_INPUT,
    364       1073741824);
    365   ixheaacd_fix_to_float_int(
    366       (WORD32 *)self->r_out_im_scratch_m1, (FLOAT32 *)self->r_out_im_in_m1,
    367       MAX_TIME_SLOTS * MAX_PARAMETER_BANDS * MAX_M_OUTPUT * MAX_M_INPUT,
    368       1073741824);
    369 
    370   for (ts = 0; ts < self->time_slots; ts++) {
    371     for (qs = 0; qs < 2; qs++) {
    372       WORD32 sign = -1;
    373       WORD32 indx = self->hyb_band_to_processing_band_table[qs];
    374       for (row = 0; row < (self->dir_sig_count + self->decor_sig_count);
    375            row++) {
    376         FLOAT32 sum_real = 0.0f;
    377         FLOAT32 sum_imag = 0.0f;
    378 
    379         {
    380           FLOAT32 real = self->hyb_in[0][ts][qs].re *
    381                              self->r_out_re_in_m1[ts][indx][row][col] -
    382                          self->hyb_in[0][ts][qs].im *
    383                              self->r_out_im_in_m1[ts][indx][row][col] * sign;
    384           FLOAT32 imag = self->hyb_in[0][ts][qs].re *
    385                              self->r_out_im_in_m1[ts][indx][row][col] * sign +
    386                          self->hyb_in[0][ts][qs].im *
    387                              self->r_out_re_in_m1[ts][indx][row][col];
    388           sum_real += real;
    389           sum_imag += imag;
    390         }
    391         self->v[row][ts][qs].re = sum_real;
    392         self->v[row][ts][qs].im = sum_imag;
    393       }
    394     }
    395     for (qs = 2; qs < self->hyb_band_count; qs++) {
    396       WORD32 sign = 1;
    397       WORD32 indx = self->hyb_band_to_processing_band_table[qs];
    398       for (row = 0; row < (self->dir_sig_count + self->decor_sig_count);
    399            row++) {
    400         FLOAT32 sum_real = 0.0f;
    401         FLOAT32 sum_imag = 0.0f;
    402 
    403         {
    404           FLOAT32 real = self->hyb_in[0][ts][qs].re *
    405                              self->r_out_re_in_m1[ts][indx][row][col] -
    406                          self->hyb_in[0][ts][qs].im *
    407                              self->r_out_im_in_m1[ts][indx][row][col] * sign;
    408           FLOAT32 imag = self->hyb_in[0][ts][qs].re *
    409                              self->r_out_im_in_m1[ts][indx][row][col] * sign +
    410                          self->hyb_in[0][ts][qs].im *
    411                              self->r_out_re_in_m1[ts][indx][row][col];
    412           sum_real += real;
    413           sum_imag += imag;
    414         }
    415         self->v[row][ts][qs].re = sum_real;
    416         self->v[row][ts][qs].im = sum_imag;
    417       }
    418     }
    419   }
    420 }
    421 
    422 VOID ixheaacd_mps_apply_mix_matrix(ia_mps_dec_state_struct *self) {
    423   WORD32 ts, qs, row, col;
    424   WORD32 complex_m2 = ((self->config->bs_phase_coding != 0));
    425   WORD32 phase_interpolation = (self->config->bs_phase_coding == 1);
    426 
    427   ixheaacd_mps_upmix_interp(
    428       self->m2_decor_re, self->r_diff_out_re_fix_in_m2, self->m2_decor_re_prev,
    429       self->out_ch_count, (self->dir_sig_count + self->decor_sig_count), self);
    430   ixheaacd_mps_upmix_interp(
    431       self->m2_resid_re, self->r_out_re_fix_in_m2, self->m2_resid_re_prev,
    432       self->out_ch_count, (self->dir_sig_count + self->decor_sig_count), self);
    433   ixheaacd_fix_to_float_int(
    434       (WORD32 *)self->r_out_re_fix_in_m2, (FLOAT32 *)self->r_out_re_in_m2,
    435       MAX_TIME_SLOTS * MAX_PARAMETER_BANDS * MAX_M_OUTPUT * MAX_M_INPUT,
    436       268435456);
    437   ixheaacd_fix_to_float_int(
    438       (WORD32 *)self->r_diff_out_re_fix_in_m2,
    439       (FLOAT32 *)self->r_out_diff_re_in_m2,
    440       MAX_TIME_SLOTS * MAX_PARAMETER_BANDS * MAX_M_OUTPUT * MAX_M_INPUT,
    441       268435456);
    442 
    443   if (complex_m2 && !phase_interpolation) {
    444     ixheaacd_mps_upmix_interp(self->m2_decor_im, self->r_diff_out_im_fix_in_m2,
    445                               self->m2_decor_im_prev, self->out_ch_count,
    446                               (self->dir_sig_count + self->decor_sig_count),
    447                               self);
    448     ixheaacd_mps_upmix_interp(self->m2_resid_im, self->r_out_im_fix_in_m2,
    449                               self->m2_resid_im_prev, self->out_ch_count,
    450                               (self->dir_sig_count + self->decor_sig_count),
    451                               self);
    452     ixheaacd_fix_to_float_int(
    453         (WORD32 *)self->r_diff_out_im_fix_in_m2,
    454         (FLOAT32 *)self->r_out_diff_im_in_m2,
    455         MAX_TIME_SLOTS * MAX_PARAMETER_BANDS * MAX_M_OUTPUT * MAX_M_INPUT,
    456         268435456);
    457     ixheaacd_fix_to_float_int(
    458         (WORD32 *)self->r_out_im_fix_in_m2, (FLOAT32 *)self->r_out_im_in_m2,
    459         MAX_TIME_SLOTS * MAX_PARAMETER_BANDS * MAX_M_OUTPUT * MAX_M_INPUT,
    460         268435456);
    461   }
    462 
    463   if (phase_interpolation) {
    464     ixheaacd_mps_phase_interpolation(
    465         self->phase_l, self->phase_r, self->phase_l_prev, self->phase_r_prev,
    466         self->r_out_ph_re_in_m2, self->r_out_ph_im_in_m2, self);
    467 
    468     for (ts = 0; ts < self->time_slots; ts++) {
    469       WORD32 pb;
    470       for (pb = 0; pb < self->bs_param_bands; pb++) {
    471         for (row = 0; row < self->out_ch_count; row++) {
    472           for (col = 0; col < (self->dir_sig_count + self->decor_sig_count);
    473                col++) {
    474             self->r_out_im_in_m2[ts][pb][row][col] =
    475                 self->r_out_re_in_m2[ts][pb][row][col] *
    476                 self->r_out_ph_im_in_m2[ts][pb][row];
    477             self->r_out_re_in_m2[ts][pb][row][col] =
    478                 self->r_out_re_in_m2[ts][pb][row][col] *
    479                 self->r_out_ph_re_in_m2[ts][pb][row];
    480 
    481             self->r_out_diff_im_in_m2[ts][pb][row][col] =
    482                 self->r_out_diff_re_in_m2[ts][pb][row][col] *
    483                 self->r_out_ph_im_in_m2[ts][pb][row];
    484             self->r_out_diff_re_in_m2[ts][pb][row][col] =
    485                 self->r_out_diff_re_in_m2[ts][pb][row][col] *
    486                 self->r_out_ph_re_in_m2[ts][pb][row];
    487           }
    488         }
    489       }
    490     }
    491   }
    492 
    493   for (ts = 0; ts < self->time_slots; ts++) {
    494     for (qs = 0; qs < self->hyb_band_count; qs++) {
    495       WORD32 indx = self->hyb_band_to_processing_band_table[qs];
    496       for (row = 0; row < self->out_ch_count; row++) {
    497         FLOAT32 sum_re_dir = 0;
    498         FLOAT32 sum_re_diff = 0;
    499         FLOAT32 sum_im_dir = 0;
    500         FLOAT32 sum_im_diff = 0;
    501         for (col = 0; col < (self->dir_sig_count + self->decor_sig_count);
    502              col++) {
    503           sum_re_dir += self->w_dir[col][ts][qs].re *
    504                         self->r_out_re_in_m2[ts][indx][row][col];
    505           sum_im_dir += self->w_dir[col][ts][qs].im *
    506                         self->r_out_re_in_m2[ts][indx][row][col];
    507           sum_re_diff += self->w_diff[col][ts][qs].re *
    508                          self->r_out_diff_re_in_m2[ts][indx][row][col];
    509           sum_im_diff += self->w_diff[col][ts][qs].im *
    510                          self->r_out_diff_re_in_m2[ts][indx][row][col];
    511         }
    512         self->hyb_dir_out[row][ts][qs].re = sum_re_dir;
    513         self->hyb_dir_out[row][ts][qs].im = sum_im_dir;
    514         self->hyb_diff_out[row][ts][qs].re = sum_re_diff;
    515         self->hyb_diff_out[row][ts][qs].im = sum_im_diff;
    516       }
    517     }
    518   }
    519 
    520   if (complex_m2) {
    521     for (ts = 0; ts < self->time_slots; ts++) {
    522       for (qs = 0; qs < 2; qs++) {
    523         WORD32 indx = self->hyb_band_to_processing_band_table[qs];
    524         for (row = 0; row < self->out_ch_count; row++) {
    525           FLOAT32 sum_re_dir = self->hyb_dir_out[row][ts][qs].re;
    526           FLOAT32 sum_im_dir = self->hyb_dir_out[row][ts][qs].im;
    527           FLOAT32 sum_re_diff = self->hyb_diff_out[row][ts][qs].re;
    528           FLOAT32 sum_im_diff = self->hyb_diff_out[row][ts][qs].im;
    529           for (col = 0; col < (self->dir_sig_count + self->decor_sig_count);
    530                col++) {
    531             sum_re_dir += self->w_dir[col][ts][qs].im *
    532                           self->r_out_im_in_m2[ts][indx][row][col];
    533             sum_im_dir -= self->w_dir[col][ts][qs].re *
    534                           self->r_out_im_in_m2[ts][indx][row][col];
    535             sum_re_diff += self->w_diff[col][ts][qs].im *
    536                            self->r_out_diff_im_in_m2[ts][indx][row][col];
    537             sum_im_diff -= self->w_diff[col][ts][qs].re *
    538                            self->r_out_diff_im_in_m2[ts][indx][row][col];
    539           }
    540           self->hyb_dir_out[row][ts][qs].re = sum_re_dir;
    541           self->hyb_dir_out[row][ts][qs].im = sum_im_dir;
    542           self->hyb_diff_out[row][ts][qs].re = sum_re_diff;
    543           self->hyb_diff_out[row][ts][qs].im = sum_im_diff;
    544         }
    545       }
    546       for (qs = 2; qs < self->hyb_band_count; qs++) {
    547         WORD32 indx = self->hyb_band_to_processing_band_table[qs];
    548         for (row = 0; row < self->out_ch_count; row++) {
    549           FLOAT32 sum_re_dir = self->hyb_dir_out[row][ts][qs].re;
    550           FLOAT32 sum_im_dir = self->hyb_dir_out[row][ts][qs].im;
    551           FLOAT32 sum_re_diff = self->hyb_diff_out[row][ts][qs].re;
    552           FLOAT32 sum_im_diff = self->hyb_diff_out[row][ts][qs].im;
    553           for (col = 0; col < (self->dir_sig_count + self->decor_sig_count);
    554                col++) {
    555             sum_re_dir -= self->w_dir[col][ts][qs].im *
    556                           self->r_out_im_in_m2[ts][indx][row][col];
    557             sum_im_dir += self->w_dir[col][ts][qs].re *
    558                           self->r_out_im_in_m2[ts][indx][row][col];
    559             sum_re_diff -= self->w_diff[col][ts][qs].im *
    560                            self->r_out_diff_im_in_m2[ts][indx][row][col];
    561             sum_im_diff += self->w_diff[col][ts][qs].re *
    562                            self->r_out_diff_im_in_m2[ts][indx][row][col];
    563           }
    564           self->hyb_dir_out[row][ts][qs].re = sum_re_dir;
    565           self->hyb_dir_out[row][ts][qs].im = sum_im_dir;
    566           self->hyb_diff_out[row][ts][qs].re = sum_re_diff;
    567           self->hyb_diff_out[row][ts][qs].im = sum_im_diff;
    568         }
    569       }
    570     }
    571   }
    572 }
    573 
    574 static PLATFORM_INLINE WORD32 ixheaacd_mult32_shl2(WORD32 a, WORD32 b) {
    575   WORD32 result;
    576   WORD64 temp_result;
    577 
    578   temp_result = (WORD64)a * (WORD64)b;
    579   result = (WORD32)(temp_result >> 30);
    580 
    581   return (result);
    582 }
    583 
    584 VOID ixheaacd_mps_upmix_interp(
    585     WORD32 m_matrix[MAX_PARAMETER_SETS_MPS][MAX_PARAMETER_BANDS][MAX_M_OUTPUT]
    586                    [MAX_M_INPUT],
    587     WORD32 r_matrix[MAX_TIME_SLOTS][MAX_PARAMETER_BANDS][MAX_M_OUTPUT]
    588                    [MAX_M_INPUT],
    589     WORD32 m_matrix_prev[MAX_PARAMETER_BANDS][MAX_M_OUTPUT][MAX_M_INPUT],
    590     WORD32 num_rows, WORD32 num_cols, ia_mps_dec_state_struct *self) {
    591   WORD32 ts, ps, pb, row, col, i;
    592 
    593   for (pb = 0; pb < self->bs_param_bands; pb++) {
    594     for (row = 0; row < num_rows; row++) {
    595       for (col = 0; col < num_cols; col++) {
    596         ps = 0;
    597         ts = 0;
    598         for (i = 1; i <= (WORD32)self->param_slot_diff[0]; i++) {
    599           WORD32 alpha = i * self->inv_param_slot_diff_Q30[ps];
    600           WORD32 one_minus_alpha = 1073741824 - alpha;
    601           r_matrix[ts][pb][row][col] =
    602               ((ixheaacd_mult32_shl2(m_matrix_prev[pb][row][col],
    603                                      one_minus_alpha) +
    604                 ixheaacd_mult32_shl2(alpha, m_matrix[ps][pb][row][col])));
    605           ts++;
    606         }
    607 
    608         for (ps = 1; ps < self->num_parameter_sets; ps++) {
    609           for (i = 1; i <= (WORD32)self->param_slot_diff[ps]; i++) {
    610             WORD32 alpha = i * self->inv_param_slot_diff_Q30[ps];
    611             WORD32 one_minus_alpha = 1073741824 - alpha;
    612             r_matrix[ts][pb][row][col] =
    613                 ((ixheaacd_mult32_shl2(m_matrix[ps - 1][pb][row][col],
    614                                        one_minus_alpha) +
    615                   ixheaacd_mult32_shl2(alpha, m_matrix[ps][pb][row][col])));
    616             ts++;
    617           }
    618         }
    619       }
    620     }
    621   }
    622 }
    623 
    624 static FLOAT32 ixheaacd_mps_angle_interpolation(FLOAT32 angle1, FLOAT32 angle2,
    625                                                 FLOAT32 alpha) {
    626   while (angle2 - angle1 > (FLOAT32)P_PI)
    627     angle1 = angle1 + 2.0f * (FLOAT32)P_PI;
    628   while (angle1 - angle2 > (FLOAT32)P_PI)
    629     angle2 = angle2 + 2.0f * (FLOAT32)P_PI;
    630 
    631   return (1 - alpha) * angle1 + alpha * angle2;
    632 }
    633 
    634 VOID ixheaacd_mps_phase_interpolation(
    635     FLOAT32 pl[MAX_PARAMETER_SETS_MPS][MAX_PARAMETER_BANDS],
    636     FLOAT32 pr[MAX_PARAMETER_SETS_MPS][MAX_PARAMETER_BANDS],
    637     FLOAT32 pl_prev[MAX_PARAMETER_BANDS], FLOAT32 pr_prev[MAX_PARAMETER_BANDS],
    638     FLOAT32 r_re[MAX_TIME_SLOTS][MAX_PARAMETER_BANDS][2],
    639     FLOAT32 r_im[MAX_TIME_SLOTS][MAX_PARAMETER_BANDS][2],
    640     ia_mps_dec_state_struct *self) {
    641   WORD32 ts, ps, pb;
    642   WORD32 i;
    643   for (pb = 0; pb < self->bs_param_bands; pb++) {
    644     ps = 0;
    645     ts = 0;
    646     for (i = 1; i <= self->param_slot_diff[ps]; i++) {
    647       FLOAT32 alpha = (FLOAT32)i * self->inv_param_slot_diff[ps];
    648       FLOAT32 t;
    649 
    650       t = ixheaacd_mps_angle_interpolation(pl_prev[pb], pl[ps][pb], alpha);
    651       r_re[ts][pb][0] = (FLOAT32)cos(t);
    652       r_im[ts][pb][0] = (FLOAT32)sin(t);
    653 
    654       t = ixheaacd_mps_angle_interpolation(pr_prev[pb], pr[ps][pb], alpha);
    655       r_re[ts][pb][1] = (FLOAT32)cos(t);
    656       r_im[ts][pb][1] = (FLOAT32)sin(t);
    657       ts++;
    658     }
    659 
    660     for (ps = 1; ps < self->num_parameter_sets; ps++) {
    661       for (i = 1; i <= self->param_slot_diff[ps]; i++) {
    662         FLOAT32 alpha = (FLOAT32)i * self->inv_param_slot_diff[ps];
    663         FLOAT32 t;
    664 
    665         t = ixheaacd_mps_angle_interpolation(pl[ps - 1][pb], pl[ps][pb], alpha);
    666         r_re[ts][pb][0] = (FLOAT32)cos(t);
    667         r_im[ts][pb][0] = (FLOAT32)sin(t);
    668 
    669         t = ixheaacd_mps_angle_interpolation(pr[ps - 1][pb], pr[ps][pb], alpha);
    670         r_re[ts][pb][1] = (FLOAT32)cos(t);
    671         r_im[ts][pb][1] = (FLOAT32)sin(t);
    672         ts++;
    673       }
    674     }
    675   }
    676 }
    677 
    678 VOID ixheaacd_mps_init_pre_and_post_matrix(ia_mps_dec_state_struct *self) {
    679   memset(self->m1_param_re_prev, 0,
    680          MAX_PARAMETER_BANDS * MAX_M_OUTPUT * MAX_M_INPUT * sizeof(WORD32));
    681   memset(self->m1_param_im_prev, 0,
    682          MAX_PARAMETER_BANDS * MAX_M_OUTPUT * MAX_M_INPUT * sizeof(WORD32));
    683   memset(self->m1_param_re_prev, 0,
    684          MAX_PARAMETER_BANDS * MAX_M_OUTPUT * MAX_M_INPUT * sizeof(WORD32));
    685   memset(self->m2_decor_re_prev, 0,
    686          MAX_PARAMETER_BANDS * MAX_M_OUTPUT * MAX_M_INPUT * sizeof(WORD32));
    687   memset(self->m2_resid_re_prev, 0,
    688          MAX_PARAMETER_BANDS * MAX_M_OUTPUT * MAX_M_INPUT * sizeof(WORD32));
    689   memset(self->m2_resid_im_prev, 0,
    690          MAX_PARAMETER_BANDS * MAX_M_OUTPUT * MAX_M_INPUT * sizeof(WORD32));
    691 }
    692