• 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 <stdio.h>
21 #include <stdlib.h>
22 #include <math.h>
23 #include <string.h>
24 #include <assert.h>
25 
26 #include "ixheaacd_type_def.h"
27 #include "ixheaacd_bitbuffer.h"
28 #include "ixheaacd_config.h"
29 
30 #include "ixheaacd_mps_polyphase.h"
31 #include "ixheaacd_mps_dec.h"
32 #include "ixheaacd_mps_interface.h"
33 
34 #include "ixheaacd_mps_polyphase.h"
35 
36 #include "ixheaacd_mps_decor.h"
37 #include "ixheaacd_mps_hybfilter.h"
38 #include "ixheaacd_error_standards.h"
39 #include "ixheaacd_constants.h"
40 
41 static const WORD32 ixheaacd_decorr_delay[] = {11, 10, 5, 2};
42 
43 static const WORD32 ixheaacd_qmf_split_freq_0[] = {3, 15, 24, 65};
44 static const WORD32 ixheaacd_qmf_split_freq_1[] = {3, 50, 65, 65};
45 static const WORD32 ixheaacd_qmf_split_freq_2[] = {0, 15, 65, 65};
46 
47 static const FLOAT32
48     ixheaacd_lattice_coeff_0_filt_den_coeff[DECORR_FILT_0_ORD + 1] = {
49         1.000000f, -0.314818f, -0.256828f, -0.173641f, -0.115077f, 0.000599f,
50         0.033343f, 0.122672f,  -0.356362f, 0.128058f,  0.089800f};
51 static const FLOAT32
52     ixheaacd_lattice_coeff_0_filt_num_coeff[DECORR_FILT_0_ORD + 1] = {
53         0.089800f,  0.128058f,  -0.356362f, 0.122672f,  0.033343f, 0.000599f,
54         -0.115077f, -0.173641f, -0.256828f, -0.314818f, 1.000000f};
55 
56 static const FLOAT32
57     ixheaacd_lattice_coeff_1_filt_den_coeff[DECORR_FILT_1_ORD + 1] = {
58         1.000000f, -0.287137f, -0.088940f, 0.123204f, -0.126111f,
59         0.064218f, 0.045768f,  -0.016264f, -0.122100f};
60 static const FLOAT32
61     ixheaacd_lattice_coeff_1_filt_num_coeff[DECORR_FILT_1_ORD + 1] = {
62         -0.122100f, -0.016264f, 0.045768f,  0.064218f, -0.126111f,
63         0.123204f,  -0.088940f, -0.287137f, 1.000000f};
64 
65 static const FLOAT32
66     ixheaacd_lattice_coeff_2_filt_den_coeff[DECORR_FILT_2_ORD + 1] = {
67         1.000000f, 0.129403f, -0.032633f, 0.035700f};
68 static const FLOAT32
69     ixheaacd_lattice_coeff_2_filt_num_coeff[DECORR_FILT_2_ORD + 1] = {
70         0.035700f, -0.032633f, 0.129403f, 1.000000f};
71 
72 static const FLOAT32
73     ixheaacd_lattice_coeff_3_filt_den_coeff[DECORR_FILT_3_ORD + 1] = {
74         1.000000f, 0.034742f, -0.013000f};
75 static const FLOAT32
76     ixheaacd_lattice_coeff_3_filt_num_coeff[DECORR_FILT_3_ORD + 1] = {
77         -0.013000f, 0.034742f, 1.000000f};
78 
79 extern const WORD32
80     ixheaacd_hybrid_band_71_to_processing_band_28_map[MAX_HYBRID_BANDS_MPS];
81 
82 static const WORD32 ixheaacd_hybrid_to_qmf_map[MAX_HYBRID_BANDS_MPS] = {
83     0,  0,  0,  0,  0,  0,  1,  1,  2,  2,  3,  4,  5,  6,  7,  8,  9,  10,
84     11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
85     29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
86     47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
87 
ixheaacd_mps_decor_filt_init(ia_mps_decor_filt_struct * self,WORD32 reverb_band)88 static void ixheaacd_mps_decor_filt_init(ia_mps_decor_filt_struct *self,
89                                          WORD32 reverb_band) {
90   switch (reverb_band) {
91     case 0:
92       self->num_len = self->den_len = DECORR_FILT_0_ORD + 1;
93       self->num = ixheaacd_lattice_coeff_0_filt_num_coeff;
94       self->den = ixheaacd_lattice_coeff_0_filt_den_coeff;
95 
96       break;
97     case 1:
98       self->num_len = self->den_len = DECORR_FILT_1_ORD + 1;
99       self->num = ixheaacd_lattice_coeff_1_filt_num_coeff;
100       self->den = ixheaacd_lattice_coeff_1_filt_den_coeff;
101 
102       break;
103     case 2:
104       self->num_len = self->den_len = DECORR_FILT_2_ORD + 1;
105       self->num = ixheaacd_lattice_coeff_2_filt_num_coeff;
106       self->den = ixheaacd_lattice_coeff_2_filt_den_coeff;
107       break;
108     case 3:
109       self->num_len = self->den_len = DECORR_FILT_3_ORD + 1;
110       self->num = ixheaacd_lattice_coeff_3_filt_num_coeff;
111       self->den = ixheaacd_lattice_coeff_3_filt_den_coeff;
112       break;
113   }
114 
115   self->state_len = self->num_len;
116   memset(self->state, 0,
117          sizeof(ia_cmplx_flt_struct) * (MAX_DECORR_FIL_ORDER + 1));
118 
119   return;
120 }
121 
ixheaacd_mps_allpass_apply(ia_mps_decor_filt_struct * self,ia_cmplx_flt_struct * input,WORD32 len,ia_cmplx_flt_struct * output)122 static VOID ixheaacd_mps_allpass_apply(ia_mps_decor_filt_struct *self,
123                                        ia_cmplx_flt_struct *input, WORD32 len,
124                                        ia_cmplx_flt_struct *output) {
125   WORD32 i, j;
126 
127   for (i = 0; i < len; i++) {
128     output[i].re = self->state[0].re + input[i].re * self->num[0];
129     output[i].im = self->state[0].im + input[i].im * self->num[0];
130 
131     for (j = 1; j < self->num_len; j++) {
132       self->state[j - 1].re = self->state[j].re + self->num[j] * input[i].re -
133                               self->den[j] * output[i].re;
134       self->state[j - 1].im = self->state[j].im + self->num[j] * input[i].im -
135                               self->den[j] * output[i].im;
136     }
137   }
138 }
139 
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)140 static VOID ixheaacd_mps_decor_energy_adjustment(
141     ixheaacd_mps_decor_energy_adjust_filt_struct *handle,
142     ia_cmplx_flt_struct in[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS],
143     ia_cmplx_flt_struct out[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS],
144     WORD32 time_slots) {
145   ixheaacd_mps_decor_energy_adjust_filt_struct *self =
146       (ixheaacd_mps_decor_energy_adjust_filt_struct *)handle;
147   FLOAT32 in_energy[MAX_PARAMETER_BANDS] = {0};
148   FLOAT32 out_energy[MAX_PARAMETER_BANDS] = {0};
149   FLOAT32 gain[MAX_PARAMETER_BANDS];
150   WORD32 i, j, k;
151 
152   for (i = 0; i < time_slots; i++) {
153     memset(in_energy, 0, sizeof(FLOAT32) * MAX_PARAMETER_BANDS);
154     memset(out_energy, 0, sizeof(FLOAT32) * MAX_PARAMETER_BANDS);
155 
156     for (j = 0; j < self->num_bins; j++) {
157       k = ixheaacd_hybrid_band_71_to_processing_band_28_map[j];
158 
159       in_energy[k] += in[i][j].re * in[i][j].re + in[i][j].im * in[i][j].im;
160       out_energy[k] +=
161           out[i][j].re * out[i][j].re + out[i][j].im * out[i][j].im;
162     }
163 
164     for (k = 0; k < MAX_PARAMETER_BANDS; k++) {
165       self->smooth_in_energy[k] = self->smooth_in_energy[k] * DECOR_ALPHA +
166                                   in_energy[k] * ONE_MINUS_DECOR_ALPHA;
167       self->smooth_out_energy[k] = self->smooth_out_energy[k] * DECOR_ALPHA +
168                                    out_energy[k] * ONE_MINUS_DECOR_ALPHA;
169 
170       gain[k] = 1.0f;
171 
172       if (self->smooth_out_energy[k] >
173           self->smooth_in_energy[k] * DECOR_GAMMA) {
174         gain[k] = (FLOAT32)sqrt(self->smooth_in_energy[k] * DECOR_GAMMA /
175                                 (self->smooth_out_energy[k] + ABS_THR));
176       }
177 
178       if (self->smooth_in_energy[k] >
179           self->smooth_out_energy[k] * DECOR_GAMMA) {
180         gain[k] =
181             min(2.0f, (FLOAT32)sqrt(self->smooth_in_energy[k] /
182                                     (DECOR_GAMMA * self->smooth_out_energy[k] +
183                                      ABS_THR)));
184       }
185     }
186 
187     for (j = 0; j < self->num_bins; j++) {
188       k = ixheaacd_hybrid_band_71_to_processing_band_28_map[j];
189 
190       out[i][j].re *= gain[k];
191       out[i][j].im *= gain[k];
192     }
193   }
194 }
195 
ixheaacd_mps_decor_init(ia_mps_decor_struct_handle self,WORD32 subbands,WORD32 decor_config)196 IA_ERRORCODE ixheaacd_mps_decor_init(ia_mps_decor_struct_handle self,
197                                      WORD32 subbands, WORD32 decor_config) {
198   WORD32 i, reverb_band;
199   const WORD32 *splitfreq;
200 
201   switch (decor_config) {
202     case 0:
203       splitfreq = ixheaacd_qmf_split_freq_0;
204       break;
205     case 1:
206       splitfreq = ixheaacd_qmf_split_freq_1;
207       break;
208     case 2:
209       splitfreq = ixheaacd_qmf_split_freq_2;
210       break;
211     default:
212       return IA_FATAL_ERROR;
213   }
214 
215   self->num_bins = subbands;
216 
217   for (i = 0; i < self->num_bins; i++) {
218     reverb_band = 0;
219     while ((reverb_band < 3) &&
220            (ixheaacd_hybrid_to_qmf_map[i] >= (splitfreq[reverb_band] - 1)))
221       reverb_band++;
222 
223     self->delay_sample_count[i] = ixheaacd_decorr_delay[reverb_band];
224     ixheaacd_mps_decor_filt_init(&self->filter[i], reverb_band);
225   }
226 
227   self->decor_nrg_smooth.num_bins = self->num_bins;
228 
229   return IA_NO_ERROR;
230 }
231 
ixheaacd_mps_decor_apply(ia_mps_decor_struct_handle 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)232 VOID ixheaacd_mps_decor_apply(
233     ia_mps_decor_struct_handle self,
234     ia_cmplx_flt_struct in[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS],
235     ia_cmplx_flt_struct out[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS],
236     WORD32 length) {
237   WORD32 idx, sb_sample;
238 
239   ia_cmplx_flt_struct scratch[MAX_TIME_SLOTS];
240 
241   for (idx = 0; idx < self->num_bins; idx++) {
242     for (sb_sample = 0; sb_sample < length; sb_sample++) {
243       self->decor_delay_buffer[idx][self->delay_sample_count[idx] + sb_sample]
244           .re = in[sb_sample][idx].re;
245       self->decor_delay_buffer[idx][self->delay_sample_count[idx] + sb_sample]
246           .im = in[sb_sample][idx].im;
247     }
248     ixheaacd_mps_allpass_apply(&self->filter[idx],
249                                self->decor_delay_buffer[idx], length, scratch);
250 
251     for (sb_sample = 0; sb_sample < length; sb_sample++) {
252       out[sb_sample][idx].re = scratch[sb_sample].re;
253       out[sb_sample][idx].im = scratch[sb_sample].im;
254     }
255 
256     for (sb_sample = 0; sb_sample < self->delay_sample_count[idx];
257          sb_sample++) {
258       self->decor_delay_buffer[idx][sb_sample].re =
259           self->decor_delay_buffer[idx][length + sb_sample].re;
260       self->decor_delay_buffer[idx][sb_sample].im =
261           self->decor_delay_buffer[idx][length + sb_sample].im;
262     }
263   }
264 
265   ixheaacd_mps_decor_energy_adjustment(&self->decor_nrg_smooth, in, out,
266                                        length);
267 }
268