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
ixheaace_mps_212_calculate_ratio(const FLOAT32 sqrt_lin_cld_m,const FLOAT32 lin_cld_m,const FLOAT32 icc_m,FLOAT32 g_m[2])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 FLOAT32 g_m[2]) {
39 if (icc_m >= 0.f) {
40 g_m[0] = g_m[1] = 1.0f;
41 } else {
42 FLOAT32 max_gain_factor = 2.0f;
43 FLOAT32 numerator, denominator;
44 FLOAT32 q = 0.0f;
45 numerator = (lin_cld_m + 0.5f) + (icc_m * sqrt_lin_cld_m);
46 denominator = (lin_cld_m + 0.5f) - (icc_m * sqrt_lin_cld_m);
47
48 if ((numerator > (0.f)) && (denominator > (0.f))) {
49 FLOAT32 intermediate;
50 intermediate = numerator / denominator;
51 intermediate = (FLOAT32)sqrt(intermediate);
52 intermediate = (FLOAT32)sqrt(intermediate);
53 q = (intermediate >= max_gain_factor) ? max_gain_factor : intermediate;
54 }
55
56 g_m[0] = max_gain_factor - q;
57 g_m[1] = q;
58 }
59 }
60
ixheaace_mps_212_calculate_dmx_gains(const FLOAT32 lin_cld_m,const FLOAT32 lin_cld_2_m,const FLOAT32 icc_m,const FLOAT32 g_m[2],FLOAT32 h_1_m[2])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 const FLOAT32 g_m[2], FLOAT32 h_1_m[2]) {
64 const FLOAT32 max_gain_factor = 2.0f;
65 FLOAT32 energy_right, energy_left, cross_energy, inverse_weight_num, inverse_weight_den,
66 inverse_weight, inverse_weight_limited;
67 energy_right = lin_cld_2_m - 0.5f;
68 energy_right = (FLOAT32)sqrt(energy_right);
69 energy_left = lin_cld_m * energy_right;
70 cross_energy = (FLOAT32)sqrt(energy_left * energy_right);
71 inverse_weight_num = energy_right + energy_left;
72 inverse_weight_den = ((g_m[0] * g_m[0]) * energy_left) + ((g_m[1] * g_m[1]) * energy_right);
73
74 inverse_weight_den = ((((g_m[0] * g_m[1]) * cross_energy) * icc_m) * 2) + inverse_weight_den;
75
76 if (inverse_weight_den > (0.f)) {
77 inverse_weight = inverse_weight_num / inverse_weight_den;
78
79 inverse_weight = (FLOAT32)sqrt(inverse_weight);
80
81 inverse_weight_limited =
82 (inverse_weight >= max_gain_factor) ? max_gain_factor : inverse_weight;
83 } else {
84 inverse_weight_limited = max_gain_factor;
85 }
86
87 h_1_m[1] = g_m[1] * inverse_weight_limited;
88 h_1_m[0] = g_m[0] * inverse_weight_limited;
89 }
90
ixheaace_mps_212_init_enhanced_time_domain_dmx(ixheaace_mps_pstr_enhanced_time_domain_dmx pstr_enhanced_time_domain_dmx,const FLOAT32 * const ptr_input_gain_m_flt,const FLOAT32 output_gain_m_flt,const WORD32 frame_length)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 const WORD32 frame_length) {
95 IA_ERRORCODE error = IA_NO_ERROR;
96 WORD32 sample_idx;
97 FLOAT32 delta;
98 if (frame_length > pstr_enhanced_time_domain_dmx->max_frame_length) {
99 return IA_EXHEAACE_INIT_FATAL_MPS_INIT_FAILED;
100 }
101 pstr_enhanced_time_domain_dmx->frame_length = frame_length;
102 delta = (FLOAT32)(PI_FLT / (2.0 * pstr_enhanced_time_domain_dmx->frame_length));
103 for (sample_idx = 0; sample_idx < pstr_enhanced_time_domain_dmx->frame_length + 1;
104 sample_idx++) {
105 FLOAT32 sin_val = (FLOAT32)sin(sample_idx * delta);
106 pstr_enhanced_time_domain_dmx->sinus_window[sample_idx] = ALPHA * sin_val * sin_val;
107 }
108
109 pstr_enhanced_time_domain_dmx->prev_left_energy =
110 pstr_enhanced_time_domain_dmx->prev_right_energy =
111 pstr_enhanced_time_domain_dmx->prev_x_energy = 0.0f;
112 pstr_enhanced_time_domain_dmx->cld_weight =
113 (ptr_input_gain_m_flt[LEFT_CH]) / (ptr_input_gain_m_flt[RIGHT_CH]);
114 pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH] =
115 (ptr_input_gain_m_flt[LEFT_CH] * output_gain_m_flt);
116 pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH] =
117 (ptr_input_gain_m_flt[RIGHT_CH] * output_gain_m_flt);
118 pstr_enhanced_time_domain_dmx->prev_gain[LEFT_CH] =
119 pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH];
120 pstr_enhanced_time_domain_dmx->prev_gain[RIGHT_CH] =
121 pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH];
122 pstr_enhanced_time_domain_dmx->prev_h1[LEFT_CH] =
123 pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH];
124 pstr_enhanced_time_domain_dmx->prev_h1[RIGHT_CH] =
125 pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH];
126 return error;
127 }
128
ixheaace_mps_212_apply_enhanced_time_domain_dmx(ixheaace_mps_pstr_enhanced_time_domain_dmx pstr_enhanced_time_domain_dmx,FLOAT32 input_time[2][MPS_MAX_FRAME_LENGTH+MAX_DELAY_SURROUND_ANALYSIS],FLOAT32 * const ptr_output_time_dmx,const WORD32 input_delay)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 FLOAT32 *const ptr_output_time_dmx, const WORD32 input_delay) {
133 IA_ERRORCODE error = IA_NO_ERROR;
134
135 WORD32 sample_idx;
136 FLOAT32 lin_bb_cld, lin_cld, corr, sqrt_lin_cld, g[2], h1[2], gain_left, gain_right;
137 FLOAT32 prev_energy_left, prev_energy_right, prev_energy, energy_left, energy_right, energy_out;
138 WORD32 granule_length = MIN(128, pstr_enhanced_time_domain_dmx->frame_length);
139
140 sample_idx = 0;
141 prev_energy_left = prev_energy_right = prev_energy = .5f;
142
143 do {
144 WORD32 offset = sample_idx;
145 FLOAT32 partial_left, partial_right, partial_out;
146 partial_left = partial_right = partial_out = 0.0;
147
148 WORD32 value = MIN(offset + granule_length, pstr_enhanced_time_domain_dmx->frame_length);
149 for (sample_idx = offset; sample_idx < value; sample_idx++) {
150 FLOAT32 input_left = input_time[LEFT_CH][sample_idx];
151 FLOAT32 input_right = input_time[RIGHT_CH][sample_idx];
152
153 partial_left += (FLOAT32)pow(input_left, 2);
154 partial_right += (FLOAT32)pow(input_right, 2);
155 partial_out += input_left * input_right;
156 }
157
158 prev_energy_left = prev_energy_left + partial_left;
159 prev_energy_right = prev_energy_right + partial_right;
160 prev_energy = prev_energy + partial_out;
161
162 } while (sample_idx < pstr_enhanced_time_domain_dmx->frame_length);
163
164 energy_left = pstr_enhanced_time_domain_dmx->prev_left_energy + prev_energy_left;
165 energy_right = pstr_enhanced_time_domain_dmx->prev_right_energy + prev_energy_right;
166 energy_out = pstr_enhanced_time_domain_dmx->prev_x_energy + prev_energy;
167
168 lin_bb_cld = pstr_enhanced_time_domain_dmx->cld_weight * (energy_left / energy_right);
169 corr = energy_out * (1 / (FLOAT32)sqrt(energy_left * energy_right));
170
171 pstr_enhanced_time_domain_dmx->prev_left_energy = prev_energy_left;
172 pstr_enhanced_time_domain_dmx->prev_right_energy = prev_energy_right;
173 pstr_enhanced_time_domain_dmx->prev_x_energy = prev_energy;
174
175 lin_cld = (FLOAT32)sqrt(lin_bb_cld);
176 sqrt_lin_cld = (FLOAT32)sqrt(lin_cld);
177
178 ixheaace_mps_212_calculate_ratio(sqrt_lin_cld, lin_cld, corr, g);
179
180 ixheaace_mps_212_calculate_dmx_gains(lin_cld, lin_bb_cld, corr, g, h1);
181
182 h1[LEFT_CH] = h1[LEFT_CH] * pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH];
183 h1[RIGHT_CH] = h1[RIGHT_CH] * pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH];
184
185 gain_left = pstr_enhanced_time_domain_dmx->prev_gain[LEFT_CH];
186 gain_right = pstr_enhanced_time_domain_dmx->prev_gain[RIGHT_CH];
187
188 for (sample_idx = 0; sample_idx < pstr_enhanced_time_domain_dmx->frame_length; sample_idx++) {
189 WORD32 frame_length = pstr_enhanced_time_domain_dmx->frame_length;
190 FLOAT32 intermediate_gain_left, intermediate_gain_right, temp;
191
192 intermediate_gain_left =
193 ((pstr_enhanced_time_domain_dmx->sinus_window[sample_idx] * h1[LEFT_CH]) +
194 (pstr_enhanced_time_domain_dmx->sinus_window[frame_length - sample_idx] *
195 pstr_enhanced_time_domain_dmx->prev_h1[LEFT_CH]));
196
197 intermediate_gain_right =
198 ((pstr_enhanced_time_domain_dmx->sinus_window[sample_idx] * h1[RIGHT_CH]) +
199 (pstr_enhanced_time_domain_dmx->sinus_window[frame_length - sample_idx] *
200 pstr_enhanced_time_domain_dmx->prev_h1[RIGHT_CH]));
201
202 gain_left = intermediate_gain_left + ((1.f - ALPHA) * gain_left);
203 gain_right = intermediate_gain_right + ((1.f - ALPHA) * gain_right);
204 temp = (gain_left * (FLOAT32)input_time[LEFT_CH][sample_idx + input_delay]) +
205 (gain_right * (FLOAT32)input_time[RIGHT_CH][sample_idx + input_delay]);
206 ptr_output_time_dmx[sample_idx] = (FLOAT32)temp;
207 }
208
209 pstr_enhanced_time_domain_dmx->prev_gain[LEFT_CH] = gain_left;
210 pstr_enhanced_time_domain_dmx->prev_gain[RIGHT_CH] = gain_right;
211 pstr_enhanced_time_domain_dmx->prev_h1[LEFT_CH] = h1[LEFT_CH];
212 pstr_enhanced_time_domain_dmx->prev_h1[RIGHT_CH] = h1[RIGHT_CH];
213
214 return error;
215 }
216