xref: /aosp_15_r20/external/libxaac/decoder/ixheaacd_mps_decorr.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
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 <math.h>
21 #include <string.h>
22 #include "ixheaac_type_def.h"
23 #include "ixheaacd_bitbuffer.h"
24 #include "ixheaacd_common_rom.h"
25 #include "ixheaacd_sbrdecsettings.h"
26 #include "ixheaacd_sbr_scale.h"
27 #include "ixheaacd_env_extr_part.h"
28 #include "ixheaacd_sbr_rom.h"
29 #include "ixheaacd_hybrid.h"
30 #include "ixheaacd_ps_dec.h"
31 #include "ixheaacd_config.h"
32 #include "ixheaacd_qmf_dec.h"
33 #include "ixheaacd_audioobjtypes.h"
34 #include "ixheaacd_mps_polyphase.h"
35 #include "ixheaacd_mps_struct_def.h"
36 #include "ixheaacd_mps_res_rom.h"
37 #include "ixheaacd_mps_aac_struct.h"
38 #include "ixheaac_constants.h"
39 #include "ixheaacd_mps_dec.h"
40 #include "ixheaacd_mps_decor.h"
41 #include "ixheaacd_mps_hybfilter.h"
42 #include "ixheaac_error_standards.h"
43 #include "ixheaac_basic_ops32.h"
44 #include "ixheaac_basic_ops40.h"
45 #include "ixheaacd_mps_macro_def.h"
46 #include "ixheaacd_mps_basic_op.h"
47 
48 static const WORD32 ixheaacd_decorr_delay[] = {11, 10, 5, 2};
49 static const WORD32 ixheaacd_decorr_delay_ldmps[] = {8, 7, 2, 1};
50 
51 static const WORD32 ixheaacd_qmf_split_freq_0[] = {3, 15, 24, 65};
52 static const WORD32 ixheaacd_qmf_split_freq_1[] = {3, 50, 65, 65};
53 static const WORD32 ixheaacd_qmf_split_freq_2[] = {0, 15, 65, 65};
54 
55 
56 static const WORD32 ixheaacd_qmf_split_freq_0_ldmps[] = {0, 15, 24, 65};
57 static const WORD32 ixheaacd_qmf_split_freq_1_ldmps[] = {0, 50, 65, 65};
58 static const WORD32 ixheaacd_qmf_split_freq_2_ldmps[] = {0, 15, 65, 65};
59 
60 extern const WORD32 ixheaacd_mps_gain_set_indx[29];
61 
62 static const FLOAT32
63     ixheaacd_lattice_coeff_0_filt_den_coeff[DECORR_FILT_0_ORD + 1] = {
64         1.000000f, -0.314818f, -0.256828f, -0.173641f, -0.115077f, 0.000599f,
65         0.033343f, 0.122672f,  -0.356362f, 0.128058f,  0.089800f};
66 static const FLOAT32
67     ixheaacd_lattice_coeff_0_filt_num_coeff[DECORR_FILT_0_ORD + 1] = {
68         0.089800f,  0.128058f,  -0.356362f, 0.122672f,  0.033343f, 0.000599f,
69         -0.115077f, -0.173641f, -0.256828f, -0.314818f, 1.000000f};
70 
71 static const FLOAT32
72     ixheaacd_lattice_coeff_1_filt_den_coeff[DECORR_FILT_1_ORD + 1] = {
73         1.000000f, -0.287137f, -0.088940f, 0.123204f, -0.126111f,
74         0.064218f, 0.045768f,  -0.016264f, -0.122100f};
75 static const FLOAT32
76     ixheaacd_lattice_coeff_1_filt_num_coeff[DECORR_FILT_1_ORD + 1] = {
77         -0.122100f, -0.016264f, 0.045768f,  0.064218f, -0.126111f,
78         0.123204f,  -0.088940f, -0.287137f, 1.000000f};
79 
80 static const FLOAT32
81     ixheaacd_lattice_coeff_2_filt_den_coeff[DECORR_FILT_2_ORD + 1] = {
82         1.000000f, 0.129403f, -0.032633f, 0.035700f};
83 static const FLOAT32
84     ixheaacd_lattice_coeff_2_filt_num_coeff[DECORR_FILT_2_ORD + 1] = {
85         0.035700f, -0.032633f, 0.129403f, 1.000000f};
86 
87 static const FLOAT32
88     ixheaacd_lattice_coeff_3_filt_den_coeff[DECORR_FILT_3_ORD + 1] = {
89         1.000000f, 0.034742f, -0.013000f};
90 static const FLOAT32
91     ixheaacd_lattice_coeff_3_filt_num_coeff[DECORR_FILT_3_ORD + 1] = {
92         -0.013000f, 0.034742f, 1.000000f};
93 
94 static const FLOAT32
95     ixheaacd_lattice_coeff_1_filt_num_ldmps[DECORR_FILTER_ORDER_BAND_1 + 1] = {
96         (0.3355999887f),  (0.0024894588f),  (-0.1572290659f), (0.2807503343f),
97         (-0.1942857355f), (0.3840600252f),  (-0.4084388912f), (-0.1750483066f),
98         (0.5559588671f),  (-0.4935829639f), (0.0567415841f),  (-0.0658148378f),
99         (0.3378961682f),  (0.2284426540f),  (-0.7025330663f), (1.0000000000f)};
100 
101 static const FLOAT32
102     ixheaacd_lattice_coeff_1_filt_den_ldmps[DECORR_FILTER_ORDER_BAND_1 + 1] = {
103         (1.0000000000f),  (-0.7025330663f), (0.2284426540f),  (0.3378961682f),
104         (-0.0658148378f), (0.0567415841f),  (-0.4935829639f), (0.5559588671f),
105         (-0.1750483066f), (-0.4084388912f), (0.3840600252f),  (-0.1942857355f),
106         (0.2807503343f),  (-0.1572290659f), (0.0024894588f),  (0.3355999887f)};
107 
108 static const FLOAT32
109     ixheaacd_lattice_coeff_2_filt_num_ldmps[DECORR_FILTER_ORDER_BAND_2 + 1] = {
110         (-0.4623999894f), (0.2341193259f), (0.5163637400f), (-0.0253488291f),
111         (-0.2871030867f), (0.0153170601f), (1.0000000000f)};
112 
113 static const FLOAT32
114     ixheaacd_lattice_coeff_2_filt_den_ldmps[DECORR_FILTER_ORDER_BAND_2 + 1] = {
115         (1.0000000000f), (0.0153170601f), (-0.2871030867f), (-0.0253488291f),
116         (0.5163637400f), (0.2341193259f), (-0.4623999894f)
117 
118 };
119 
120 static const FLOAT32
121     ixheaacd_lattice_coeff_3_filt_num_ldmps[DECORR_FILTER_ORDER_BAND_3 + 1] = {
122         (0.2468000054f), (0.0207958221f), (-0.3898491263f), (1.0000000000f)};
123 
124 static const FLOAT32
125     ixheaacd_lattice_coeff_3_filt_den_ldmps[DECORR_FILTER_ORDER_BAND_3 + 1] = {
126         (1.0000000000f), (-0.3898491263f), (0.0207958221f), (0.2468000054f)};
127 
128 extern WORD32
129     ixheaacd_hybrid_band_71_to_processing_band_28_map[MAX_HYBRID_BANDS_MPS];
130 extern WORD32
131     ixheaacd_hybrid_band_64_to_processing_band_23_map[MAX_HYBRID_BANDS_MPS];
132 
133 static const WORD32 ixheaacd_hybrid_to_qmf_map[MAX_HYBRID_BANDS_MPS] = {
134     0,  0,  0,  0,  0,  0,  1,  1,  2,  2,  3,  4,  5,  6,  7,  8,  9,  10,
135     11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
136     29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
137     47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
138 
139 static const WORD32 ixheaacd_hybrid_to_qmf_map_ldmps[MAX_HYBRID_BANDS_MPS] = {
140     0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16, 17,
141     18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
142     36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
143     54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70};
144 
ixheaacd_mps_decor_filt_init(ia_mps_decor_filt_struct * self,WORD32 reverb_band,WORD32 object_type)145 static VOID ixheaacd_mps_decor_filt_init(ia_mps_decor_filt_struct *self,
146                                          WORD32 reverb_band,
147                                          WORD32 object_type) {
148   if (object_type == AOT_ER_AAC_ELD || object_type == AOT_ER_AAC_LD) {
149     switch (reverb_band) {
150       case 0:
151         self->num_len = self->den_len = DECORR_FILTER_ORDER_BAND_0 + 1;
152         self->num = NULL;
153         self->den = NULL;
154 
155         break;
156       case 1:
157         self->num_len = self->den_len = DECORR_FILTER_ORDER_BAND_1 + 1;
158         self->num = ixheaacd_lattice_coeff_1_filt_num_ldmps;
159         self->den = ixheaacd_lattice_coeff_1_filt_den_ldmps;
160 
161         break;
162       case 2:
163         self->num_len = self->den_len = DECORR_FILTER_ORDER_BAND_2 + 1;
164         self->num = ixheaacd_lattice_coeff_2_filt_num_ldmps;
165         self->den = ixheaacd_lattice_coeff_2_filt_den_ldmps;
166         break;
167       case 3:
168         self->num_len = self->den_len = DECORR_FILTER_ORDER_BAND_3 + 1;
169         self->num = ixheaacd_lattice_coeff_3_filt_num_ldmps;
170         self->den = ixheaacd_lattice_coeff_3_filt_den_ldmps;
171         break;
172     }
173   } else {
174     switch (reverb_band) {
175       case 0:
176         self->num_len = self->den_len = DECORR_FILT_0_ORD + 1;
177         self->num = ixheaacd_lattice_coeff_0_filt_num_coeff;
178         self->den = ixheaacd_lattice_coeff_0_filt_den_coeff;
179 
180         break;
181       case 1:
182         self->num_len = self->den_len = DECORR_FILT_1_ORD + 1;
183         self->num = ixheaacd_lattice_coeff_1_filt_num_coeff;
184         self->den = ixheaacd_lattice_coeff_1_filt_den_coeff;
185 
186         break;
187       case 2:
188         self->num_len = self->den_len = DECORR_FILT_2_ORD + 1;
189         self->num = ixheaacd_lattice_coeff_2_filt_num_coeff;
190         self->den = ixheaacd_lattice_coeff_2_filt_den_coeff;
191         break;
192       case 3:
193         self->num_len = self->den_len = DECORR_FILT_3_ORD + 1;
194         self->num = ixheaacd_lattice_coeff_3_filt_num_coeff;
195         self->den = ixheaacd_lattice_coeff_3_filt_den_coeff;
196         break;
197     }
198   }
199 
200   self->state_len = self->num_len;
201   memset(self->state, 0,
202          sizeof(ia_cmplx_flt_struct) * (MAX_DECORR_FILTER_ORDER + 1));
203 
204   return;
205 }
206 
ixheaacd_mps_allpass_apply(ia_mps_decor_filt_struct * self,ia_cmplx_flt_struct * input,WORD32 len,ia_cmplx_flt_struct * output)207 static VOID ixheaacd_mps_allpass_apply(ia_mps_decor_filt_struct *self,
208                                        ia_cmplx_flt_struct *input, WORD32 len,
209                                        ia_cmplx_flt_struct *output) {
210   WORD32 i, j;
211 
212   for (i = 0; i < len; i++) {
213     output[i].re = self->state[0].re + input[i].re * self->num[0];
214     output[i].im = self->state[0].im + input[i].im * self->num[0];
215 
216     for (j = 1; j < self->num_len; j++) {
217       self->state[j - 1].re = self->state[j].re + self->num[j] * input[i].re -
218                               self->den[j] * output[i].re;
219       self->state[j - 1].im = self->state[j].im + self->num[j] * input[i].im -
220                               self->den[j] * output[i].im;
221     }
222   }
223 }
224 
ixheaacd_mps_decor_energy_adjustment(ixheaacd_mps_decor_energy_adjust_filt_struct * handle,ia_cmplx_flt_struct in[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS],ia_cmplx_flt_struct out[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS],WORD32 time_slots,WORD32 res_bands,WORD32 ldmps_present)225 static VOID ixheaacd_mps_decor_energy_adjustment(
226     ixheaacd_mps_decor_energy_adjust_filt_struct *handle,
227     ia_cmplx_flt_struct in[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS],
228     ia_cmplx_flt_struct out[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS],
229     WORD32 time_slots, WORD32 res_bands, WORD32 ldmps_present) {
230   ixheaacd_mps_decor_energy_adjust_filt_struct *self =
231       (ixheaacd_mps_decor_energy_adjust_filt_struct *)handle;
232   FLOAT32 in_energy[MAX_PARAMETER_BANDS] = {0};
233   FLOAT32 out_energy[MAX_PARAMETER_BANDS] = {0};
234   FLOAT32 gain[MAX_PARAMETER_BANDS];
235   WORD32 i, j, k, loop_counter;
236   WORD32 *ptr_hybrid_band;
237 
238   if (ldmps_present == 1)
239     ptr_hybrid_band = ixheaacd_hybrid_band_64_to_processing_band_23_map;
240   else
241     ptr_hybrid_band = ixheaacd_hybrid_band_71_to_processing_band_28_map;
242 
243   WORD32 start_param_band = 0, start_bin = 0;
244 
245   if (res_bands != NO_RES_BANDS) {
246     start_bin = ixheaacd_mps_gain_set_indx[res_bands];
247     start_param_band = res_bands;
248   }
249 
250   for (i = 0; i < time_slots; i++) {
251     memset(in_energy, 0, sizeof(FLOAT32) * MAX_PARAMETER_BANDS);
252     memset(out_energy, 0, sizeof(FLOAT32) * MAX_PARAMETER_BANDS);
253 
254     for (j = start_bin; j < self->num_bins; j++) {
255       k = ptr_hybrid_band[j];
256 
257       in_energy[k] += in[i][j].re * in[i][j].re + in[i][j].im * in[i][j].im;
258       out_energy[k] +=
259           out[i][j].re * out[i][j].re + out[i][j].im * out[i][j].im;
260     }
261 
262     loop_counter = MAX_PARAMETER_BANDS;
263 
264     for (k = start_param_band; k < loop_counter; k++) {
265       self->smooth_in_energy[k] = self->smooth_in_energy[k] * DECOR_ALPHA +
266                                   in_energy[k] * ONE_MINUS_DECOR_ALPHA;
267       self->smooth_out_energy[k] = self->smooth_out_energy[k] * DECOR_ALPHA +
268                                    out_energy[k] * ONE_MINUS_DECOR_ALPHA;
269 
270       gain[k] = 1.0f;
271 
272       if (self->smooth_out_energy[k] >
273           self->smooth_in_energy[k] * DECOR_GAMMA) {
274         gain[k] = (FLOAT32)sqrt(self->smooth_in_energy[k] * DECOR_GAMMA /
275                                 (self->smooth_out_energy[k] + ABS_THR));
276       }
277 
278       if (self->smooth_in_energy[k] >
279           self->smooth_out_energy[k] * DECOR_GAMMA) {
280         gain[k] =
281             min(2.0f, (FLOAT32)sqrt(self->smooth_in_energy[k] /
282                                     (DECOR_GAMMA * self->smooth_out_energy[k] +
283                                      ABS_THR)));
284       }
285     }
286 
287     for (j = start_bin; j < self->num_bins; j++) {
288       k = ptr_hybrid_band[j];
289 
290       out[i][j].re *= gain[k];
291       out[i][j].im *= gain[k];
292     }
293   }
294 }
295 
ixheaacd_mps_decor_init(ia_mps_decor_struct * self,WORD32 subbands,WORD32 decor_config,WORD32 object_type)296 IA_ERRORCODE ixheaacd_mps_decor_init(ia_mps_decor_struct *self,
297                                      WORD32 subbands, WORD32 decor_config,
298                                      WORD32 object_type) {
299   WORD32 i, reverb_band;
300   const WORD32 *splitfreq;
301   const WORD32 *ptr_ixheaacd_hybrid_to_qmf_map;
302   const WORD32 *ptr_decorr_delay;
303   if (object_type == AOT_ER_AAC_ELD || object_type == AOT_ER_AAC_LD) {
304     ptr_ixheaacd_hybrid_to_qmf_map = ixheaacd_hybrid_to_qmf_map_ldmps;
305     ptr_decorr_delay = ixheaacd_decorr_delay_ldmps;
306     switch (decor_config) {
307       case 0:
308         splitfreq = ixheaacd_qmf_split_freq_0_ldmps;
309         break;
310       case 1:
311         splitfreq = ixheaacd_qmf_split_freq_1_ldmps;
312         break;
313       case 2:
314         splitfreq = ixheaacd_qmf_split_freq_2_ldmps;
315         break;
316       default:
317         return IA_FATAL_ERROR;
318     }
319   } else {
320     ptr_ixheaacd_hybrid_to_qmf_map = ixheaacd_hybrid_to_qmf_map;
321     ptr_decorr_delay = ixheaacd_decorr_delay;
322     switch (decor_config) {
323       case 0:
324         splitfreq = ixheaacd_qmf_split_freq_0;
325         break;
326       case 1:
327         splitfreq = ixheaacd_qmf_split_freq_1;
328         break;
329       case 2:
330         splitfreq = ixheaacd_qmf_split_freq_2;
331         break;
332       default:
333         return IA_FATAL_ERROR;
334     }
335   }
336 
337   self->num_bins = subbands;
338   if (self->num_bins > MAX_HYBRID_BANDS_MPS) return IA_FATAL_ERROR;
339 
340   for (i = 0; i < self->num_bins; i++) {
341     reverb_band = 0;
342     while ((reverb_band < 3) &&
343            (ptr_ixheaacd_hybrid_to_qmf_map[i] >= (splitfreq[reverb_band] - 1)))
344       reverb_band++;
345 
346     self->delay_sample_count[i] = ptr_decorr_delay[reverb_band];
347     ixheaacd_mps_decor_filt_init(&self->filter[i], reverb_band, object_type);
348   }
349 
350   self->decor_nrg_smooth.num_bins = self->num_bins;
351 
352   return IA_NO_ERROR;
353 }
354 
ixheaacd_mps_decor_apply(ia_mps_decor_struct * self,ia_cmplx_flt_struct in[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS],ia_cmplx_flt_struct out[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS],WORD32 length,WORD32 res_bands,WORD32 ldmps_present)355 VOID ixheaacd_mps_decor_apply(
356     ia_mps_decor_struct *self,
357     ia_cmplx_flt_struct in[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS],
358     ia_cmplx_flt_struct out[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS],
359     WORD32 length, WORD32 res_bands, WORD32 ldmps_present) {
360   WORD32 idx, sb_sample, index = 0;
361 
362   ia_cmplx_flt_struct scratch[MAX_TIME_SLOTS];
363 
364   if (res_bands != NO_RES_BANDS) index = ixheaacd_mps_gain_set_indx[res_bands];
365 
366   for (idx = index; idx < self->num_bins; idx++) {
367     for (sb_sample = 0; sb_sample < length; sb_sample++) {
368       self->decor_delay_buffer[idx][self->delay_sample_count[idx] + sb_sample]
369           .re = in[sb_sample][idx].re;
370       self->decor_delay_buffer[idx][self->delay_sample_count[idx] + sb_sample]
371           .im = in[sb_sample][idx].im;
372     }
373     ixheaacd_mps_allpass_apply(&self->filter[idx],
374                                self->decor_delay_buffer[idx], length, scratch);
375 
376     for (sb_sample = 0; sb_sample < length; sb_sample++) {
377       out[sb_sample][idx].re = scratch[sb_sample].re;
378       out[sb_sample][idx].im = scratch[sb_sample].im;
379     }
380 
381     for (sb_sample = 0; sb_sample < self->delay_sample_count[idx];
382          sb_sample++) {
383       self->decor_delay_buffer[idx][sb_sample].re =
384           self->decor_delay_buffer[idx][length + sb_sample].re;
385       self->decor_delay_buffer[idx][sb_sample].im =
386           self->decor_delay_buffer[idx][length + sb_sample].im;
387     }
388   }
389 
390   ixheaacd_mps_decor_energy_adjustment(&self->decor_nrg_smooth, in, out, length,
391                                        res_bands,
392                                        ldmps_present);
393 }
394 
ixheaacd_convert_lattice_coefs_complex(WORD32 const order,WORD32 const * const rfc_real,WORD32 const * const rfc_imag,WORD32 * const apar_real,WORD32 * const apar_imag)395 static VOID ixheaacd_convert_lattice_coefs_complex(WORD32 const order,
396                                                    WORD32 const *const rfc_real,
397                                                    WORD32 const *const rfc_imag,
398                                                    WORD32 *const apar_real,
399                                                    WORD32 *const apar_imag) {
400   WORD32 i, j;
401   WORD32 tmp_real[MAX_DECORR_FILTER_ORDER + 1];
402   WORD32 tmp_imag[MAX_DECORR_FILTER_ORDER + 1];
403   WORD64 temp;
404 
405   apar_real[0] = 32768;
406   apar_imag[0] = 0;
407 
408   for (i = 0; i < order; i++) {
409     apar_real[i + 1] = rfc_real[i];
410     apar_imag[i + 1] = rfc_imag[i];
411     for (j = 0; j < i; j++) {
412       temp = (WORD64)((WORD64)rfc_real[i] * (WORD64)tmp_real[i - j - 1] +
413                       (WORD64)rfc_imag[i] * (WORD64)tmp_imag[i - j - 1]);
414       temp >>= 15;
415       apar_real[j + 1] = ixheaac_add32(tmp_real[j], (WORD32)temp);
416 
417       temp = (WORD64)((WORD64)rfc_real[i] * (WORD64)tmp_imag[i - j - 1] +
418                       (WORD64)rfc_imag[i] * (WORD64)tmp_real[i - j - 1]);
419       temp >>= 15;
420       apar_imag[j + 1] = ixheaac_sub32(tmp_imag[j], (WORD32)temp);
421     }
422     for (j = 0; j <= i; j++) {
423       tmp_real[j] = apar_real[j + 1];
424       tmp_imag[j] = apar_imag[j + 1];
425     }
426   }
427 }
428 
ixheaacd_decorr_filt_create(ia_mps_dec_decorr_filter_instance_struct * self,WORD32 const decorr_seed,WORD32 const qmf_band,WORD32 const reverb_band,WORD32 const dec_type,ia_mps_dec_mps_tables_struct * ia_mps_dec_mps_table)429 static IA_ERRORCODE ixheaacd_decorr_filt_create(
430     ia_mps_dec_decorr_filter_instance_struct *self, WORD32 const decorr_seed,
431     WORD32 const qmf_band, WORD32 const reverb_band, WORD32 const dec_type,
432     ia_mps_dec_mps_tables_struct *ia_mps_dec_mps_table) {
433   IA_ERRORCODE error_code = IA_NO_ERROR;
434   WORD32 i;
435   const WORD32 *lattice_coeff = NULL;
436   WORD32 lattice_coeff_real[MAX_DECORR_FILTER_ORDER];
437   WORD32 lattice_coeff_imag[MAX_DECORR_FILTER_ORDER];
438   WORD32 temp_1;
439 
440   if (self == NULL) {
441     error_code = IA_FATAL_ERROR;
442   }
443 
444   if (error_code == IA_NO_ERROR) {
445     switch (reverb_band) {
446       case REVERB_BAND_0:
447         self->num_length = self->den_length = DECORR_FILTER_ORDER_BAND_0 + 1;
448         lattice_coeff = &(ia_mps_dec_mps_table->decor_table_ptr
449                               ->lattice_coeff_0[decorr_seed][0]);
450         break;
451       case REVERB_BAND_1:
452         self->num_length = self->den_length = DECORR_FILTER_ORDER_BAND_1 + 1;
453         lattice_coeff = &(ia_mps_dec_mps_table->decor_table_ptr
454                               ->lattice_coeff_1[decorr_seed][0]);
455         break;
456       case REVERB_BAND_2:
457         self->num_length = self->den_length = DECORR_FILTER_ORDER_BAND_2 + 1;
458         lattice_coeff = &(ia_mps_dec_mps_table->decor_table_ptr
459                               ->lattice_coeff_2[decorr_seed][0]);
460         break;
461       case REVERB_BAND_3:
462         self->num_length = self->den_length = DECORR_FILTER_ORDER_BAND_3 + 1;
463         lattice_coeff = &(ia_mps_dec_mps_table->decor_table_ptr
464                               ->lattice_coeff_3[decorr_seed][0]);
465         break;
466       default:
467         return IA_FATAL_ERROR;
468     }
469     self->state_length = (self->num_length > self->den_length)
470                              ? self->num_length
471                              : self->den_length;
472   }
473 
474   if (error_code == IA_NO_ERROR) {
475     const WORD32 *cos_tab =
476         ia_mps_dec_mps_table->hybrid_table_ptr->cosine_array;
477     const WORD32 *sin_tab = ia_mps_dec_mps_table->hybrid_table_ptr->sine_array;
478 
479     if (dec_type == 1) {
480       for (i = 0; i < self->num_length - 1; i++) {
481         temp_1 = (qmf_band * ia_mps_dec_mps_table->decor_table_ptr
482                                  ->lattice_delta_phi[decorr_seed][i]) >>
483                  1;
484         lattice_coeff_real[i] = ixheaacd_mps_mult32_shr_15(
485             ixheaacd_mps_cos(temp_1, cos_tab), lattice_coeff[i]);
486         lattice_coeff_imag[i] = ixheaacd_mps_mult32_shr_15(
487             ixheaacd_mps_sin(temp_1, sin_tab), lattice_coeff[i]);
488       }
489 
490       ixheaacd_convert_lattice_coefs_complex(
491           self->num_length - 1, lattice_coeff_real, lattice_coeff_imag,
492           self->denominator_real, self->denominator_imag);
493       for (i = 0; i < self->num_length; i++) {
494         self->numerator_real[i] =
495             self->denominator_real[self->num_length - 1 - i];
496         self->numerator_imag[i] =
497             -self->denominator_imag[self->num_length - 1 - i];
498       }
499 
500       self->complex = 1;
501     } else {
502       switch (reverb_band) {
503         case REVERB_BAND_0:
504           self->denominator_real = &(ia_mps_dec_mps_table->decor_table_ptr
505                                          ->den_coef_0[decorr_seed][0]);
506           break;
507         case REVERB_BAND_1:
508           self->denominator_real = &(ia_mps_dec_mps_table->decor_table_ptr
509                                          ->den_coef_1[decorr_seed][0]);
510           break;
511         case REVERB_BAND_2:
512           self->denominator_real = &(ia_mps_dec_mps_table->decor_table_ptr
513                                          ->den_coef_2[decorr_seed][0]);
514           break;
515         case REVERB_BAND_3:
516           self->denominator_real = &(ia_mps_dec_mps_table->decor_table_ptr
517                                          ->den_coef_3[decorr_seed][0]);
518           break;
519         default:
520           return IA_FATAL_ERROR;
521       }
522 
523       for (i = 0; i < self->num_length; i++) {
524         self->numerator_real[i] =
525             self->denominator_real[self->num_length - 1 - i];
526       }
527       self->complex = 0;
528     }
529   }
530   return error_code;
531 }
532 
ixheaacd_decorr_filt_apply(ia_mps_dec_decorr_filter_instance_struct * const self,WORD32 const length,WORD32 const * const input_real,WORD32 const * const input_imag,WORD32 * const p_output_real,WORD32 * const p_output_imag)533 static VOID ixheaacd_decorr_filt_apply(
534     ia_mps_dec_decorr_filter_instance_struct *const self, WORD32 const length,
535     WORD32 const *const input_real, WORD32 const *const input_imag,
536     WORD32 *const p_output_real, WORD32 *const p_output_imag) {
537   WORD32 temp_1, temp_2, temp3, temp4;
538   WORD32 temp5, temp6, temp7, temp8;
539   WORD32 *state_real, *state_imag;
540   WORD32 *numerator_real, *denominator_real;
541   WORD32 *output_real = p_output_real;
542   WORD32 *output_imag = p_output_imag;
543 
544   WORD32 common_part;
545   WORD32 i;
546   WORD32 j;
547 
548   common_part = self->num_length;
549   state_real = self->state_real;
550   state_imag = self->state_imag;
551   numerator_real = self->numerator_real;
552   denominator_real = self->denominator_real;
553 
554   {
555     for (i = 0; i < length; i++) {
556       {
557         temp5 = input_real[i];
558         temp6 = input_imag[i];
559 
560         temp_1 = ixheaacd_mps_mult32_shr_14(temp5, numerator_real[0]);
561         temp_2 = ixheaacd_mps_mult32_shr_14(temp6, numerator_real[0]);
562 
563         *output_real = temp_1 + state_real[0];
564         *output_imag = temp_2 + state_imag[0];
565 
566         temp7 = *output_real;
567         temp8 = *output_imag;
568 
569         output_real += MAX_HYBRID_BANDS;
570         output_imag += MAX_HYBRID_BANDS;
571         for (j = 1; j < common_part; j++) {
572           temp_1 = ixheaacd_mps_mult32x16_shr_16(temp5, numerator_real[j]);
573           temp3 = ixheaacd_mps_mult32x16_shr_16(temp6, numerator_real[j]);
574           temp_2 = ixheaacd_mps_mult32x16_shr_16(temp7, denominator_real[j]);
575           temp4 = ixheaacd_mps_mult32x16_shr_16(temp8, denominator_real[j]);
576           temp_1 -= temp_2;
577 
578           state_real[j - 1] = state_real[j] + (temp_1 << 2);
579           temp3 -= temp4;
580 
581           state_imag[j - 1] = state_imag[j] + (temp3 << 2);
582         }
583       }
584     }
585   }
586 }
587 
ixheaacd_ducker_apply_71(ia_mps_dec_ducker_interface * const face,WORD32 const time_slots,WORD32 const * input_real,WORD32 const * input_imag,WORD32 * output_real,WORD32 * output_imag,ia_mps_dec_mps_tables_struct * ia_mps_dec_mps_table_ptr,VOID * scratch)588 static VOID ixheaacd_ducker_apply_71(
589     ia_mps_dec_ducker_interface *const face, WORD32 const time_slots,
590     WORD32 const *input_real, WORD32 const *input_imag, WORD32 *output_real,
591     WORD32 *output_imag, ia_mps_dec_mps_tables_struct *ia_mps_dec_mps_table_ptr,
592     VOID *scratch) {
593   ia_mps_dec_duck_instance_struct *self =
594       (ia_mps_dec_duck_instance_struct *)&face[1];
595   WORD32 *duck_gain;
596   WORD32 gain;
597   WORD16 qgain;
598   WORD64 direct_nrg[28];
599   WORD64 reverb_nrg[28];
600   WORD16 *q_duck_gain;
601   WORD32 ts;
602   WORD32 qs;
603   WORD32 pb;
604   WORD16 qtemp1, qtemp2, qtemp3;
605   WORD32 temp_1, temp_2, temp3;
606   const WORD32 *p_input_real;
607   const WORD32 *p_input_imag;
608   const WORD32 *hybrid_2_param_28 =
609       ia_mps_dec_mps_table_ptr->m1_m2_table_ptr->hybrid_2_param_28;
610   const WORD32 *sqrt_tab = ia_mps_dec_mps_table_ptr->common_table_ptr->sqrt_tab;
611   WORD32 *smooth_direct_nrg = self->smooth_direct_nrg;
612   WORD16 *q_smooth_direct_nrg = self->q_smooth_direct_nrg;
613 
614   WORD32 *smooth_reverb_nrg = self->smooth_reverb_nrg;
615   WORD16 *q_smooth_reverb_nrg = self->q_smooth_reverb_nrg;
616 
617   WORD32 parameter_bands = self->parameter_bands;
618 
619   WORD32 *p_output_real, *p_output_imag;
620 
621   WORD32 num_bands_2 = self->hybrid_bands;
622   WORD32 v1, v2, v3, v4;
623   WORD16 one_by_5 = ONE_BY_FIVE_Q16;
624 
625   duck_gain = scratch;
626   q_duck_gain = (WORD16 *)scratch + IXHEAAC_GET_SIZE_ALIGNED_TYPE(
627                                         PARAMETER_BANDSX2, sizeof(*q_duck_gain), BYTE_ALIGN_8);
628 
629   p_input_real = input_real;
630   p_input_imag = input_imag;
631 
632   p_output_real = output_real;
633   p_output_imag = output_imag;
634 
635   for (ts = 0; ts < time_slots; ts++) {
636     memset(direct_nrg, 0, sizeof(direct_nrg));
637     memset(reverb_nrg, 0, sizeof(reverb_nrg));
638 
639     for (qs = 0; qs < 55; qs++) {
640       v1 = p_input_real[qs];
641       v2 = p_input_imag[qs];
642       v3 = p_output_real[qs];
643       v4 = p_output_imag[qs];
644 
645       pb = hybrid_2_param_28[qs];
646       direct_nrg[pb] +=
647           (WORD64)((WORD64)v1 * (WORD64)v1) + (WORD64)((WORD64)v2 * (WORD64)v2);
648       reverb_nrg[pb] +=
649           (WORD64)((WORD64)v3 * (WORD64)v3) + (WORD64)((WORD64)v4 * (WORD64)v4);
650     }
651 
652     for (; qs < num_bands_2; qs++) {
653       v1 = p_input_real[qs];
654       v2 = p_input_imag[qs];
655       v3 = p_output_real[qs];
656       v4 = p_output_imag[qs];
657 
658       direct_nrg[27] +=
659           (WORD64)((WORD64)v1 * (WORD64)v1) + (WORD64)((WORD64)v2 * (WORD64)v2);
660       reverb_nrg[27] +=
661           (WORD64)((WORD64)v3 * (WORD64)v3) + (WORD64)((WORD64)v4 * (WORD64)v4);
662     }
663 
664     for (pb = 0; pb < parameter_bands; pb++) {
665       WORD16 qtemp, qtemp_1;
666       temp_1 = ixheaacd_mps_narrow(direct_nrg[pb], &qtemp);
667 
668       temp_2 = smooth_direct_nrg[pb] << 2;
669       temp3 =
670           ixheaacd_mps_add32(temp_2, temp_1, &(q_smooth_direct_nrg[pb]), qtemp);
671       smooth_direct_nrg[pb] = ixheaacd_mps_mult32x16_shr_16(temp3, one_by_5);
672 
673       temp_1 = ixheaacd_mps_narrow(reverb_nrg[pb], &qtemp);
674       temp_2 = smooth_reverb_nrg[pb] << 2;
675 
676       temp3 =
677           ixheaacd_mps_add32(temp_2, temp_1, &(q_smooth_reverb_nrg[pb]), qtemp);
678       smooth_reverb_nrg[pb] = ixheaacd_mps_mult32x16_shr_16(temp3, one_by_5);
679 
680       qtemp1 = q_smooth_reverb_nrg[pb] - 1;
681       temp_1 = (smooth_reverb_nrg[pb] >> 2) * 3;
682       qtemp = q_smooth_direct_nrg[pb];
683       temp3 = smooth_direct_nrg[pb];
684 
685       if (ixheaacd_mps_comp(temp3, temp_1, &qtemp, qtemp1)) {
686         temp_2 = ixheaacd_mps_div_32(temp3, temp_1, &qtemp2);
687         qtemp2 = qtemp2 + qtemp - qtemp1;
688         if (temp_1 == 0) {
689           qtemp2 = qtemp;
690         }
691         temp3 = (qtemp2) > 28 ? MAX_32 : 4 << qtemp2;
692 
693         if (temp_2 > temp3) {
694           *duck_gain = (ONE_IN_Q15 - 1);
695           *q_duck_gain++ = 14;
696         } else {
697           *duck_gain = ixheaacd_mps_sqrt(temp_2, &qtemp2, sqrt_tab);
698           *q_duck_gain++ = qtemp2;
699         }
700         duck_gain++;
701         continue;
702       }
703 
704       *duck_gain = ONE_IN_Q14 - 1;
705 
706       qtemp = q_smooth_direct_nrg[pb] - 1;
707       temp_1 = (smooth_direct_nrg[pb] >> 2) * 3;
708 
709       qtemp_1 = q_smooth_reverb_nrg[pb];
710       temp_2 = smooth_reverb_nrg[pb];
711       if (ixheaacd_mps_comp(temp_2, temp_1, &(qtemp_1), qtemp)) {
712         temp3 = ixheaacd_mps_div_32(temp_1, temp_2, &qtemp3);
713         qtemp3 = qtemp3 + qtemp - qtemp_1;
714 
715         *duck_gain = ixheaacd_mps_sqrt(temp3, &qtemp3, sqrt_tab);
716         *q_duck_gain = qtemp3;
717       }
718 
719       duck_gain++;
720       q_duck_gain++;
721     }
722     duck_gain -= parameter_bands;
723     q_duck_gain -= parameter_bands;
724 
725     for (qs = 0; qs < 55; qs++) {
726       pb = hybrid_2_param_28[qs];
727       gain = duck_gain[pb];
728       if (gain == 16383) {
729         continue;
730       }
731       qgain = q_duck_gain[pb];
732       p_output_real[qs] =
733           ixheaacd_mps_mult32_shr_n(p_output_real[qs], gain, qgain);
734       p_output_imag[qs] =
735           ixheaacd_mps_mult32_shr_n(p_output_imag[qs], gain, qgain);
736     }
737 
738     gain = duck_gain[27];
739 
740     if (gain != 16383) {
741       qgain = q_duck_gain[27];
742       for (; qs < num_bands_2; qs++) {
743         p_output_real[qs] =
744             ixheaacd_mps_mult32_shr_n(p_output_real[qs], gain, qgain);
745         p_output_imag[qs] =
746             ixheaacd_mps_mult32_shr_n(p_output_imag[qs], gain, qgain);
747       }
748     }
749 
750     p_input_real += MAX_HYBRID_BANDS;
751     p_input_imag += MAX_HYBRID_BANDS;
752 
753     p_output_real += MAX_HYBRID_BANDS;
754     p_output_imag += MAX_HYBRID_BANDS;
755   }
756 }
757 
ixheaacd_ducker_apply(ia_mps_dec_ducker_interface * const face,WORD32 const time_slots,WORD32 const * input_real,WORD32 const * input_imag,WORD32 * output_real,WORD32 * output_imag,ia_mps_dec_mps_tables_struct * ia_mps_dec_mps_table_ptr,VOID * scratch)758 static VOID ixheaacd_ducker_apply(
759     ia_mps_dec_ducker_interface *const face, WORD32 const time_slots,
760     WORD32 const *input_real, WORD32 const *input_imag, WORD32 *output_real,
761     WORD32 *output_imag, ia_mps_dec_mps_tables_struct *ia_mps_dec_mps_table_ptr,
762     VOID *scratch) {
763   ia_mps_dec_duck_instance_struct *self =
764       (ia_mps_dec_duck_instance_struct *)&face[1];
765   WORD32 *duck_gain;
766   WORD32 gain;
767   WORD16 qgain;
768   WORD64 direct_nrg[28];
769   WORD64 reverb_nrg[28];
770   WORD16 *q_duck_gain;
771   WORD32 ts;
772   WORD32 qs;
773   WORD32 pb;
774   WORD16 qtemp1, qtemp2, qtemp3;
775   WORD32 temp_1, temp_2, temp3;
776   const WORD32 *p_input_real;
777   const WORD32 *p_input_imag;
778   const WORD32 *hybrid_2_param_28 =
779       ia_mps_dec_mps_table_ptr->m1_m2_table_ptr->hybrid_2_param_28;
780   const WORD32 *sqrt_tab = ia_mps_dec_mps_table_ptr->common_table_ptr->sqrt_tab;
781   WORD32 *smooth_direct_nrg = self->smooth_direct_nrg;
782   WORD16 *q_smooth_direct_nrg = self->q_smooth_direct_nrg;
783 
784   WORD32 *smooth_reverb_nrg = self->smooth_reverb_nrg;
785   WORD16 *q_smooth_reverb_nrg = self->q_smooth_reverb_nrg;
786 
787   WORD32 parameter_bands = self->parameter_bands;
788 
789   WORD32 *p_output_real, *p_output_imag;
790 
791   WORD32 num_bands_2 = self->hybrid_bands;
792   WORD32 v1, v2, v3, v4;
793   WORD16 one_by_5 = ONE_BY_FIVE_Q16;
794 
795   duck_gain = scratch;
796   q_duck_gain = (WORD16 *)scratch + IXHEAAC_GET_SIZE_ALIGNED_TYPE(
797                                         PARAMETER_BANDSX2, sizeof(*q_duck_gain), BYTE_ALIGN_8);
798 
799   p_input_real = input_real;
800   p_input_imag = input_imag;
801 
802   p_output_real = output_real;
803   p_output_imag = output_imag;
804 
805   for (ts = 0; ts < time_slots; ts++) {
806     memset(direct_nrg, 0, sizeof(direct_nrg));
807     memset(reverb_nrg, 0, sizeof(reverb_nrg));
808 
809     for (qs = 0; qs < num_bands_2; qs++) {
810       v1 = p_input_real[qs];
811       v2 = p_input_imag[qs];
812       v3 = p_output_real[qs];
813       v4 = p_output_imag[qs];
814 
815       pb = hybrid_2_param_28[qs];
816       direct_nrg[pb] +=
817           (WORD64)((WORD64)v1 * (WORD64)v1) + (WORD64)((WORD64)v2 * (WORD64)v2);
818       reverb_nrg[pb] +=
819           (WORD64)((WORD64)v3 * (WORD64)v3) + (WORD64)((WORD64)v4 * (WORD64)v4);
820     }
821 
822     for (pb = 0; pb < parameter_bands; pb++) {
823       WORD16 qtemp, qtemp_1;
824       temp_1 = ixheaacd_mps_narrow(direct_nrg[pb], &qtemp);
825       temp_2 = smooth_direct_nrg[pb] << 2;
826       temp3 =
827           ixheaacd_mps_add32(temp_2, temp_1, &(q_smooth_direct_nrg[pb]), qtemp);
828       smooth_direct_nrg[pb] = ixheaacd_mps_mult32x16_shr_16(temp3, one_by_5);
829 
830       temp_1 = ixheaacd_mps_narrow(reverb_nrg[pb], &qtemp);
831       temp_2 = smooth_reverb_nrg[pb] << 2;
832 
833       temp3 =
834           ixheaacd_mps_add32(temp_2, temp_1, &(q_smooth_reverb_nrg[pb]), qtemp);
835       smooth_reverb_nrg[pb] = ixheaacd_mps_mult32x16_shr_16(temp3, one_by_5);
836 
837       qtemp1 = q_smooth_reverb_nrg[pb] - 1;
838       temp_1 = (smooth_reverb_nrg[pb] >> 2) * 3;
839       qtemp = q_smooth_direct_nrg[pb];
840       temp3 = smooth_direct_nrg[pb];
841 
842       if (ixheaacd_mps_comp(temp3, temp_1, &qtemp, qtemp1)) {
843         temp_2 = ixheaacd_mps_div_32(temp3, temp_1, &qtemp2);
844         qtemp2 = qtemp2 + qtemp - qtemp1;
845         if (temp_1 == 0) {
846           qtemp2 = qtemp;
847         }
848         temp3 = qtemp2 > 28 ? MAX_32 : 4 << qtemp2;
849 
850         if (temp_2 > temp3) {
851           *duck_gain = 32767;
852           *q_duck_gain++ = 14;
853         } else {
854           *duck_gain = ixheaacd_mps_sqrt(temp_2, &qtemp2, sqrt_tab);
855           *q_duck_gain++ = qtemp2;
856         }
857         duck_gain++;
858         continue;
859       }
860 
861       *duck_gain = 16383;
862 
863       qtemp = q_smooth_direct_nrg[pb] - 1;
864       temp_1 = (smooth_direct_nrg[pb] >> 2) * 3;
865 
866       qtemp_1 = q_smooth_reverb_nrg[pb];
867       temp_2 = smooth_reverb_nrg[pb];
868       if (ixheaacd_mps_comp(temp_2, temp_1, &(qtemp_1), qtemp)) {
869         temp3 = ixheaacd_mps_div_32(temp_1, temp_2, &qtemp3);
870         qtemp3 = qtemp3 + qtemp - qtemp_1;
871 
872         *duck_gain = ixheaacd_mps_sqrt(temp3, &qtemp3, sqrt_tab);
873         *q_duck_gain = qtemp3;
874       }
875 
876       duck_gain++;
877       q_duck_gain++;
878     }
879 
880     duck_gain -= parameter_bands;
881     q_duck_gain -= parameter_bands;
882 
883     for (qs = 0; qs < num_bands_2; qs++) {
884       pb = hybrid_2_param_28[qs];
885       gain = duck_gain[pb];
886       if (gain == 16383) {
887         continue;
888       }
889       qgain = q_duck_gain[pb];
890       p_output_real[qs] =
891           ixheaacd_mps_mult32_shr_n(p_output_real[qs], gain, qgain);
892       p_output_imag[qs] =
893           ixheaacd_mps_mult32_shr_n(p_output_imag[qs], gain, qgain);
894     }
895 
896     p_input_real += MAX_HYBRID_BANDS;
897     p_input_imag += MAX_HYBRID_BANDS;
898 
899     p_output_real += MAX_HYBRID_BANDS;
900     p_output_imag += MAX_HYBRID_BANDS;
901   }
902 }
903 
ixheaacd_ducker_create(ia_mps_dec_ducker_interface * const face,WORD32 const hybrid_bands)904 static IA_ERRORCODE ixheaacd_ducker_create(
905     ia_mps_dec_ducker_interface *const face, WORD32 const hybrid_bands) {
906   ia_mps_dec_duck_instance_struct *self = NULL;
907   IA_ERRORCODE error_code = IA_NO_ERROR;
908   WORD32 i;
909 
910   if (face == NULL) {
911     error_code = IA_FATAL_ERROR;
912   }
913 
914   if (error_code == IA_NO_ERROR) {
915     self = (ia_mps_dec_duck_instance_struct *)&face[1];
916 
917     self->hybrid_bands = hybrid_bands;
918     self->parameter_bands = MAX_PARAMETER_BANDS;
919 
920     self->alpha = DUCK_ALPHA;
921     self->one_minus_alpha = DUCK_ONEMINUSALPHA;
922     self->gamma = DUCK_GAMMA;
923     self->abs_thr = ABS_THR_FIX;
924     self->hybrid_bands = hybrid_bands;
925     self->parameter_bands = MAX_PARAMETER_BANDS;
926 
927     self->qalpha = 15;
928     self->qgamma = 14;
929 
930     if (hybrid_bands == 71)
931       face->apply = ixheaacd_ducker_apply_71;
932     else
933       face->apply = ixheaacd_ducker_apply;
934 
935     for (i = 0; i < MAX_PARAMETER_BANDS; i++) {
936       self->q_smooth_direct_nrg[i] = 31;
937       self->q_smooth_reverb_nrg[i] = 31;
938     }
939   }
940 
941   return error_code;
942 }
943 
ixheaacd_decorr_create(ia_mps_dec_decorr_dec_handle self,WORD32 subbands,WORD32 seed,WORD32 dec_type,WORD32 decorr_config,ia_mps_dec_mps_tables_struct * ia_mps_dec_mps_table_ptr)944 IA_ERRORCODE ixheaacd_decorr_create(
945     ia_mps_dec_decorr_dec_handle self, WORD32 subbands, WORD32 seed,
946     WORD32 dec_type, WORD32 decorr_config,
947     ia_mps_dec_mps_tables_struct *ia_mps_dec_mps_table_ptr) {
948   IA_ERRORCODE error_code = IA_NO_ERROR;
949   WORD32 i, reverb_band;
950 
951   const WORD32 *rev_split_freq;
952 
953   switch (decorr_config) {
954     case DECOR_CONFIG_0:
955       rev_split_freq =
956           ia_mps_dec_mps_table_ptr->decor_table_ptr->rev_table.rev_split_freq_0;
957       break;
958     case DECOR_CONFIG_1:
959       rev_split_freq =
960           ia_mps_dec_mps_table_ptr->decor_table_ptr->rev_table.rev_split_freq_1;
961       break;
962     case DECOR_CONFIG_2:
963       rev_split_freq =
964           ia_mps_dec_mps_table_ptr->decor_table_ptr->rev_table.rev_split_freq_2;
965       break;
966     default:
967       return IA_FATAL_ERROR;
968       break;
969   }
970 
971   if (error_code == IA_NO_ERROR) {
972     self->decorr_seed = seed;
973     self->numbins = subbands;
974 
975     for (i = 0; i < self->numbins; i++) {
976       reverb_band = 0;
977       while ((reverb_band < 3) &&
978              (ixheaacd_get_qmf_sb(
979                   i, ia_mps_dec_mps_table_ptr->mdct2qmf_table_ptr) >=
980               (rev_split_freq[reverb_band] - 1)))
981         reverb_band++;
982 
983       {
984         self->no_sample_delay[i] =
985             ia_mps_dec_mps_table_ptr->decor_table_ptr->rev_table
986                 .rev_delay[reverb_band][self->decorr_seed];
987 
988         error_code = ixheaacd_decorr_filt_create(
989             self->filter[i], self->decorr_seed,
990             ixheaacd_get_qmf_sb(i,
991                                 ia_mps_dec_mps_table_ptr->mdct2qmf_table_ptr),
992             reverb_band, dec_type, ia_mps_dec_mps_table_ptr);
993       }
994     }
995 
996     if (error_code == IA_NO_ERROR) {
997       error_code = ixheaacd_ducker_create(self->ducker, self->numbins);
998     }
999   }
1000   return (error_code);
1001 }
1002 
ixheaacd_decorr_apply(ia_heaac_mps_state_struct * pstr_mps_state,WORD32 length,WORD32 * input_real,WORD32 * input_imag,WORD32 * output_real,WORD32 * output_imag,WORD32 index)1003 VOID ixheaacd_decorr_apply(ia_heaac_mps_state_struct *pstr_mps_state, WORD32 length,
1004                            WORD32 *input_real, WORD32 *input_imag,
1005                            WORD32 *output_real, WORD32 *output_imag,
1006                            WORD32 index) {
1007   WORD32 l = index - pstr_mps_state->num_direct_signals;
1008   ia_mps_dec_decorr_dec_handle decorr_ptr = pstr_mps_state->ap_decor[l];
1009   WORD32 idx, sb_sample;
1010 
1011   WORD32 *p_input_real, *p_input_re, *p_input_imag, *p_input_im;
1012   WORD32 *p_output_real, *p_output_imag, *p_output_re, *p_output_im;
1013   WORD32 *delay_buffer_real, *delay_buffer_imag;
1014   WORD32 length1;
1015   VOID *free_scratch;
1016 
1017   free_scratch = (WORD32 *)pstr_mps_state->mps_scratch_mem_v +
1018                  IXHEAAC_GET_SIZE_ALIGNED_TYPE(MAX_TIMESLOTSX2, sizeof(WORD32), BYTE_ALIGN_8);
1019 
1020   if (decorr_ptr != NULL) {
1021     p_input_real = input_real;
1022     p_input_imag = input_imag;
1023 
1024     p_output_real = output_real;
1025     p_output_imag = output_imag;
1026     for (idx = 0; idx < decorr_ptr->numbins; idx++) {
1027       p_input_re = p_input_real;
1028       p_input_im = p_input_imag;
1029 
1030       p_output_re = p_output_real;
1031       p_output_im = p_output_imag;
1032 
1033       length1 = length - decorr_ptr->no_sample_delay[idx];
1034       delay_buffer_real =
1035           &decorr_ptr->delay_buffer_real[idx][decorr_ptr->no_sample_delay[idx]];
1036       delay_buffer_imag =
1037           &decorr_ptr->delay_buffer_imag[idx][decorr_ptr->no_sample_delay[idx]];
1038       for (sb_sample = 0; sb_sample < length1; sb_sample++) {
1039         delay_buffer_real[sb_sample] = *p_input_re;
1040         *delay_buffer_imag++ = *p_input_im;
1041         p_input_re += MAX_HYBRID_BANDS;
1042         p_input_im += MAX_HYBRID_BANDS;
1043       }
1044       {
1045         ixheaacd_decorr_filt_apply(
1046             decorr_ptr->filter[idx], length, decorr_ptr->delay_buffer_real[idx],
1047             decorr_ptr->delay_buffer_imag[idx], p_output_re++, p_output_im++);
1048       }
1049 
1050       length1 = decorr_ptr->no_sample_delay[idx];
1051       delay_buffer_real = &decorr_ptr->delay_buffer_real[idx][0];
1052       delay_buffer_imag = &decorr_ptr->delay_buffer_imag[idx][0];
1053       for (sb_sample = 0; sb_sample < length1; sb_sample++) {
1054         delay_buffer_real[sb_sample] = *p_input_re;
1055         p_input_re += MAX_HYBRID_BANDS;
1056         *delay_buffer_imag++ = *p_input_im;
1057         p_input_im += MAX_HYBRID_BANDS;
1058       }
1059 
1060       p_input_real++;
1061       p_input_imag++;
1062 
1063       p_output_real++;
1064       p_output_imag++;
1065     }
1066     decorr_ptr->ducker->apply(decorr_ptr->ducker, length, input_real,
1067                               input_imag, output_real, output_imag,
1068                               &(pstr_mps_state->ia_mps_dec_mps_table), free_scratch);
1069   }
1070 }
1071