• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ixheaacd_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 "ixheaacd_constants.h"
39 #include "ixheaacd_mps_dec.h"
40 #include "ixheaacd_mps_decor.h"
41 #include "ixheaacd_mps_hybfilter.h"
42 #include "ixheaacd_error_standards.h"
43 #include "ixheaacd_basic_ops32.h"
44 #include "ixheaacd_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] = ixheaacd_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] = ixheaacd_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 + PARAMETER_BANDSX2;
627 
628   p_input_real = input_real;
629   p_input_imag = input_imag;
630 
631   p_output_real = output_real;
632   p_output_imag = output_imag;
633 
634   for (ts = 0; ts < time_slots; ts++) {
635     memset(direct_nrg, 0, sizeof(direct_nrg));
636     memset(reverb_nrg, 0, sizeof(reverb_nrg));
637 
638     for (qs = 0; qs < 55; qs++) {
639       v1 = p_input_real[qs];
640       v2 = p_input_imag[qs];
641       v3 = p_output_real[qs];
642       v4 = p_output_imag[qs];
643 
644       pb = hybrid_2_param_28[qs];
645       direct_nrg[pb] +=
646           (WORD64)((WORD64)v1 * (WORD64)v1) + (WORD64)((WORD64)v2 * (WORD64)v2);
647       reverb_nrg[pb] +=
648           (WORD64)((WORD64)v3 * (WORD64)v3) + (WORD64)((WORD64)v4 * (WORD64)v4);
649     }
650 
651     for (; qs < num_bands_2; qs++) {
652       v1 = p_input_real[qs];
653       v2 = p_input_imag[qs];
654       v3 = p_output_real[qs];
655       v4 = p_output_imag[qs];
656 
657       direct_nrg[27] +=
658           (WORD64)((WORD64)v1 * (WORD64)v1) + (WORD64)((WORD64)v2 * (WORD64)v2);
659       reverb_nrg[27] +=
660           (WORD64)((WORD64)v3 * (WORD64)v3) + (WORD64)((WORD64)v4 * (WORD64)v4);
661     }
662 
663     for (pb = 0; pb < parameter_bands; pb++) {
664       WORD16 qtemp, qtemp_1;
665       temp_1 = ixheaacd_mps_narrow(direct_nrg[pb], &qtemp);
666 
667       temp_2 = smooth_direct_nrg[pb] << 2;
668       temp3 =
669           ixheaacd_mps_add32(temp_2, temp_1, &(q_smooth_direct_nrg[pb]), qtemp);
670       smooth_direct_nrg[pb] = ixheaacd_mps_mult32x16_shr_16(temp3, one_by_5);
671 
672       temp_1 = ixheaacd_mps_narrow(reverb_nrg[pb], &qtemp);
673       temp_2 = smooth_reverb_nrg[pb] << 2;
674 
675       temp3 =
676           ixheaacd_mps_add32(temp_2, temp_1, &(q_smooth_reverb_nrg[pb]), qtemp);
677       smooth_reverb_nrg[pb] = ixheaacd_mps_mult32x16_shr_16(temp3, one_by_5);
678 
679       qtemp1 = q_smooth_reverb_nrg[pb] - 1;
680       temp_1 = (smooth_reverb_nrg[pb] >> 2) * 3;
681       qtemp = q_smooth_direct_nrg[pb];
682       temp3 = smooth_direct_nrg[pb];
683 
684       if (ixheaacd_mps_comp(temp3, temp_1, &qtemp, qtemp1)) {
685         temp_2 = ixheaacd_mps_div_32(temp3, temp_1, &qtemp2);
686         qtemp2 = qtemp2 + qtemp - qtemp1;
687         temp3 = (qtemp2) > 28 ? MAX_32 : 4 << qtemp2;
688 
689         if (temp_2 > temp3) {
690           *duck_gain = (ONE_IN_Q15 - 1);
691           *q_duck_gain++ = 14;
692         } else {
693           *duck_gain = ixheaacd_mps_sqrt(temp_2, &qtemp2, sqrt_tab);
694           *q_duck_gain++ = qtemp2;
695         }
696         duck_gain++;
697         continue;
698       }
699 
700       *duck_gain = ONE_IN_Q14 - 1;
701 
702       qtemp = q_smooth_direct_nrg[pb] - 1;
703       temp_1 = (smooth_direct_nrg[pb] >> 2) * 3;
704 
705       qtemp_1 = q_smooth_reverb_nrg[pb];
706       temp_2 = smooth_reverb_nrg[pb];
707       if (ixheaacd_mps_comp(temp_2, temp_1, &(qtemp_1), qtemp)) {
708         temp3 = ixheaacd_mps_div_32(temp_1, temp_2, &qtemp3);
709         qtemp3 = qtemp3 + qtemp - qtemp_1;
710 
711         *duck_gain = ixheaacd_mps_sqrt(temp3, &qtemp3, sqrt_tab);
712         *q_duck_gain = qtemp3;
713       }
714 
715       duck_gain++;
716       q_duck_gain++;
717     }
718     duck_gain -= parameter_bands;
719     q_duck_gain -= parameter_bands;
720 
721     for (qs = 0; qs < 55; qs++) {
722       pb = hybrid_2_param_28[qs];
723       gain = duck_gain[pb];
724       if (gain == 16383) {
725         continue;
726       }
727       qgain = q_duck_gain[pb];
728       p_output_real[qs] =
729           ixheaacd_mps_mult32_shr_n(p_output_real[qs], gain, qgain);
730       p_output_imag[qs] =
731           ixheaacd_mps_mult32_shr_n(p_output_imag[qs], gain, qgain);
732     }
733 
734     gain = duck_gain[27];
735 
736     if (gain != 16383) {
737       qgain = q_duck_gain[27];
738       for (; qs < num_bands_2; qs++) {
739         p_output_real[qs] =
740             ixheaacd_mps_mult32_shr_n(p_output_real[qs], gain, qgain);
741         p_output_imag[qs] =
742             ixheaacd_mps_mult32_shr_n(p_output_imag[qs], gain, qgain);
743       }
744     }
745 
746     p_input_real += MAX_HYBRID_BANDS;
747     p_input_imag += MAX_HYBRID_BANDS;
748 
749     p_output_real += MAX_HYBRID_BANDS;
750     p_output_imag += MAX_HYBRID_BANDS;
751   }
752 }
753 
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)754 static VOID ixheaacd_ducker_apply(
755     ia_mps_dec_ducker_interface *const face, WORD32 const time_slots,
756     WORD32 const *input_real, WORD32 const *input_imag, WORD32 *output_real,
757     WORD32 *output_imag, ia_mps_dec_mps_tables_struct *ia_mps_dec_mps_table_ptr,
758     VOID *scratch) {
759   ia_mps_dec_duck_instance_struct *self =
760       (ia_mps_dec_duck_instance_struct *)&face[1];
761   WORD32 *duck_gain;
762   WORD32 gain;
763   WORD16 qgain;
764   WORD64 direct_nrg[28];
765   WORD64 reverb_nrg[28];
766   WORD16 *q_duck_gain;
767   WORD32 ts;
768   WORD32 qs;
769   WORD32 pb;
770   WORD16 qtemp1, qtemp2, qtemp3;
771   WORD32 temp_1, temp_2, temp3;
772   const WORD32 *p_input_real;
773   const WORD32 *p_input_imag;
774   const WORD32 *hybrid_2_param_28 =
775       ia_mps_dec_mps_table_ptr->m1_m2_table_ptr->hybrid_2_param_28;
776   const WORD32 *sqrt_tab = ia_mps_dec_mps_table_ptr->common_table_ptr->sqrt_tab;
777   WORD32 *smooth_direct_nrg = self->smooth_direct_nrg;
778   WORD16 *q_smooth_direct_nrg = self->q_smooth_direct_nrg;
779 
780   WORD32 *smooth_reverb_nrg = self->smooth_reverb_nrg;
781   WORD16 *q_smooth_reverb_nrg = self->q_smooth_reverb_nrg;
782 
783   WORD32 parameter_bands = self->parameter_bands;
784 
785   WORD32 *p_output_real, *p_output_imag;
786 
787   WORD32 num_bands_2 = self->hybrid_bands;
788   WORD32 v1, v2, v3, v4;
789   WORD16 one_by_5 = ONE_BY_FIVE_Q16;
790 
791   duck_gain = scratch;
792   q_duck_gain = (WORD16 *)scratch + PARAMETER_BANDSX2;
793 
794   p_input_real = input_real;
795   p_input_imag = input_imag;
796 
797   p_output_real = output_real;
798   p_output_imag = output_imag;
799 
800   for (ts = 0; ts < time_slots; ts++) {
801     memset(direct_nrg, 0, sizeof(direct_nrg));
802     memset(reverb_nrg, 0, sizeof(reverb_nrg));
803 
804     for (qs = 0; qs < num_bands_2; qs++) {
805       v1 = p_input_real[qs];
806       v2 = p_input_imag[qs];
807       v3 = p_output_real[qs];
808       v4 = p_output_imag[qs];
809 
810       pb = hybrid_2_param_28[qs];
811       direct_nrg[pb] +=
812           (WORD64)((WORD64)v1 * (WORD64)v1) + (WORD64)((WORD64)v2 * (WORD64)v2);
813       reverb_nrg[pb] +=
814           (WORD64)((WORD64)v3 * (WORD64)v3) + (WORD64)((WORD64)v4 * (WORD64)v4);
815     }
816 
817     for (pb = 0; pb < parameter_bands; pb++) {
818       WORD16 qtemp, qtemp_1;
819       temp_1 = ixheaacd_mps_narrow(direct_nrg[pb], &qtemp);
820       temp_2 = smooth_direct_nrg[pb] << 2;
821       temp3 =
822           ixheaacd_mps_add32(temp_2, temp_1, &(q_smooth_direct_nrg[pb]), qtemp);
823       smooth_direct_nrg[pb] = ixheaacd_mps_mult32x16_shr_16(temp3, one_by_5);
824 
825       temp_1 = ixheaacd_mps_narrow(reverb_nrg[pb], &qtemp);
826       temp_2 = smooth_reverb_nrg[pb] << 2;
827 
828       temp3 =
829           ixheaacd_mps_add32(temp_2, temp_1, &(q_smooth_reverb_nrg[pb]), qtemp);
830       smooth_reverb_nrg[pb] = ixheaacd_mps_mult32x16_shr_16(temp3, one_by_5);
831 
832       qtemp1 = q_smooth_reverb_nrg[pb] - 1;
833       temp_1 = (smooth_reverb_nrg[pb] >> 2) * 3;
834       qtemp = q_smooth_direct_nrg[pb];
835       temp3 = smooth_direct_nrg[pb];
836 
837       if (ixheaacd_mps_comp(temp3, temp_1, &qtemp, qtemp1)) {
838         temp_2 = ixheaacd_mps_div_32(temp3, temp_1, &qtemp2);
839         qtemp2 = qtemp2 + qtemp - qtemp1;
840         temp3 = qtemp2 > 28 ? MAX_32 : 4 << qtemp2;
841 
842         if (temp_2 > temp3) {
843           *duck_gain = 32767;
844           *q_duck_gain++ = 14;
845         } else {
846           *duck_gain = ixheaacd_mps_sqrt(temp_2, &qtemp2, sqrt_tab);
847           *q_duck_gain++ = qtemp2;
848         }
849         duck_gain++;
850         continue;
851       }
852 
853       *duck_gain = 16383;
854 
855       qtemp = q_smooth_direct_nrg[pb] - 1;
856       temp_1 = (smooth_direct_nrg[pb] >> 2) * 3;
857 
858       qtemp_1 = q_smooth_reverb_nrg[pb];
859       temp_2 = smooth_reverb_nrg[pb];
860       if (ixheaacd_mps_comp(temp_2, temp_1, &(qtemp_1), qtemp)) {
861         temp3 = ixheaacd_mps_div_32(temp_1, temp_2, &qtemp3);
862         qtemp3 = qtemp3 + qtemp - qtemp_1;
863 
864         *duck_gain = ixheaacd_mps_sqrt(temp3, &qtemp3, sqrt_tab);
865         *q_duck_gain = qtemp3;
866       }
867 
868       duck_gain++;
869       q_duck_gain++;
870     }
871 
872     duck_gain -= parameter_bands;
873     q_duck_gain -= parameter_bands;
874 
875     for (qs = 0; qs < num_bands_2; qs++) {
876       pb = hybrid_2_param_28[qs];
877       gain = duck_gain[pb];
878       if (gain == 16383) {
879         continue;
880       }
881       qgain = q_duck_gain[pb];
882       p_output_real[qs] =
883           ixheaacd_mps_mult32_shr_n(p_output_real[qs], gain, qgain);
884       p_output_imag[qs] =
885           ixheaacd_mps_mult32_shr_n(p_output_imag[qs], gain, qgain);
886     }
887 
888     p_input_real += MAX_HYBRID_BANDS;
889     p_input_imag += MAX_HYBRID_BANDS;
890 
891     p_output_real += MAX_HYBRID_BANDS;
892     p_output_imag += MAX_HYBRID_BANDS;
893   }
894 }
895 
ixheaacd_ducker_create(ia_mps_dec_ducker_interface * const face,WORD32 const hybrid_bands)896 static IA_ERRORCODE ixheaacd_ducker_create(
897     ia_mps_dec_ducker_interface *const face, WORD32 const hybrid_bands) {
898   ia_mps_dec_duck_instance_struct *self = NULL;
899   IA_ERRORCODE error_code = IA_NO_ERROR;
900   WORD32 i;
901 
902   if (face == NULL) {
903     error_code = IA_FATAL_ERROR;
904   }
905 
906   if (error_code == IA_NO_ERROR) {
907     self = (ia_mps_dec_duck_instance_struct *)&face[1];
908 
909     self->hybrid_bands = hybrid_bands;
910     self->parameter_bands = MAX_PARAMETER_BANDS;
911 
912     self->alpha = DUCK_ALPHA;
913     self->one_minus_alpha = DUCK_ONEMINUSALPHA;
914     self->gamma = DUCK_GAMMA;
915     self->abs_thr = ABS_THR_FIX;
916     self->hybrid_bands = hybrid_bands;
917     self->parameter_bands = MAX_PARAMETER_BANDS;
918 
919     self->qalpha = 15;
920     self->qgamma = 14;
921 
922     if (hybrid_bands == 71)
923       face->apply = ixheaacd_ducker_apply_71;
924     else
925       face->apply = ixheaacd_ducker_apply;
926 
927     for (i = 0; i < MAX_PARAMETER_BANDS; i++) {
928       self->q_smooth_direct_nrg[i] = 31;
929       self->q_smooth_reverb_nrg[i] = 31;
930     }
931   }
932 
933   return error_code;
934 }
935 
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)936 IA_ERRORCODE ixheaacd_decorr_create(
937     ia_mps_dec_decorr_dec_handle self, WORD32 subbands, WORD32 seed,
938     WORD32 dec_type, WORD32 decorr_config,
939     ia_mps_dec_mps_tables_struct *ia_mps_dec_mps_table_ptr) {
940   IA_ERRORCODE error_code = IA_NO_ERROR;
941   WORD32 i, reverb_band;
942 
943   const WORD32 *rev_split_freq;
944 
945   switch (decorr_config) {
946     case DECOR_CONFIG_0:
947       rev_split_freq =
948           ia_mps_dec_mps_table_ptr->decor_table_ptr->rev_table.rev_split_freq_0;
949       break;
950     case DECOR_CONFIG_1:
951       rev_split_freq =
952           ia_mps_dec_mps_table_ptr->decor_table_ptr->rev_table.rev_split_freq_1;
953       break;
954     case DECOR_CONFIG_2:
955       rev_split_freq =
956           ia_mps_dec_mps_table_ptr->decor_table_ptr->rev_table.rev_split_freq_2;
957       break;
958     default:
959       return IA_FATAL_ERROR;
960       break;
961   }
962 
963   if (error_code == IA_NO_ERROR) {
964     self->decorr_seed = seed;
965     self->numbins = subbands;
966 
967     for (i = 0; i < self->numbins; i++) {
968       reverb_band = 0;
969       while ((reverb_band < 3) &&
970              (ixheaacd_get_qmf_sb(
971                   i, ia_mps_dec_mps_table_ptr->mdct2qmf_table_ptr) >=
972               (rev_split_freq[reverb_band] - 1)))
973         reverb_band++;
974 
975       {
976         self->no_sample_delay[i] =
977             ia_mps_dec_mps_table_ptr->decor_table_ptr->rev_table
978                 .rev_delay[reverb_band][self->decorr_seed];
979 
980         error_code = ixheaacd_decorr_filt_create(
981             self->filter[i], self->decorr_seed,
982             ixheaacd_get_qmf_sb(i,
983                                 ia_mps_dec_mps_table_ptr->mdct2qmf_table_ptr),
984             reverb_band, dec_type, ia_mps_dec_mps_table_ptr);
985       }
986     }
987 
988     if (error_code == IA_NO_ERROR) {
989       error_code = ixheaacd_ducker_create(self->ducker, self->numbins);
990     }
991   }
992   return (error_code);
993 }
994 
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)995 VOID ixheaacd_decorr_apply(ia_heaac_mps_state_struct *pstr_mps_state, WORD32 length,
996                            WORD32 *input_real, WORD32 *input_imag,
997                            WORD32 *output_real, WORD32 *output_imag,
998                            WORD32 index) {
999   WORD32 l = index - pstr_mps_state->num_direct_signals;
1000   ia_mps_dec_decorr_dec_handle decorr_ptr = pstr_mps_state->ap_decor[l];
1001   WORD32 idx, sb_sample;
1002 
1003   WORD32 *p_input_real, *p_input_re, *p_input_imag, *p_input_im;
1004   WORD32 *p_output_real, *p_output_imag, *p_output_re, *p_output_im;
1005   WORD32 *delay_buffer_real, *delay_buffer_imag;
1006   WORD32 length1;
1007   VOID *free_scratch;
1008 
1009   free_scratch = (WORD32 *)pstr_mps_state->mps_scratch_mem_v + MAX_TIMESLOTSX2;
1010 
1011   if (decorr_ptr != NULL) {
1012     p_input_real = input_real;
1013     p_input_imag = input_imag;
1014 
1015     p_output_real = output_real;
1016     p_output_imag = output_imag;
1017     for (idx = 0; idx < decorr_ptr->numbins; idx++) {
1018       p_input_re = p_input_real;
1019       p_input_im = p_input_imag;
1020 
1021       p_output_re = p_output_real;
1022       p_output_im = p_output_imag;
1023 
1024       length1 = length - decorr_ptr->no_sample_delay[idx];
1025       delay_buffer_real =
1026           &decorr_ptr->delay_buffer_real[idx][decorr_ptr->no_sample_delay[idx]];
1027       delay_buffer_imag =
1028           &decorr_ptr->delay_buffer_imag[idx][decorr_ptr->no_sample_delay[idx]];
1029       for (sb_sample = 0; sb_sample < length1; sb_sample++) {
1030         delay_buffer_real[sb_sample] = *p_input_re;
1031         *delay_buffer_imag++ = *p_input_im;
1032         p_input_re += MAX_HYBRID_BANDS;
1033         p_input_im += MAX_HYBRID_BANDS;
1034       }
1035       {
1036         ixheaacd_decorr_filt_apply(
1037             decorr_ptr->filter[idx], length, decorr_ptr->delay_buffer_real[idx],
1038             decorr_ptr->delay_buffer_imag[idx], p_output_re++, p_output_im++);
1039       }
1040 
1041       length1 = decorr_ptr->no_sample_delay[idx];
1042       delay_buffer_real = &decorr_ptr->delay_buffer_real[idx][0];
1043       delay_buffer_imag = &decorr_ptr->delay_buffer_imag[idx][0];
1044       for (sb_sample = 0; sb_sample < length1; sb_sample++) {
1045         delay_buffer_real[sb_sample] = *p_input_re;
1046         p_input_re += MAX_HYBRID_BANDS;
1047         *delay_buffer_imag++ = *p_input_im;
1048         p_input_im += MAX_HYBRID_BANDS;
1049       }
1050 
1051       p_input_real++;
1052       p_input_imag++;
1053 
1054       p_output_real++;
1055       p_output_imag++;
1056     }
1057     decorr_ptr->ducker->apply(decorr_ptr->ducker, length, input_real,
1058                               input_imag, output_real, output_imag,
1059                               &(pstr_mps_state->ia_mps_dec_mps_table), free_scratch);
1060   }
1061 }
1062