Coverage Report

Created: 2026-06-10 06:29

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