mirror of
https://github.com/ittiam-systems/libxaac.git
synced 2026-04-02 20:30:47 +07:00
282 lines
9.4 KiB
C
282 lines
9.4 KiB
C
/******************************************************************************
|
|
* *
|
|
* Copyright (C) 2023 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*****************************************************************************
|
|
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
|
|
*/
|
|
|
|
#include "iusace_type_def.h"
|
|
#include "ixheaace_mps_common_define.h"
|
|
#include "iusace_cnst.h"
|
|
#include "iusace_block_switch_const.h"
|
|
#include "iusace_block_switch_struct_def.h"
|
|
#include "iusace_rom.h"
|
|
|
|
static FLOAT32 iusace_fmult(FLOAT32 a, FLOAT32 b) { return (a * b); }
|
|
|
|
static FLOAT32 iusace_fadd(FLOAT32 a, FLOAT32 b) { return (a + b); }
|
|
|
|
VOID iusace_init_block_switching(ia_block_switch_ctrl *pstr_blk_switch_ctrl,
|
|
const WORD32 bit_rate, const WORD32 num_chans) {
|
|
WORD32 i, w;
|
|
|
|
if ((num_chans == 1 && bit_rate > 24000) || (num_chans > 1 && bit_rate / num_chans > 16000)) {
|
|
pstr_blk_switch_ctrl->inv_attack_ratio = INV_ATTACK_RATIO_HIGH_BR;
|
|
} else {
|
|
pstr_blk_switch_ctrl->inv_attack_ratio = INV_ATTACK_RATIO_LOW_BR;
|
|
}
|
|
|
|
for (i = 0; i < BLK_SWITCH_FILT_LEN; i++) {
|
|
pstr_blk_switch_ctrl->iir_states[i] = 0;
|
|
}
|
|
|
|
/* Clear Filtered Window Energies */
|
|
for (w = 0; w < MAX_SHORT_WINDOWS; w++) {
|
|
pstr_blk_switch_ctrl->win_energy_filt[0][w] = 0;
|
|
pstr_blk_switch_ctrl->win_energy_filt[1][w] = 0;
|
|
pstr_blk_switch_ctrl->win_energy[0][w] = 0;
|
|
pstr_blk_switch_ctrl->win_energy[1][w] = 0;
|
|
}
|
|
pstr_blk_switch_ctrl->acc_win_energy = 0;
|
|
|
|
pstr_blk_switch_ctrl->window_seq = ONLY_LONG_SEQUENCE;
|
|
pstr_blk_switch_ctrl->next_win_seq = ONLY_LONG_SEQUENCE;
|
|
|
|
pstr_blk_switch_ctrl->attack = 0;
|
|
pstr_blk_switch_ctrl->lastattack = 0;
|
|
pstr_blk_switch_ctrl->attack_idx = 0;
|
|
pstr_blk_switch_ctrl->last_attack_idx = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
static FLOAT32 iusace_srch_max_with_idx(const FLOAT32 *ptr_in, WORD32 *index) {
|
|
FLOAT32 max;
|
|
WORD32 i, idx;
|
|
|
|
max = 0;
|
|
idx = 0;
|
|
|
|
for (i = 0; i < MAX_SHORT_WINDOWS; i++) {
|
|
if (ptr_in[i + 1] > max) {
|
|
max = ptr_in[i + 1];
|
|
idx = i;
|
|
}
|
|
}
|
|
*index = idx;
|
|
|
|
return max;
|
|
}
|
|
|
|
static VOID iusace_blk_switch_iir_filt(const FLOAT32 *ptr_in, const FLOAT32 *ptr_iir_coeff,
|
|
const WORD32 w, FLOAT32 *ptr_iir_states,
|
|
FLOAT32 *energy_accu, WORD32 block_len) {
|
|
FLOAT32 accu1;
|
|
|
|
WORD32 i;
|
|
|
|
FLOAT32 accu_unfilt = 0.0f;
|
|
FLOAT32 accu_filt = 0.0f;
|
|
FLOAT32 accu2, temp2, temp1;
|
|
|
|
FLOAT32 state0 = ptr_iir_states[0];
|
|
FLOAT32 state1 = ptr_iir_states[1];
|
|
|
|
FLOAT32 coeff0 = ptr_iir_coeff[0];
|
|
FLOAT32 coeff1 = ptr_iir_coeff[1];
|
|
|
|
const FLOAT32 *p_time_signal = &ptr_in[(block_len * w)];
|
|
|
|
for (i = 0; i < block_len; i++) {
|
|
accu2 = iusace_fmult(state0, coeff1);
|
|
accu1 = iusace_fmult(state1, coeff0);
|
|
accu1 += accu2;
|
|
|
|
state0 = p_time_signal[i];
|
|
state1 = iusace_fmult(state0, coeff1);
|
|
state1 = (state1 - accu1);
|
|
|
|
temp1 = iusace_fmult(state0, state0);
|
|
temp2 = iusace_fmult(state1, state1);
|
|
|
|
accu_unfilt = iusace_fadd(accu_unfilt, temp1);
|
|
accu_filt = iusace_fadd(accu_filt, temp2);
|
|
}
|
|
|
|
energy_accu[0] = accu_unfilt;
|
|
energy_accu[1] = accu_filt;
|
|
|
|
ptr_iir_states[0] = state0;
|
|
ptr_iir_states[1] = state1;
|
|
|
|
return;
|
|
}
|
|
|
|
static VOID iusace_calc_window_energy(ia_block_switch_ctrl *ptr_blk_switch_ctrl,
|
|
const FLOAT32 *ptr_in, FLOAT32 *max, WORD32 ccfl) {
|
|
WORD32 w;
|
|
|
|
FLOAT32 energy_accu[2];
|
|
*max = 0.0f;
|
|
|
|
for (w = 0; w < MAX_SHORT_WINDOWS; w++) {
|
|
// block length for calculating energy is corecoder frame length / MAX_SHORT_WINDOWS
|
|
iusace_blk_switch_iir_filt(ptr_in, iusace_iir_hipass_coeffs, w,
|
|
ptr_blk_switch_ctrl->iir_states, &energy_accu[0], ccfl >> 3);
|
|
|
|
ptr_blk_switch_ctrl->win_energy[1][w] = energy_accu[0];
|
|
ptr_blk_switch_ctrl->win_energy_filt[1][w] = energy_accu[1];
|
|
|
|
if (ptr_blk_switch_ctrl->win_energy_filt[1][w] > *max)
|
|
*max = ptr_blk_switch_ctrl->win_energy_filt[1][w];
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID iusace_block_switching(ia_block_switch_ctrl *ptr_blk_switch_ctrl, const FLOAT32 *ptr_in,
|
|
WORD32 ccfl) {
|
|
WORD32 i;
|
|
|
|
FLOAT32 temp1, temp2;
|
|
FLOAT32 max;
|
|
FLOAT32 energy, energy_max;
|
|
|
|
for (i = 0; i < MAX_SHORT_WINDOWS; i++) {
|
|
ptr_blk_switch_ctrl->group_len[i] = 0;
|
|
}
|
|
|
|
ptr_blk_switch_ctrl->max_win_energy =
|
|
iusace_srch_max_with_idx(&ptr_blk_switch_ctrl->win_energy[0][MAX_SHORT_WINDOWS - 1],
|
|
&ptr_blk_switch_ctrl->attack_idx);
|
|
|
|
ptr_blk_switch_ctrl->attack_idx = ptr_blk_switch_ctrl->last_attack_idx;
|
|
ptr_blk_switch_ctrl->tot_grps_cnt = MAXIMUM_NO_OF_GROUPS;
|
|
|
|
for (i = 0; i < MAXIMUM_NO_OF_GROUPS; i++) {
|
|
ptr_blk_switch_ctrl->group_len[i] =
|
|
iusace_suggested_grouping_table[ptr_blk_switch_ctrl->attack_idx][i];
|
|
}
|
|
|
|
for (i = 0; i < MAX_SHORT_WINDOWS; i++) {
|
|
ptr_blk_switch_ctrl->win_energy[0][i] = ptr_blk_switch_ctrl->win_energy[1][i];
|
|
ptr_blk_switch_ctrl->win_energy_filt[0][i] = ptr_blk_switch_ctrl->win_energy_filt[1][i];
|
|
}
|
|
|
|
iusace_calc_window_energy(ptr_blk_switch_ctrl, ptr_in, &max, ccfl);
|
|
|
|
ptr_blk_switch_ctrl->attack = FALSE;
|
|
|
|
energy_max = 0.0f;
|
|
|
|
energy = ptr_blk_switch_ctrl->win_energy_filt[0][MAX_SHORT_WINDOWS - 1];
|
|
|
|
for (i = 0; i < MAX_SHORT_WINDOWS; i++) {
|
|
temp1 = iusace_fmult(ONE_MINUS_ACC_WINDOW_NRG_FAC, ptr_blk_switch_ctrl->acc_win_energy);
|
|
temp2 = iusace_fmult(ACC_WINDOW_NRG_FAC, energy);
|
|
ptr_blk_switch_ctrl->acc_win_energy = iusace_fadd(temp1, temp2);
|
|
|
|
temp1 = iusace_fmult(ptr_blk_switch_ctrl->win_energy_filt[1][i],
|
|
ptr_blk_switch_ctrl->inv_attack_ratio);
|
|
if (temp1 > ptr_blk_switch_ctrl->acc_win_energy) {
|
|
ptr_blk_switch_ctrl->attack = TRUE;
|
|
ptr_blk_switch_ctrl->last_attack_idx = i;
|
|
}
|
|
|
|
energy = ptr_blk_switch_ctrl->win_energy_filt[1][i];
|
|
if (energy_max < energy) energy_max = energy;
|
|
}
|
|
|
|
if (ccfl == LEN_SUPERFRAME_768) {
|
|
energy_max = (energy_max * 4) / 3.0f;
|
|
}
|
|
if (energy_max < USAC_MIN_ATTACK_NRG) {
|
|
ptr_blk_switch_ctrl->attack = FALSE;
|
|
}
|
|
|
|
if ((!ptr_blk_switch_ctrl->attack) && (ptr_blk_switch_ctrl->lastattack)) {
|
|
if (ptr_blk_switch_ctrl->attack_idx == MAX_SHORT_WINDOWS - 1) {
|
|
ptr_blk_switch_ctrl->attack = TRUE;
|
|
}
|
|
ptr_blk_switch_ctrl->lastattack = FALSE;
|
|
} else {
|
|
ptr_blk_switch_ctrl->lastattack = ptr_blk_switch_ctrl->attack;
|
|
}
|
|
ptr_blk_switch_ctrl->window_seq = ptr_blk_switch_ctrl->next_win_seq;
|
|
|
|
if (ptr_blk_switch_ctrl->attack) {
|
|
ptr_blk_switch_ctrl->next_win_seq = EIGHT_SHORT_SEQUENCE;
|
|
} else {
|
|
ptr_blk_switch_ctrl->next_win_seq = ONLY_LONG_SEQUENCE;
|
|
}
|
|
if (ptr_blk_switch_ctrl->next_win_seq == EIGHT_SHORT_SEQUENCE) {
|
|
if (ptr_blk_switch_ctrl->window_seq == ONLY_LONG_SEQUENCE) {
|
|
ptr_blk_switch_ctrl->window_seq = LONG_START_SEQUENCE;
|
|
}
|
|
|
|
if (ptr_blk_switch_ctrl->window_seq == LONG_STOP_SEQUENCE) {
|
|
ptr_blk_switch_ctrl->window_seq = EIGHT_SHORT_SEQUENCE;
|
|
ptr_blk_switch_ctrl->tot_grps_cnt = 3;
|
|
ptr_blk_switch_ctrl->group_len[0] = 3;
|
|
ptr_blk_switch_ctrl->group_len[1] = 3;
|
|
ptr_blk_switch_ctrl->group_len[2] = 2;
|
|
}
|
|
}
|
|
|
|
if (ptr_blk_switch_ctrl->next_win_seq == ONLY_LONG_SEQUENCE) {
|
|
if (ptr_blk_switch_ctrl->window_seq == EIGHT_SHORT_SEQUENCE) {
|
|
ptr_blk_switch_ctrl->next_win_seq = LONG_STOP_SEQUENCE;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID iusace_sync_block_switching(ia_block_switch_ctrl *ptr_blk_switch_left_ctrl,
|
|
ia_block_switch_ctrl *ptr_blk_switch_right_ctrl) {
|
|
WORD32 i;
|
|
WORD32 patch_type = ONLY_LONG_SEQUENCE;
|
|
|
|
patch_type = iusace_synchronized_block_types[patch_type][ptr_blk_switch_left_ctrl->window_seq];
|
|
patch_type = iusace_synchronized_block_types[patch_type][ptr_blk_switch_right_ctrl->window_seq];
|
|
|
|
ptr_blk_switch_left_ctrl->window_seq = patch_type;
|
|
ptr_blk_switch_right_ctrl->window_seq = patch_type;
|
|
|
|
if (patch_type != EIGHT_SHORT_SEQUENCE) { /* tns_data_long Blocks */
|
|
ptr_blk_switch_left_ctrl->tot_grps_cnt = 1;
|
|
ptr_blk_switch_right_ctrl->tot_grps_cnt = 1;
|
|
ptr_blk_switch_left_ctrl->group_len[0] = 1;
|
|
ptr_blk_switch_right_ctrl->group_len[0] = 1;
|
|
|
|
for (i = 1; i < MAX_SHORT_WINDOWS; i++) {
|
|
ptr_blk_switch_left_ctrl->group_len[i] = 0;
|
|
ptr_blk_switch_right_ctrl->group_len[i] = 0;
|
|
}
|
|
} else { /* tns_data_short Blocks */
|
|
if (ptr_blk_switch_left_ctrl->max_win_energy > ptr_blk_switch_right_ctrl->max_win_energy) {
|
|
ptr_blk_switch_right_ctrl->tot_grps_cnt = ptr_blk_switch_left_ctrl->tot_grps_cnt;
|
|
for (i = 0; i < ptr_blk_switch_right_ctrl->tot_grps_cnt; i++) {
|
|
ptr_blk_switch_right_ctrl->group_len[i] = ptr_blk_switch_left_ctrl->group_len[i];
|
|
}
|
|
} else {
|
|
ptr_blk_switch_left_ctrl->tot_grps_cnt = ptr_blk_switch_right_ctrl->tot_grps_cnt;
|
|
for (i = 0; i < ptr_blk_switch_left_ctrl->tot_grps_cnt; i++) {
|
|
ptr_blk_switch_left_ctrl->group_len[i] = ptr_blk_switch_right_ctrl->group_len[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|