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
53extern const WORD32 ixheaacd_im_weight_Q28[16][8][31];
54extern const WORD32 ixheaacd_re_weight_Q28[16][8][31];
55extern const WORD32 ixheaacd_beta_Q28[16][8][31];
56extern const WORD32 ixheaacd_weight_Q28[16][8][31];
57extern const WORD32 ixheaacd_c_l_table_Q31[31];
58extern const WORD32 ixheaacd_sin_table_Q31[16][31];
59extern const WORD32 ixheaacd_cos_table_Q31[16][31];
60extern const WORD32 ixheaacd_atan_table_Q28[16][8][31];
61extern WORD32 ixheaacd_ipd_de_quant_table_q28[16];
62
63#define P_PI 3.1415926535897932
64#define PI_IN_Q28 843314880
65
66extern WORD32 ixheaacd_ipd_de_quant_table_q28[16];
67
68#define P_PI 3.1415926535897932
69#define PI_IN_Q28 843314880
70
71static 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
81static 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
112VOID 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
120VOID 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
193static 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
223VOID 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
231static 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
249VOID 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
283VOID 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
351VOID 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
422VOID 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
574static 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
584VOID 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
624static 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
634VOID 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
678VOID 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