/src/libxaac/encoder/ixheaace_mps_dmx_tdom_enh.c
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * * |
3 | | * Copyright (C) 2023 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 | | |
21 | | #include <math.h> |
22 | | #include "ixheaac_type_def.h" |
23 | | #include "ixheaac_constants.h" |
24 | | #include "ixheaac_error_standards.h" |
25 | | #include "ixheaace_error_codes.h" |
26 | | #include "ixheaace_mps_common_fix.h" |
27 | | |
28 | | #include "ixheaace_mps_common_define.h" |
29 | | #include "ixheaace_mps_defines.h" |
30 | | #include "ixheaac_constants.h" |
31 | | #include "ixheaace_mps_dmx_tdom_enh.h" |
32 | | #include "ixheaac_basic_ops32.h" |
33 | | #include "ixheaac_basic_ops40.h" |
34 | | #include "ixheaac_basic_ops.h" |
35 | | |
36 | | static VOID ixheaace_mps_212_calculate_ratio(const FLOAT32 sqrt_lin_cld_m, |
37 | | const FLOAT32 lin_cld_m, const FLOAT32 icc_m, |
38 | 89.6k | FLOAT32 g_m[2]) { |
39 | 89.6k | if (icc_m >= 0.f) { |
40 | 88.3k | g_m[0] = g_m[1] = 1.0f; |
41 | 88.3k | } else { |
42 | 1.27k | FLOAT32 max_gain_factor = 2.0f; |
43 | 1.27k | FLOAT32 numerator, denominator; |
44 | 1.27k | FLOAT32 q = 0.0f; |
45 | 1.27k | numerator = (lin_cld_m + 0.5f) + (icc_m * sqrt_lin_cld_m); |
46 | 1.27k | denominator = (lin_cld_m + 0.5f) - (icc_m * sqrt_lin_cld_m); |
47 | | |
48 | 1.27k | if ((numerator > (0.f)) && (denominator > (0.f))) { |
49 | 1.27k | FLOAT32 intermediate; |
50 | 1.27k | intermediate = numerator / denominator; |
51 | 1.27k | intermediate = (FLOAT32)sqrt(intermediate); |
52 | 1.27k | intermediate = (FLOAT32)sqrt(intermediate); |
53 | 1.27k | q = (intermediate >= max_gain_factor) ? max_gain_factor : intermediate; |
54 | 1.27k | } |
55 | | |
56 | 1.27k | g_m[0] = max_gain_factor - q; |
57 | 1.27k | g_m[1] = q; |
58 | 1.27k | } |
59 | 89.6k | } |
60 | | |
61 | | static VOID ixheaace_mps_212_calculate_dmx_gains(const FLOAT32 lin_cld_m, |
62 | | const FLOAT32 lin_cld_2_m, const FLOAT32 icc_m, |
63 | 89.6k | const FLOAT32 g_m[2], FLOAT32 h_1_m[2]) { |
64 | 89.6k | const FLOAT32 max_gain_factor = 2.0f; |
65 | 89.6k | FLOAT32 energy_right, energy_left, cross_energy, inverse_weight_num, inverse_weight_den, |
66 | 89.6k | inverse_weight, inverse_weight_limited; |
67 | 89.6k | energy_right = lin_cld_2_m - 0.5f; |
68 | 89.6k | energy_right = (FLOAT32)sqrt(energy_right); |
69 | 89.6k | energy_left = lin_cld_m * energy_right; |
70 | 89.6k | cross_energy = (FLOAT32)sqrt(energy_left * energy_right); |
71 | 89.6k | inverse_weight_num = energy_right + energy_left; |
72 | 89.6k | inverse_weight_den = ((g_m[0] * g_m[0]) * energy_left) + ((g_m[1] * g_m[1]) * energy_right); |
73 | | |
74 | 89.6k | inverse_weight_den = ((((g_m[0] * g_m[1]) * cross_energy) * icc_m) * 2) + inverse_weight_den; |
75 | | |
76 | 89.6k | if (inverse_weight_den > (0.f)) { |
77 | 88.6k | inverse_weight = inverse_weight_num / inverse_weight_den; |
78 | | |
79 | 88.6k | inverse_weight = (FLOAT32)sqrt(inverse_weight); |
80 | | |
81 | 88.6k | inverse_weight_limited = |
82 | 88.6k | (inverse_weight >= max_gain_factor) ? max_gain_factor : inverse_weight; |
83 | 88.6k | } else { |
84 | 1.03k | inverse_weight_limited = max_gain_factor; |
85 | 1.03k | } |
86 | | |
87 | 89.6k | h_1_m[1] = g_m[1] * inverse_weight_limited; |
88 | 89.6k | h_1_m[0] = g_m[0] * inverse_weight_limited; |
89 | 89.6k | } |
90 | | |
91 | | IA_ERRORCODE ixheaace_mps_212_init_enhanced_time_domain_dmx( |
92 | | ixheaace_mps_pstr_enhanced_time_domain_dmx pstr_enhanced_time_domain_dmx, |
93 | | const FLOAT32 *const ptr_input_gain_m_flt, const FLOAT32 output_gain_m_flt, |
94 | 1.42k | const WORD32 frame_length) { |
95 | 1.42k | IA_ERRORCODE error = IA_NO_ERROR; |
96 | 1.42k | WORD32 sample_idx; |
97 | 1.42k | FLOAT32 delta; |
98 | 1.42k | if (frame_length > pstr_enhanced_time_domain_dmx->max_frame_length) { |
99 | 0 | return IA_EXHEAACE_INIT_FATAL_MPS_INIT_FAILED; |
100 | 0 | } |
101 | 1.42k | pstr_enhanced_time_domain_dmx->frame_length = frame_length; |
102 | 1.42k | delta = (FLOAT32)(PI_FLT / (2.0 * pstr_enhanced_time_domain_dmx->frame_length)); |
103 | 3.00M | for (sample_idx = 0; sample_idx < pstr_enhanced_time_domain_dmx->frame_length + 1; |
104 | 2.99M | sample_idx++) { |
105 | 2.99M | FLOAT32 sin_val = (FLOAT32)sin(sample_idx * delta); |
106 | 2.99M | pstr_enhanced_time_domain_dmx->sinus_window[sample_idx] = ALPHA * sin_val * sin_val; |
107 | 2.99M | } |
108 | | |
109 | 1.42k | pstr_enhanced_time_domain_dmx->prev_left_energy = |
110 | 1.42k | pstr_enhanced_time_domain_dmx->prev_right_energy = |
111 | 1.42k | pstr_enhanced_time_domain_dmx->prev_x_energy = 0.0f; |
112 | 1.42k | pstr_enhanced_time_domain_dmx->cld_weight = |
113 | 1.42k | (ptr_input_gain_m_flt[LEFT_CH]) / (ptr_input_gain_m_flt[RIGHT_CH]); |
114 | 1.42k | pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH] = |
115 | 1.42k | (ptr_input_gain_m_flt[LEFT_CH] * output_gain_m_flt); |
116 | 1.42k | pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH] = |
117 | 1.42k | (ptr_input_gain_m_flt[RIGHT_CH] * output_gain_m_flt); |
118 | 1.42k | pstr_enhanced_time_domain_dmx->prev_gain[LEFT_CH] = |
119 | 1.42k | pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH]; |
120 | 1.42k | pstr_enhanced_time_domain_dmx->prev_gain[RIGHT_CH] = |
121 | 1.42k | pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH]; |
122 | 1.42k | pstr_enhanced_time_domain_dmx->prev_h1[LEFT_CH] = |
123 | 1.42k | pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH]; |
124 | 1.42k | pstr_enhanced_time_domain_dmx->prev_h1[RIGHT_CH] = |
125 | 1.42k | pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH]; |
126 | 1.42k | return error; |
127 | 1.42k | } |
128 | | |
129 | | IA_ERRORCODE ixheaace_mps_212_apply_enhanced_time_domain_dmx( |
130 | | ixheaace_mps_pstr_enhanced_time_domain_dmx pstr_enhanced_time_domain_dmx, |
131 | | FLOAT32 input_time[2][MPS_MAX_FRAME_LENGTH + MAX_DELAY_SURROUND_ANALYSIS], |
132 | 89.6k | FLOAT32 *const ptr_output_time_dmx, const WORD32 input_delay) { |
133 | 89.6k | IA_ERRORCODE error = IA_NO_ERROR; |
134 | | |
135 | 89.6k | WORD32 sample_idx; |
136 | 89.6k | FLOAT32 lin_bb_cld, lin_cld, corr, sqrt_lin_cld, g[2], h1[2], gain_left, gain_right; |
137 | 89.6k | FLOAT32 prev_energy_left, prev_energy_right, prev_energy, energy_left, energy_right, energy_out; |
138 | 89.6k | WORD32 granule_length = MIN(128, pstr_enhanced_time_domain_dmx->frame_length); |
139 | | |
140 | 89.6k | sample_idx = 0; |
141 | 89.6k | prev_energy_left = prev_energy_right = prev_energy = .5f; |
142 | | |
143 | 1.53M | do { |
144 | 1.53M | WORD32 offset = sample_idx; |
145 | 1.53M | FLOAT32 partial_left, partial_right, partial_out; |
146 | 1.53M | partial_left = partial_right = partial_out = 0.0; |
147 | | |
148 | 1.53M | WORD32 value = MIN(offset + granule_length, pstr_enhanced_time_domain_dmx->frame_length); |
149 | 196M | for (sample_idx = offset; sample_idx < value; sample_idx++) { |
150 | 194M | FLOAT32 input_left = input_time[LEFT_CH][sample_idx]; |
151 | 194M | FLOAT32 input_right = input_time[RIGHT_CH][sample_idx]; |
152 | | |
153 | 194M | partial_left += (FLOAT32)pow(input_left, 2); |
154 | 194M | partial_right += (FLOAT32)pow(input_right, 2); |
155 | 194M | partial_out += input_left * input_right; |
156 | 194M | } |
157 | | |
158 | 1.53M | prev_energy_left = prev_energy_left + partial_left; |
159 | 1.53M | prev_energy_right = prev_energy_right + partial_right; |
160 | 1.53M | prev_energy = prev_energy + partial_out; |
161 | | |
162 | 1.53M | } while (sample_idx < pstr_enhanced_time_domain_dmx->frame_length); |
163 | | |
164 | 89.6k | energy_left = pstr_enhanced_time_domain_dmx->prev_left_energy + prev_energy_left; |
165 | 89.6k | energy_right = pstr_enhanced_time_domain_dmx->prev_right_energy + prev_energy_right; |
166 | 89.6k | energy_out = pstr_enhanced_time_domain_dmx->prev_x_energy + prev_energy; |
167 | | |
168 | 89.6k | lin_bb_cld = pstr_enhanced_time_domain_dmx->cld_weight * (energy_left / energy_right); |
169 | 89.6k | corr = energy_out * (1 / (FLOAT32)sqrt(energy_left * energy_right)); |
170 | | |
171 | 89.6k | pstr_enhanced_time_domain_dmx->prev_left_energy = prev_energy_left; |
172 | 89.6k | pstr_enhanced_time_domain_dmx->prev_right_energy = prev_energy_right; |
173 | 89.6k | pstr_enhanced_time_domain_dmx->prev_x_energy = prev_energy; |
174 | | |
175 | 89.6k | lin_cld = (FLOAT32)sqrt(lin_bb_cld); |
176 | 89.6k | sqrt_lin_cld = (FLOAT32)sqrt(lin_cld); |
177 | | |
178 | 89.6k | ixheaace_mps_212_calculate_ratio(sqrt_lin_cld, lin_cld, corr, g); |
179 | | |
180 | 89.6k | ixheaace_mps_212_calculate_dmx_gains(lin_cld, lin_bb_cld, corr, g, h1); |
181 | | |
182 | 89.6k | h1[LEFT_CH] = h1[LEFT_CH] * pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH]; |
183 | 89.6k | h1[RIGHT_CH] = h1[RIGHT_CH] * pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH]; |
184 | | |
185 | 89.6k | gain_left = pstr_enhanced_time_domain_dmx->prev_gain[LEFT_CH]; |
186 | 89.6k | gain_right = pstr_enhanced_time_domain_dmx->prev_gain[RIGHT_CH]; |
187 | | |
188 | 194M | for (sample_idx = 0; sample_idx < pstr_enhanced_time_domain_dmx->frame_length; sample_idx++) { |
189 | 194M | WORD32 frame_length = pstr_enhanced_time_domain_dmx->frame_length; |
190 | 194M | FLOAT32 intermediate_gain_left, intermediate_gain_right, temp; |
191 | | |
192 | 194M | intermediate_gain_left = |
193 | 194M | ((pstr_enhanced_time_domain_dmx->sinus_window[sample_idx] * h1[LEFT_CH]) + |
194 | 194M | (pstr_enhanced_time_domain_dmx->sinus_window[frame_length - sample_idx] * |
195 | 194M | pstr_enhanced_time_domain_dmx->prev_h1[LEFT_CH])); |
196 | | |
197 | 194M | intermediate_gain_right = |
198 | 194M | ((pstr_enhanced_time_domain_dmx->sinus_window[sample_idx] * h1[RIGHT_CH]) + |
199 | 194M | (pstr_enhanced_time_domain_dmx->sinus_window[frame_length - sample_idx] * |
200 | 194M | pstr_enhanced_time_domain_dmx->prev_h1[RIGHT_CH])); |
201 | | |
202 | 194M | gain_left = intermediate_gain_left + ((1.f - ALPHA) * gain_left); |
203 | 194M | gain_right = intermediate_gain_right + ((1.f - ALPHA) * gain_right); |
204 | 194M | temp = (gain_left * (FLOAT32)input_time[LEFT_CH][sample_idx + input_delay]) + |
205 | 194M | (gain_right * (FLOAT32)input_time[RIGHT_CH][sample_idx + input_delay]); |
206 | 194M | ptr_output_time_dmx[sample_idx] = (FLOAT32)temp; |
207 | 194M | } |
208 | | |
209 | 89.6k | pstr_enhanced_time_domain_dmx->prev_gain[LEFT_CH] = gain_left; |
210 | 89.6k | pstr_enhanced_time_domain_dmx->prev_gain[RIGHT_CH] = gain_right; |
211 | 89.6k | pstr_enhanced_time_domain_dmx->prev_h1[LEFT_CH] = h1[LEFT_CH]; |
212 | 89.6k | pstr_enhanced_time_domain_dmx->prev_h1[RIGHT_CH] = h1[RIGHT_CH]; |
213 | | |
214 | 89.6k | return error; |
215 | 89.6k | } |