Coverage Report

Created: 2025-08-29 06:15

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