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