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 "ixheaac_type_def.h"
22 #include "ixheaac_constants.h"
23 #include "ixheaace_aac_constants.h"
24 #include "ixheaace_psy_const.h"
25 #include "ixheaace_tns.h"
26 #include "ixheaace_tns_params.h"
27 #include "ixheaace_rom.h"
28 #include "ixheaace_common_rom.h"
29 #include "ixheaace_bitbuffer.h"
30 #include "ixheaac_basic_ops32.h"
31 #include "ixheaac_basic_ops40.h"
32 #include "ixheaac_basic_ops.h"
33 #include "ixheaace_block_switch.h"
34 #include "iusace_block_switch_struct_def.h"
35 #include <string.h>
36
iaace_fmult(FLOAT32 a,FLOAT32 b)37 static FLOAT32 iaace_fmult(FLOAT32 a, FLOAT32 b) { return (a * b); }
38
iaace_fadd(FLOAT32 a,FLOAT32 b)39 static FLOAT32 iaace_fadd(FLOAT32 a, FLOAT32 b) { return (a + b); }
40
iaace_init_block_switching(ixheaace_block_switch_control * pstr_blk_switch_ctrl,const WORD32 bit_rate,const WORD32 num_chans)41 VOID iaace_init_block_switching(ixheaace_block_switch_control *pstr_blk_switch_ctrl,
42 const WORD32 bit_rate, const WORD32 num_chans) {
43 if ((num_chans == 1 && bit_rate > BLK_SWITCH_HIGH_BR_MONO) ||
44 (num_chans > 1 && bit_rate / num_chans > BLK_SWITCH_HIGH_BR_STEREO)) {
45 pstr_blk_switch_ctrl->inv_attack_ratio = INV_ATTACK_RATIO_HIGH_BR;
46 } else {
47 pstr_blk_switch_ctrl->inv_attack_ratio = INV_ATTACK_RATIO_LOW_BR;
48 }
49
50 memset(pstr_blk_switch_ctrl->iir_states, 0,
51 BLK_SWITCH_FILT_LEN * sizeof(pstr_blk_switch_ctrl->iir_states[0]));
52 /* Clear Filtered Window Energies */
53
54 memset(pstr_blk_switch_ctrl->win_energy_filt, 0,
55 BLK_SWITCH_WIN * sizeof(pstr_blk_switch_ctrl->win_energy_filt[0][0]));
56 memset(pstr_blk_switch_ctrl->win_energy, 0,
57 BLK_SWITCH_WIN * sizeof(pstr_blk_switch_ctrl->win_energy[0][0]));
58
59 pstr_blk_switch_ctrl->acc_win_energy = 0;
60
61 pstr_blk_switch_ctrl->win_seq = LONG_WINDOW;
62 pstr_blk_switch_ctrl->nxt_win_seq = LONG_WINDOW;
63
64 pstr_blk_switch_ctrl->attack = 0;
65 pstr_blk_switch_ctrl->lastattack = 0;
66 pstr_blk_switch_ctrl->attack_idx = 0;
67 pstr_blk_switch_ctrl->last_attack_idx = 0;
68 }
69
iaace_search_max_with_idx(const FLOAT32 * ptr_in,WORD32 * ptr_index,WORD32 len)70 static FLOAT32 iaace_search_max_with_idx(const FLOAT32 *ptr_in, WORD32 *ptr_index, WORD32 len) {
71 FLOAT32 max = 0;
72 WORD32 i = 0, idx = 0;
73
74 do {
75 if (ptr_in[i + 1] > max) {
76 max = ptr_in[i + 1];
77 idx = i;
78 }
79 i++;
80 } while (i < len);
81
82 *ptr_index = idx;
83
84 return max;
85 }
86
iaace_blk_switch_iir_filt(const FLOAT32 input,const FLOAT32 * ptr_iir_coeff,FLOAT32 * ptr_iir_states)87 static FLOAT32 iaace_blk_switch_iir_filt(const FLOAT32 input, const FLOAT32 *ptr_iir_coeff,
88 FLOAT32 *ptr_iir_states) {
89 FLOAT32 accu_1, accu_2;
90 FLOAT32 out;
91
92 accu_1 = ptr_iir_coeff[1] * (input - ptr_iir_states[0]);
93
94 accu_2 = ptr_iir_coeff[0] * ptr_iir_states[1];
95
96 out = accu_1 - accu_2;
97 ptr_iir_states[0] = input;
98 ptr_iir_states[1] = out;
99
100 return out;
101 }
102
iaace_calc_window_energy(ixheaace_block_switch_control * pstr_blk_switch_ctrl,const FLOAT32 * ptr_time_signal,WORD32 ch_increment,WORD32 win_len)103 static VOID iaace_calc_window_energy(ixheaace_block_switch_control *pstr_blk_switch_ctrl,
104 const FLOAT32 *ptr_time_signal, WORD32 ch_increment,
105 WORD32 win_len) {
106 WORD32 i, w;
107 FLOAT32 acc_nrg_unfilt, acc_nrg_filt;
108 FLOAT32 tmp_nrg_unfilt, tmp_nrg_filt;
109 for (w = 0; w < BLK_SWITCH_WIN; w++) {
110 acc_nrg_unfilt = 0.0f;
111 acc_nrg_filt = 0.0f;
112
113 for (i = 0; i < win_len; i++) {
114 tmp_nrg_unfilt = ptr_time_signal[(win_len * w + i) * ch_increment];
115 tmp_nrg_filt = iaace_blk_switch_iir_filt(tmp_nrg_unfilt, iaace_iir_hipass_coeffs,
116 pstr_blk_switch_ctrl->iir_states);
117
118 acc_nrg_unfilt += (tmp_nrg_unfilt * tmp_nrg_unfilt);
119 acc_nrg_filt += (tmp_nrg_filt * tmp_nrg_filt);
120 }
121
122 pstr_blk_switch_ctrl->win_energy[1][w] = acc_nrg_unfilt;
123 pstr_blk_switch_ctrl->win_energy_filt[1][w] = acc_nrg_filt;
124 }
125 }
126
iaace_block_switching(ixheaace_block_switch_control * pstr_blk_switch_ctrl,const FLOAT32 * ptr_time_signal,WORD32 frame_length,WORD32 num_chans)127 VOID iaace_block_switching(ixheaace_block_switch_control *pstr_blk_switch_ctrl,
128 const FLOAT32 *ptr_time_signal, WORD32 frame_length,
129 WORD32 num_chans) {
130 WORD32 win_idx;
131 FLOAT32 tmp_nrg_1, tmp_nrg_2;
132 FLOAT32 prev_win_nrg, max_nrg;
133
134 memset(pstr_blk_switch_ctrl->group_len, 0,
135 TRANS_FAC * sizeof(pstr_blk_switch_ctrl->group_len[0]));
136
137 pstr_blk_switch_ctrl->max_win_energy =
138 iaace_search_max_with_idx(&pstr_blk_switch_ctrl->win_energy[0][BLK_SWITCH_WIN - 1],
139 &pstr_blk_switch_ctrl->attack_idx, BLK_SWITCH_WIN);
140
141 pstr_blk_switch_ctrl->attack_idx = pstr_blk_switch_ctrl->last_attack_idx;
142 pstr_blk_switch_ctrl->total_groups_cnt = MAXIMUM_NO_OF_GROUPS;
143
144 memcpy(pstr_blk_switch_ctrl->group_len,
145 iaace_suggested_grouping_table[pstr_blk_switch_ctrl->attack_idx],
146 MAXIMUM_NO_OF_GROUPS * sizeof(pstr_blk_switch_ctrl->group_len[0]));
147
148 memcpy(pstr_blk_switch_ctrl->win_energy[0], pstr_blk_switch_ctrl->win_energy[1],
149 BLK_SWITCH_WIN * sizeof(pstr_blk_switch_ctrl->win_energy[0][0]));
150 memcpy(pstr_blk_switch_ctrl->win_energy_filt[0], pstr_blk_switch_ctrl->win_energy_filt[1],
151 BLK_SWITCH_WIN * sizeof(pstr_blk_switch_ctrl->win_energy_filt[0][0]));
152
153 iaace_calc_window_energy(
154 pstr_blk_switch_ctrl, ptr_time_signal, num_chans,
155 (frame_length == FRAME_LEN_960 ? FRAME_LEN_SHORT_120 : FRAME_LEN_SHORT_128));
156
157 pstr_blk_switch_ctrl->attack = FALSE;
158
159 max_nrg = 0.0f;
160
161 prev_win_nrg = pstr_blk_switch_ctrl->win_energy_filt[0][BLK_SWITCH_WIN - 1];
162
163 for (win_idx = 0; win_idx < BLK_SWITCH_WIN; win_idx++) {
164 tmp_nrg_1 = iaace_fmult(ONE_MINUS_ACC_WINDOW_NRG_FAC, pstr_blk_switch_ctrl->acc_win_energy);
165 tmp_nrg_2 = iaace_fmult(ACC_WINDOW_NRG_FAC, prev_win_nrg);
166 pstr_blk_switch_ctrl->acc_win_energy = iaace_fadd(tmp_nrg_1, tmp_nrg_2);
167
168 tmp_nrg_1 = iaace_fmult(pstr_blk_switch_ctrl->win_energy_filt[1][win_idx],
169 pstr_blk_switch_ctrl->inv_attack_ratio);
170 if (tmp_nrg_1 > pstr_blk_switch_ctrl->acc_win_energy) {
171 pstr_blk_switch_ctrl->attack = TRUE;
172 pstr_blk_switch_ctrl->last_attack_idx = win_idx;
173 }
174
175 prev_win_nrg = pstr_blk_switch_ctrl->win_energy_filt[1][win_idx];
176
177 max_nrg = MAX(prev_win_nrg, max_nrg);
178 }
179
180 if (max_nrg < MIN_ATTACK_NRG) {
181 pstr_blk_switch_ctrl->attack = FALSE;
182 }
183
184 if ((!pstr_blk_switch_ctrl->attack) && (pstr_blk_switch_ctrl->lastattack)) {
185 if (pstr_blk_switch_ctrl->attack_idx == (TRANS_FAC - 1)) {
186 pstr_blk_switch_ctrl->attack = TRUE;
187 }
188 pstr_blk_switch_ctrl->lastattack = FALSE;
189 } else {
190 pstr_blk_switch_ctrl->lastattack = pstr_blk_switch_ctrl->attack;
191 }
192 pstr_blk_switch_ctrl->win_seq = pstr_blk_switch_ctrl->nxt_win_seq;
193
194 pstr_blk_switch_ctrl->nxt_win_seq =
195 (pstr_blk_switch_ctrl->attack == 1) ? SHORT_WINDOW : LONG_WINDOW;
196
197 if (pstr_blk_switch_ctrl->nxt_win_seq == SHORT_WINDOW) {
198 if (pstr_blk_switch_ctrl->win_seq == LONG_WINDOW) {
199 pstr_blk_switch_ctrl->win_seq = START_WINDOW;
200 } else if (pstr_blk_switch_ctrl->win_seq == STOP_WINDOW) {
201 pstr_blk_switch_ctrl->win_seq = SHORT_WINDOW;
202 pstr_blk_switch_ctrl->total_groups_cnt = 3;
203 pstr_blk_switch_ctrl->group_len[0] = 3;
204 pstr_blk_switch_ctrl->group_len[1] = 3;
205 pstr_blk_switch_ctrl->group_len[2] = 2;
206 }
207 }
208
209 if (pstr_blk_switch_ctrl->nxt_win_seq == LONG_WINDOW &&
210 pstr_blk_switch_ctrl->win_seq == SHORT_WINDOW) {
211 pstr_blk_switch_ctrl->nxt_win_seq = STOP_WINDOW;
212 }
213 }
214
iaace_sync_block_switching(ixheaace_block_switch_control * pstr_blk_switch_left_ctrl,ixheaace_block_switch_control * pstr_blk_switch_right_ctrl,const WORD32 num_channels)215 VOID iaace_sync_block_switching(ixheaace_block_switch_control *pstr_blk_switch_left_ctrl,
216 ixheaace_block_switch_control *pstr_blk_switch_right_ctrl,
217 const WORD32 num_channels) {
218 WORD32 i;
219 WORD32 patch_type = LONG_WINDOW;
220
221 if (num_channels == 1) {
222 if (pstr_blk_switch_left_ctrl->win_seq != SHORT_WINDOW) {
223 pstr_blk_switch_left_ctrl->total_groups_cnt = 1;
224 pstr_blk_switch_left_ctrl->group_len[0] = 1;
225
226 for (i = 1; i < TRANS_FAC; i++) {
227 pstr_blk_switch_left_ctrl->group_len[i] = 0;
228 }
229 }
230 } else {
231 /* Stereo */
232
233 patch_type = iaace_synchronized_block_types[patch_type][pstr_blk_switch_left_ctrl->win_seq];
234 patch_type = iaace_synchronized_block_types[patch_type][pstr_blk_switch_right_ctrl->win_seq];
235
236 pstr_blk_switch_left_ctrl->win_seq = patch_type;
237 pstr_blk_switch_right_ctrl->win_seq = patch_type;
238
239 if (patch_type != SHORT_WINDOW) { /* tns_data_long Blocks */
240 pstr_blk_switch_left_ctrl->total_groups_cnt = 1;
241 pstr_blk_switch_right_ctrl->total_groups_cnt = 1;
242 pstr_blk_switch_left_ctrl->group_len[0] = 1;
243 pstr_blk_switch_right_ctrl->group_len[0] = 1;
244
245 for (i = 1; i < TRANS_FAC; i++) {
246 pstr_blk_switch_left_ctrl->group_len[i] = 0;
247 pstr_blk_switch_right_ctrl->group_len[i] = 0;
248 }
249 } else { /* tns_data_short Blocks */
250 if (pstr_blk_switch_left_ctrl->max_win_energy >
251 pstr_blk_switch_right_ctrl->max_win_energy) {
252 pstr_blk_switch_right_ctrl->total_groups_cnt =
253 pstr_blk_switch_left_ctrl->total_groups_cnt;
254 for (i = 0; i < TRANS_FAC; i++) {
255 pstr_blk_switch_right_ctrl->group_len[i] = pstr_blk_switch_left_ctrl->group_len[i];
256 }
257 } else {
258 pstr_blk_switch_left_ctrl->total_groups_cnt =
259 pstr_blk_switch_right_ctrl->total_groups_cnt;
260 for (i = 0; i < TRANS_FAC; i++) {
261 pstr_blk_switch_left_ctrl->group_len[i] = pstr_blk_switch_right_ctrl->group_len[i];
262 }
263 }
264 }
265 }
266 }
267