xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_block_switch.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
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