Coverage Report

Created: 2026-04-12 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libxaac/encoder/iusace_block_switch.c
Line
Count
Source
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 "iusace_type_def.h"
22
#include "ixheaace_mps_common_define.h"
23
#include "iusace_cnst.h"
24
#include "iusace_block_switch_const.h"
25
#include "iusace_block_switch_struct_def.h"
26
#include "iusace_rom.h"
27
28
1.99G
static FLOAT32 iusace_fmult(FLOAT32 a, FLOAT32 b) { return (a * b); }
29
30
798M
static FLOAT32 iusace_fadd(FLOAT32 a, FLOAT32 b) { return (a + b); }
31
32
VOID iusace_init_block_switching(ia_block_switch_ctrl *pstr_blk_switch_ctrl,
33
5.62k
                                 const WORD32 bit_rate, const WORD32 num_chans) {
34
5.62k
  WORD32 i, w;
35
36
5.62k
  if ((num_chans == 1 && bit_rate > 24000) || (num_chans > 1 && bit_rate / num_chans > 16000)) {
37
5.60k
    pstr_blk_switch_ctrl->inv_attack_ratio = INV_ATTACK_RATIO_HIGH_BR;
38
5.60k
  } else {
39
17
    pstr_blk_switch_ctrl->inv_attack_ratio = INV_ATTACK_RATIO_LOW_BR;
40
17
  }
41
42
16.8k
  for (i = 0; i < BLK_SWITCH_FILT_LEN; i++) {
43
11.2k
    pstr_blk_switch_ctrl->iir_states[i] = 0;
44
11.2k
  }
45
46
  /* Clear Filtered Window Energies */
47
50.6k
  for (w = 0; w < MAX_SHORT_WINDOWS; w++) {
48
44.9k
    pstr_blk_switch_ctrl->win_energy_filt[0][w] = 0;
49
44.9k
    pstr_blk_switch_ctrl->win_energy_filt[1][w] = 0;
50
44.9k
    pstr_blk_switch_ctrl->win_energy[0][w] = 0;
51
44.9k
    pstr_blk_switch_ctrl->win_energy[1][w] = 0;
52
44.9k
  }
53
5.62k
  pstr_blk_switch_ctrl->acc_win_energy = 0;
54
55
5.62k
  pstr_blk_switch_ctrl->window_seq = ONLY_LONG_SEQUENCE;
56
5.62k
  pstr_blk_switch_ctrl->next_win_seq = ONLY_LONG_SEQUENCE;
57
58
5.62k
  pstr_blk_switch_ctrl->attack = 0;
59
5.62k
  pstr_blk_switch_ctrl->lastattack = 0;
60
5.62k
  pstr_blk_switch_ctrl->attack_idx = 0;
61
5.62k
  pstr_blk_switch_ctrl->last_attack_idx = 0;
62
63
5.62k
  return;
64
5.62k
}
65
66
421k
static FLOAT32 iusace_srch_max_with_idx(const FLOAT32 *ptr_in, WORD32 *index) {
67
421k
  FLOAT32 max;
68
421k
  WORD32 i, idx;
69
70
421k
  max = 0;
71
421k
  idx = 0;
72
73
3.79M
  for (i = 0; i < MAX_SHORT_WINDOWS; i++) {
74
3.37M
    if (ptr_in[i + 1] > max) {
75
758k
      max = ptr_in[i + 1];
76
758k
      idx = i;
77
758k
    }
78
3.37M
  }
79
421k
  *index = idx;
80
81
421k
  return max;
82
421k
}
83
84
static VOID iusace_blk_switch_iir_filt(const FLOAT32 *ptr_in, const FLOAT32 *ptr_iir_coeff,
85
                                       const WORD32 w, FLOAT32 *ptr_iir_states,
86
3.37M
                                       FLOAT32 *energy_accu, WORD32 block_len) {
87
3.37M
  FLOAT32 accu1;
88
89
3.37M
  WORD32 i;
90
91
3.37M
  FLOAT32 accu_unfilt = 0.0f;
92
3.37M
  FLOAT32 accu_filt = 0.0f;
93
3.37M
  FLOAT32 accu2, temp2, temp1;
94
95
3.37M
  FLOAT32 state0 = ptr_iir_states[0];
96
3.37M
  FLOAT32 state1 = ptr_iir_states[1];
97
98
3.37M
  FLOAT32 coeff0 = ptr_iir_coeff[0];
99
3.37M
  FLOAT32 coeff1 = ptr_iir_coeff[1];
100
101
3.37M
  const FLOAT32 *p_time_signal = &ptr_in[(block_len * w)];
102
103
400M
  for (i = 0; i < block_len; i++) {
104
397M
    accu2 = iusace_fmult(state0, coeff1);
105
397M
    accu1 = iusace_fmult(state1, coeff0);
106
397M
    accu1 += accu2;
107
108
397M
    state0 = p_time_signal[i];
109
397M
    state1 = iusace_fmult(state0, coeff1);
110
397M
    state1 = (state1 - accu1);
111
112
397M
    temp1 = iusace_fmult(state0, state0);
113
397M
    temp2 = iusace_fmult(state1, state1);
114
115
397M
    accu_unfilt = iusace_fadd(accu_unfilt, temp1);
116
397M
    accu_filt = iusace_fadd(accu_filt, temp2);
117
397M
  }
118
119
3.37M
  energy_accu[0] = accu_unfilt;
120
3.37M
  energy_accu[1] = accu_filt;
121
122
3.37M
  ptr_iir_states[0] = state0;
123
3.37M
  ptr_iir_states[1] = state1;
124
125
3.37M
  return;
126
3.37M
}
127
128
static VOID iusace_calc_window_energy(ia_block_switch_ctrl *ptr_blk_switch_ctrl,
129
421k
                                      const FLOAT32 *ptr_in, FLOAT32 *max, WORD32 ccfl) {
130
421k
  WORD32 w;
131
132
421k
  FLOAT32 energy_accu[2];
133
421k
  *max = 0.0f;
134
135
3.79M
  for (w = 0; w < MAX_SHORT_WINDOWS; w++) {
136
    // block length for calculating energy is corecoder frame length / MAX_SHORT_WINDOWS
137
3.37M
    iusace_blk_switch_iir_filt(ptr_in, iusace_iir_hipass_coeffs, w,
138
3.37M
                               ptr_blk_switch_ctrl->iir_states, &energy_accu[0], ccfl >> 3);
139
140
3.37M
    ptr_blk_switch_ctrl->win_energy[1][w] = energy_accu[0];
141
3.37M
    ptr_blk_switch_ctrl->win_energy_filt[1][w] = energy_accu[1];
142
143
3.37M
    if (ptr_blk_switch_ctrl->win_energy_filt[1][w] > *max)
144
758k
      *max = ptr_blk_switch_ctrl->win_energy_filt[1][w];
145
3.37M
  }
146
421k
  return;
147
421k
}
148
149
VOID iusace_block_switching(ia_block_switch_ctrl *ptr_blk_switch_ctrl, const FLOAT32 *ptr_in,
150
421k
                            WORD32 ccfl) {
151
421k
  WORD32 i;
152
153
421k
  FLOAT32 temp1, temp2;
154
421k
  FLOAT32 max;
155
421k
  FLOAT32 energy, energy_max;
156
157
3.79M
  for (i = 0; i < MAX_SHORT_WINDOWS; i++) {
158
3.37M
    ptr_blk_switch_ctrl->group_len[i] = 0;
159
3.37M
  }
160
161
421k
  ptr_blk_switch_ctrl->max_win_energy =
162
421k
      iusace_srch_max_with_idx(&ptr_blk_switch_ctrl->win_energy[0][MAX_SHORT_WINDOWS - 1],
163
421k
                               &ptr_blk_switch_ctrl->attack_idx);
164
165
421k
  ptr_blk_switch_ctrl->attack_idx = ptr_blk_switch_ctrl->last_attack_idx;
166
421k
  ptr_blk_switch_ctrl->tot_grps_cnt = MAXIMUM_NO_OF_GROUPS;
167
168
2.10M
  for (i = 0; i < MAXIMUM_NO_OF_GROUPS; i++) {
169
1.68M
    ptr_blk_switch_ctrl->group_len[i] =
170
1.68M
        iusace_suggested_grouping_table[ptr_blk_switch_ctrl->attack_idx][i];
171
1.68M
  }
172
173
3.79M
  for (i = 0; i < MAX_SHORT_WINDOWS; i++) {
174
3.37M
    ptr_blk_switch_ctrl->win_energy[0][i] = ptr_blk_switch_ctrl->win_energy[1][i];
175
3.37M
    ptr_blk_switch_ctrl->win_energy_filt[0][i] = ptr_blk_switch_ctrl->win_energy_filt[1][i];
176
3.37M
  }
177
178
421k
  iusace_calc_window_energy(ptr_blk_switch_ctrl, ptr_in, &max, ccfl);
179
180
421k
  ptr_blk_switch_ctrl->attack = FALSE;
181
182
421k
  energy_max = 0.0f;
183
184
421k
  energy = ptr_blk_switch_ctrl->win_energy_filt[0][MAX_SHORT_WINDOWS - 1];
185
186
3.79M
  for (i = 0; i < MAX_SHORT_WINDOWS; i++) {
187
3.37M
    temp1 = iusace_fmult(ONE_MINUS_ACC_WINDOW_NRG_FAC, ptr_blk_switch_ctrl->acc_win_energy);
188
3.37M
    temp2 = iusace_fmult(ACC_WINDOW_NRG_FAC, energy);
189
3.37M
    ptr_blk_switch_ctrl->acc_win_energy = iusace_fadd(temp1, temp2);
190
191
3.37M
    temp1 = iusace_fmult(ptr_blk_switch_ctrl->win_energy_filt[1][i],
192
3.37M
                         ptr_blk_switch_ctrl->inv_attack_ratio);
193
3.37M
    if (temp1 > ptr_blk_switch_ctrl->acc_win_energy) {
194
125k
      ptr_blk_switch_ctrl->attack = TRUE;
195
125k
      ptr_blk_switch_ctrl->last_attack_idx = i;
196
125k
    }
197
198
3.37M
    energy = ptr_blk_switch_ctrl->win_energy_filt[1][i];
199
3.37M
    if (energy_max < energy) energy_max = energy;
200
3.37M
  }
201
202
421k
  if (ccfl == LEN_SUPERFRAME_768) {
203
133k
    energy_max = (energy_max * 4) / 3.0f;
204
133k
  }
205
421k
  if (energy_max < USAC_MIN_ATTACK_NRG) {
206
210k
    ptr_blk_switch_ctrl->attack = FALSE;
207
210k
  }
208
209
421k
  if ((!ptr_blk_switch_ctrl->attack) && (ptr_blk_switch_ctrl->lastattack)) {
210
65.9k
    if (ptr_blk_switch_ctrl->attack_idx == MAX_SHORT_WINDOWS - 1) {
211
2.01k
      ptr_blk_switch_ctrl->attack = TRUE;
212
2.01k
    }
213
65.9k
    ptr_blk_switch_ctrl->lastattack = FALSE;
214
355k
  } else {
215
355k
    ptr_blk_switch_ctrl->lastattack = ptr_blk_switch_ctrl->attack;
216
355k
  }
217
421k
  ptr_blk_switch_ctrl->window_seq = ptr_blk_switch_ctrl->next_win_seq;
218
219
421k
  if (ptr_blk_switch_ctrl->attack) {
220
116k
    ptr_blk_switch_ctrl->next_win_seq = EIGHT_SHORT_SEQUENCE;
221
304k
  } else {
222
304k
    ptr_blk_switch_ctrl->next_win_seq = ONLY_LONG_SEQUENCE;
223
304k
  }
224
421k
  if (ptr_blk_switch_ctrl->next_win_seq == EIGHT_SHORT_SEQUENCE) {
225
116k
    if (ptr_blk_switch_ctrl->window_seq == ONLY_LONG_SEQUENCE) {
226
46.6k
      ptr_blk_switch_ctrl->window_seq = LONG_START_SEQUENCE;
227
46.6k
    }
228
229
116k
    if (ptr_blk_switch_ctrl->window_seq == LONG_STOP_SEQUENCE) {
230
21.9k
      ptr_blk_switch_ctrl->window_seq = EIGHT_SHORT_SEQUENCE;
231
21.9k
      ptr_blk_switch_ctrl->tot_grps_cnt = 3;
232
21.9k
      ptr_blk_switch_ctrl->group_len[0] = 3;
233
21.9k
      ptr_blk_switch_ctrl->group_len[1] = 3;
234
21.9k
      ptr_blk_switch_ctrl->group_len[2] = 2;
235
21.9k
    }
236
116k
  }
237
238
421k
  if (ptr_blk_switch_ctrl->next_win_seq == ONLY_LONG_SEQUENCE) {
239
304k
    if (ptr_blk_switch_ctrl->window_seq == EIGHT_SHORT_SEQUENCE) {
240
65.2k
      ptr_blk_switch_ctrl->next_win_seq = LONG_STOP_SEQUENCE;
241
65.2k
    }
242
304k
  }
243
421k
  return;
244
421k
}
245
246
VOID iusace_sync_block_switching(ia_block_switch_ctrl *ptr_blk_switch_left_ctrl,
247
229k
                                 ia_block_switch_ctrl *ptr_blk_switch_right_ctrl) {
248
229k
  WORD32 i;
249
229k
  WORD32 patch_type = ONLY_LONG_SEQUENCE;
250
251
229k
  patch_type = iusace_synchronized_block_types[patch_type][ptr_blk_switch_left_ctrl->window_seq];
252
229k
  patch_type = iusace_synchronized_block_types[patch_type][ptr_blk_switch_right_ctrl->window_seq];
253
254
229k
  ptr_blk_switch_left_ctrl->window_seq = patch_type;
255
229k
  ptr_blk_switch_right_ctrl->window_seq = patch_type;
256
257
229k
  if (patch_type != EIGHT_SHORT_SEQUENCE) { /* tns_data_long Blocks */
258
159k
    ptr_blk_switch_left_ctrl->tot_grps_cnt = 1;
259
159k
    ptr_blk_switch_right_ctrl->tot_grps_cnt = 1;
260
159k
    ptr_blk_switch_left_ctrl->group_len[0] = 1;
261
159k
    ptr_blk_switch_right_ctrl->group_len[0] = 1;
262
263
1.27M
    for (i = 1; i < MAX_SHORT_WINDOWS; i++) {
264
1.11M
      ptr_blk_switch_left_ctrl->group_len[i] = 0;
265
1.11M
      ptr_blk_switch_right_ctrl->group_len[i] = 0;
266
1.11M
    }
267
159k
  } else { /* tns_data_short Blocks */
268
69.9k
    if (ptr_blk_switch_left_ctrl->max_win_energy > ptr_blk_switch_right_ctrl->max_win_energy) {
269
24.9k
      ptr_blk_switch_right_ctrl->tot_grps_cnt = ptr_blk_switch_left_ctrl->tot_grps_cnt;
270
121k
      for (i = 0; i < ptr_blk_switch_right_ctrl->tot_grps_cnt; i++) {
271
96.4k
        ptr_blk_switch_right_ctrl->group_len[i] = ptr_blk_switch_left_ctrl->group_len[i];
272
96.4k
      }
273
45.0k
    } else {
274
45.0k
      ptr_blk_switch_left_ctrl->tot_grps_cnt = ptr_blk_switch_right_ctrl->tot_grps_cnt;
275
218k
      for (i = 0; i < ptr_blk_switch_left_ctrl->tot_grps_cnt; i++) {
276
173k
        ptr_blk_switch_left_ctrl->group_len[i] = ptr_blk_switch_right_ctrl->group_len[i];
277
173k
      }
278
45.0k
    }
279
69.9k
  }
280
281
229k
  return;
282
229k
}