These changes handle the global-buffer-overflow runtime error reported when the tonal difference in the SBR module becomes zero. Bug: ossFuzz: 62261 Test: poc in bug
747 lines
27 KiB
C
747 lines
27 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 <string.h>
|
|
#include <math.h>
|
|
#include <float.h>
|
|
#include "ixheaac_type_def.h"
|
|
#include "ixheaac_constants.h"
|
|
#include "ixheaac_error_standards.h"
|
|
#include "ixheaace_aac_constants.h"
|
|
#include "ixheaac_basic_ops32.h"
|
|
#include "ixheaac_basic_ops16.h"
|
|
#include "ixheaac_basic_ops40.h"
|
|
#include "ixheaac_basic_ops.h"
|
|
|
|
#include "ixheaace_sbr_header.h"
|
|
#include "ixheaace_sbr_def.h"
|
|
#include "ixheaace_resampler.h"
|
|
#include "ixheaace_sbr_rom.h"
|
|
#include "ixheaace_common_rom.h"
|
|
#include "ixheaace_sbr_hbe.h"
|
|
#include "ixheaace_sbr_qmf_enc.h"
|
|
#include "ixheaace_sbr_tran_det.h"
|
|
#include "ixheaace_sbr_frame_info_gen.h"
|
|
#include "ixheaace_sbr_env_est.h"
|
|
#include "ixheaace_sbr_code_envelope.h"
|
|
#include "ixheaace_sbr_main.h"
|
|
#include "ixheaace_sbr_missing_harmonics_det.h"
|
|
#include "ixheaace_sbr_inv_filtering_estimation.h"
|
|
#include "ixheaace_sbr_noise_floor_est.h"
|
|
|
|
#include "ixheaace_sbr_ton_corr.h"
|
|
#include "iusace_esbr_pvc.h"
|
|
#include "iusace_esbr_inter_tes.h"
|
|
#include "ixheaace_sbr.h"
|
|
#include "ixheaace_common_utils.h"
|
|
|
|
static VOID ia_enhaacplus_enc_diff(FLOAT32 *ptr_tonal_orig, FLOAT32 *ptr_diff_map_2_scfb,
|
|
const UWORD8 *ptr_freq_band_tab, WORD32 n_scfb,
|
|
WORD8 *ptr_idx_vx) {
|
|
WORD32 i, ll, lu, k;
|
|
FLOAT32 max_val_orig, max_val_sbr;
|
|
for (i = 0; i < n_scfb; i++) {
|
|
ll = ptr_freq_band_tab[i];
|
|
lu = ptr_freq_band_tab[i + 1];
|
|
max_val_orig = max_val_sbr = 0;
|
|
|
|
for (k = ll; k < lu; k++) {
|
|
if (ptr_tonal_orig[k] > max_val_orig) {
|
|
max_val_orig = ptr_tonal_orig[k];
|
|
}
|
|
if (ptr_tonal_orig[ptr_idx_vx[k]] > max_val_sbr) {
|
|
max_val_sbr = ptr_tonal_orig[ptr_idx_vx[k]];
|
|
}
|
|
}
|
|
|
|
ptr_diff_map_2_scfb[i] = (max_val_sbr > 1) ? max_val_orig / max_val_sbr : max_val_orig;
|
|
}
|
|
}
|
|
|
|
static VOID ia_enhaacplus_enc_calculate_flatness_measure(FLOAT32 *ptr_quota_buf,
|
|
WORD8 *ptr_idx_vx, FLOAT32 *ptr_sfm_orig,
|
|
FLOAT32 *ptr_sfm_sbr,
|
|
const UWORD8 *ptr_freq_band_tab,
|
|
WORD32 num_sfb) {
|
|
WORD32 i, j;
|
|
|
|
FLOAT32 am_org, am_transp, gm_org, gm_transp, sfm_org, sfm_transp;
|
|
|
|
i = 0;
|
|
while (i < num_sfb) {
|
|
WORD32 band_low = ptr_freq_band_tab[i];
|
|
WORD32 band_high = ptr_freq_band_tab[i + 1];
|
|
|
|
ptr_sfm_orig[i] = 1.0f;
|
|
ptr_sfm_sbr[i] = 1.0f;
|
|
|
|
if (band_high - band_low > 1) {
|
|
am_org = 0;
|
|
am_transp = 0;
|
|
gm_org = 1.0f;
|
|
gm_transp = 1.0f;
|
|
|
|
for (j = band_low; j < band_high; j++) {
|
|
sfm_org = ptr_quota_buf[j];
|
|
sfm_transp = ptr_quota_buf[ptr_idx_vx[j]];
|
|
|
|
am_org += sfm_org;
|
|
gm_org += sfm_org;
|
|
am_transp += sfm_transp;
|
|
gm_transp += sfm_transp;
|
|
}
|
|
|
|
am_org /= band_high - band_low;
|
|
am_transp /= band_high - band_low;
|
|
gm_org = (FLOAT32)pow(gm_org, 1.0f / (band_high - band_low));
|
|
gm_transp = (FLOAT32)pow(gm_transp, 1.0f / (band_high - band_low));
|
|
|
|
if (am_org) {
|
|
ptr_sfm_orig[i] = gm_org / am_org;
|
|
}
|
|
|
|
if (am_transp) {
|
|
ptr_sfm_sbr[i] = gm_transp / am_transp;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
static VOID ia_enhaacplus_enc_calculate_detector_input(
|
|
FLOAT32 **ptr_quota_buf, WORD8 *ptr_idx_vx, FLOAT32 **ptr_tonal_diff, FLOAT32 **ptr_sfm_orig,
|
|
FLOAT32 **ptr_sfm_sbr, const UWORD8 *ptr_freq_band_tab, WORD32 num_sfb,
|
|
WORD32 no_est_per_frame, WORD32 move, WORD32 no_qmf_bands) {
|
|
WORD32 est;
|
|
|
|
for (est = 0; est < move; est++) {
|
|
memcpy(ptr_tonal_diff[est], ptr_tonal_diff[est + no_est_per_frame],
|
|
no_qmf_bands * sizeof(ptr_tonal_diff[est][0]));
|
|
|
|
memcpy(ptr_sfm_orig[est], ptr_sfm_orig[est + no_est_per_frame],
|
|
no_qmf_bands * sizeof(ptr_sfm_orig[est][0]));
|
|
|
|
memcpy(ptr_sfm_sbr[est], ptr_sfm_sbr[est + no_est_per_frame],
|
|
no_qmf_bands * sizeof(ptr_sfm_sbr[est][0]));
|
|
}
|
|
|
|
for (est = 0; est < no_est_per_frame; est++) {
|
|
ia_enhaacplus_enc_diff(ptr_quota_buf[est + move], ptr_tonal_diff[est + move],
|
|
ptr_freq_band_tab, num_sfb, ptr_idx_vx);
|
|
|
|
ia_enhaacplus_enc_calculate_flatness_measure(
|
|
ptr_quota_buf[est + move], ptr_idx_vx, ptr_sfm_orig[est + move], ptr_sfm_sbr[est + move],
|
|
ptr_freq_band_tab, num_sfb);
|
|
}
|
|
}
|
|
|
|
static WORD32 ia_enhaacplus_enc_isDetectionOfNewToneAllowed(
|
|
const ixheaace_str_frame_info_sbr *ptr_frame_info, WORD32 prev_transient_frame,
|
|
WORD32 prev_transient_pos, WORD32 prev_trans_flag, WORD32 trans_pos_offset,
|
|
WORD32 transient_flag, WORD32 transient_pos,
|
|
ixheaace_pstr_sbr_missing_harmonics_detector pstr_sbr_missing_harmonics_detector) {
|
|
WORD32 transient_frame, new_detection_allowed;
|
|
|
|
transient_frame = 0;
|
|
|
|
if (transient_flag) {
|
|
if (transient_pos + trans_pos_offset < ptr_frame_info->borders[ptr_frame_info->n_envelopes]) {
|
|
transient_frame = 1;
|
|
}
|
|
} else {
|
|
if (prev_trans_flag && !prev_transient_frame) {
|
|
transient_frame = 1;
|
|
}
|
|
}
|
|
|
|
new_detection_allowed = 0;
|
|
|
|
if (transient_frame) {
|
|
new_detection_allowed = 1;
|
|
} else {
|
|
if (prev_transient_frame &&
|
|
ixheaac_abs32(ptr_frame_info->borders[0] -
|
|
(prev_transient_pos + trans_pos_offset -
|
|
pstr_sbr_missing_harmonics_detector->time_slots)) < DELTA_TIME) {
|
|
new_detection_allowed = 1;
|
|
}
|
|
}
|
|
|
|
pstr_sbr_missing_harmonics_detector->prev_trans_flag = transient_flag;
|
|
pstr_sbr_missing_harmonics_detector->prev_trans_frame = transient_frame;
|
|
pstr_sbr_missing_harmonics_detector->prev_trans_pos = transient_pos;
|
|
|
|
return (new_detection_allowed);
|
|
}
|
|
|
|
static VOID ia_enhaacplus_enc_transient_cleanup(FLOAT32 **ptr_quota_buf, WORD32 num_sfb,
|
|
UWORD8 **ptr_detection_vectors,
|
|
const UWORD8 *ptr_freq_band_tab,
|
|
ixheaace_str_guide_vectors ptr_guide_vectors,
|
|
WORD32 start, WORD32 stop) {
|
|
WORD32 sfb, band, low_band, up_band, est;
|
|
|
|
UWORD8 ptr_harm_vec[MAXIMUM_FREQ_COEFFS];
|
|
|
|
memset(ptr_harm_vec, 0, sizeof(ptr_harm_vec));
|
|
|
|
for (est = start; est < stop; est++) {
|
|
for (sfb = 0; sfb < num_sfb - 1; sfb++) {
|
|
ptr_harm_vec[sfb] = ptr_harm_vec[sfb] || ptr_detection_vectors[est][sfb];
|
|
}
|
|
}
|
|
|
|
for (sfb = 0; sfb < num_sfb - 1; sfb++) {
|
|
if (ptr_harm_vec[sfb] && ptr_harm_vec[sfb + 1]) {
|
|
FLOAT32 max_val_1, max_val_2;
|
|
WORD32 maxPos1, maxPos2;
|
|
|
|
low_band = ptr_freq_band_tab[sfb];
|
|
up_band = ptr_freq_band_tab[sfb + 1];
|
|
maxPos1 = low_band;
|
|
|
|
max_val_1 = ptr_quota_buf[start][low_band];
|
|
for (band = low_band; band < up_band; band++) {
|
|
if (ptr_quota_buf[start][band] > max_val_1) {
|
|
max_val_1 = ptr_quota_buf[start][band];
|
|
maxPos1 = band;
|
|
}
|
|
}
|
|
|
|
for (est = start + 1; est < stop; est++) {
|
|
for (band = low_band; band < up_band; band++) {
|
|
if (ptr_quota_buf[est][band] > max_val_1) {
|
|
max_val_1 = ptr_quota_buf[est][band];
|
|
maxPos1 = band;
|
|
}
|
|
}
|
|
}
|
|
|
|
low_band = ptr_freq_band_tab[sfb + 1];
|
|
up_band = ptr_freq_band_tab[sfb + 2];
|
|
|
|
maxPos2 = low_band;
|
|
max_val_2 = ptr_quota_buf[start][low_band];
|
|
|
|
for (band = low_band; band < up_band; band++) {
|
|
if (ptr_quota_buf[start][band] > max_val_2) {
|
|
max_val_2 = ptr_quota_buf[start][band];
|
|
maxPos2 = band;
|
|
}
|
|
}
|
|
|
|
for (est = start + 1; est < stop; est++) {
|
|
for (band = low_band; band < up_band; band++) {
|
|
if (ptr_quota_buf[est][band] > max_val_2) {
|
|
max_val_2 = ptr_quota_buf[est][band];
|
|
maxPos2 = band;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (maxPos2 - maxPos1 < 2) {
|
|
if (max_val_1 > max_val_2) {
|
|
ptr_guide_vectors.ptr_guide_vector_detected[sfb + 1] = 0;
|
|
ptr_guide_vectors.ptr_guide_vec_orig[sfb + 1] = 0;
|
|
ptr_guide_vectors.ptr_guide_vec_diff[sfb + 1] = 0;
|
|
|
|
for (est = start; est < stop; est++) {
|
|
ptr_detection_vectors[est][sfb + 1] = 0;
|
|
}
|
|
} else {
|
|
ptr_guide_vectors.ptr_guide_vector_detected[sfb] = 0;
|
|
ptr_guide_vectors.ptr_guide_vec_diff[sfb] = 0;
|
|
ptr_guide_vectors.ptr_guide_vec_orig[sfb] = 0;
|
|
|
|
for (est = start; est < stop; est++) {
|
|
ptr_detection_vectors[est][sfb] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static VOID ia_enhaacplus_enc_detection(FLOAT32 *ptr_quota_buf, FLOAT32 *ptr_diff_vec_scfb,
|
|
WORD32 num_sfb, UWORD8 *ptr_harm_vec,
|
|
const UWORD8 *ptr_freq_band_tab, FLOAT32 *ptr_sfm_orig,
|
|
FLOAT32 *ptr_sfm_sbr,
|
|
ixheaace_str_guide_vectors *ptr_guide_vectors,
|
|
ixheaace_str_guide_vectors *ptr_new_guide_vectors) {
|
|
WORD32 i, j;
|
|
WORD32 lower_band, upper_band;
|
|
FLOAT32 thr, thr_org;
|
|
|
|
for (i = 0; i < num_sfb; i++) {
|
|
if (ptr_guide_vectors->ptr_guide_vec_diff[i]) {
|
|
if (SBR_DECAY_GUIDE_DIFF * ptr_guide_vectors->ptr_guide_vec_diff[i] > SBR_THR_DIFF_GUIDE) {
|
|
thr = SBR_DECAY_GUIDE_DIFF * ptr_guide_vectors->ptr_guide_vec_diff[i];
|
|
} else {
|
|
thr = SBR_THR_DIFF_GUIDE;
|
|
}
|
|
if (thr > SBR_THR_DIFF) {
|
|
thr = SBR_THR_DIFF;
|
|
}
|
|
} else {
|
|
thr = SBR_THR_DIFF;
|
|
}
|
|
|
|
if (ptr_diff_vec_scfb[i] > thr) {
|
|
ptr_harm_vec[i] = 1;
|
|
ptr_new_guide_vectors->ptr_guide_vec_diff[i] = ptr_diff_vec_scfb[i];
|
|
} else {
|
|
if (ptr_guide_vectors->ptr_guide_vec_diff[i]) {
|
|
ptr_guide_vectors->ptr_guide_vec_orig[i] = SBR_THR_TONE_GUIDE;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < num_sfb; i++) {
|
|
lower_band = ptr_freq_band_tab[i];
|
|
upper_band = ptr_freq_band_tab[i + 1];
|
|
|
|
if (ptr_guide_vectors->ptr_guide_vec_orig[i] * SBR_DECAY_GUIDE_ORIG > SBR_THR_TONE_GUIDE) {
|
|
thr_org = ptr_guide_vectors->ptr_guide_vec_orig[i] * SBR_DECAY_GUIDE_ORIG;
|
|
} else {
|
|
thr_org = SBR_THR_TONE_GUIDE;
|
|
}
|
|
if (thr_org > SBR_THR_TONE) {
|
|
thr_org = SBR_THR_TONE;
|
|
}
|
|
if (ptr_guide_vectors->ptr_guide_vec_orig[i]) {
|
|
for (j = lower_band; j < upper_band; j++) {
|
|
if (ptr_quota_buf[j] > thr_org) {
|
|
ptr_harm_vec[i] = 1;
|
|
ptr_new_guide_vectors->ptr_guide_vec_orig[i] = ptr_quota_buf[j];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
thr_org = SBR_THR_TONE;
|
|
|
|
for (i = 0; i < num_sfb; i++) {
|
|
lower_band = ptr_freq_band_tab[i];
|
|
upper_band = ptr_freq_band_tab[i + 1];
|
|
|
|
if (upper_band - lower_band > 1) {
|
|
for (j = lower_band; j < upper_band; j++) {
|
|
if (ptr_quota_buf[j] > thr_org && ptr_sfm_sbr[i] > SBR_THR_SFM_SBR &&
|
|
ptr_sfm_orig[i] > SBR_THR_SFM_ORG) {
|
|
ptr_harm_vec[i] = 1;
|
|
ptr_new_guide_vectors->ptr_guide_vec_orig[i] = ptr_quota_buf[j];
|
|
}
|
|
}
|
|
} else {
|
|
if (1 < (num_sfb - 1)) {
|
|
lower_band = ptr_freq_band_tab[i];
|
|
|
|
if (i > 0) {
|
|
if (ptr_quota_buf[lower_band] > SBR_THR_TONE &&
|
|
(ptr_diff_vec_scfb[i - 1] < SBR_INV_THR_TONE ||
|
|
ptr_diff_vec_scfb[i + 1] < SBR_INV_THR_TONE)) {
|
|
ptr_harm_vec[i] = 1;
|
|
ptr_new_guide_vectors->ptr_guide_vec_orig[i] = ptr_quota_buf[lower_band];
|
|
}
|
|
} else {
|
|
if (ptr_quota_buf[lower_band] > SBR_THR_TONE &&
|
|
ptr_diff_vec_scfb[i + 1] < SBR_INV_THR_TONE) {
|
|
ptr_harm_vec[i] = 1;
|
|
ptr_new_guide_vectors->ptr_guide_vec_orig[i] = ptr_quota_buf[lower_band];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static VOID ia_enhaacplus_enc_detection_with_prediction(
|
|
FLOAT32 **ptr_quota_buf, FLOAT32 **ptr_diff_vec_sfb, WORD32 num_sfb,
|
|
const UWORD8 *ptr_freq_band_tab, FLOAT32 **ptr_sfm_orig, FLOAT32 **ptr_sfm_sbr,
|
|
UWORD8 **ptr_detection_vectors, UWORD8 *ptr_prev_frame_sfb_harm,
|
|
ixheaace_str_guide_vectors *ptr_guide_vectors, WORD32 no_est_per_frame, WORD32 tot_no_est,
|
|
WORD32 new_detection_allowed, UWORD8 *ptr_add_harmonics_sfbs) {
|
|
WORD32 est = 0, i;
|
|
WORD32 start;
|
|
|
|
memset(ptr_add_harmonics_sfbs, 0, num_sfb * sizeof(ptr_add_harmonics_sfbs[0]));
|
|
|
|
if (new_detection_allowed) {
|
|
if (tot_no_est > 1) {
|
|
start = no_est_per_frame;
|
|
memcpy(ptr_guide_vectors[no_est_per_frame].ptr_guide_vec_diff,
|
|
ptr_guide_vectors[0].ptr_guide_vec_diff,
|
|
num_sfb * sizeof(ptr_guide_vectors[no_est_per_frame].ptr_guide_vec_diff[0]));
|
|
|
|
memcpy(ptr_guide_vectors[no_est_per_frame].ptr_guide_vec_orig,
|
|
ptr_guide_vectors[0].ptr_guide_vec_orig,
|
|
num_sfb * sizeof(ptr_guide_vectors[no_est_per_frame].ptr_guide_vec_orig[0]));
|
|
|
|
memset(
|
|
ptr_guide_vectors[no_est_per_frame - 1].ptr_guide_vector_detected, 0,
|
|
num_sfb * sizeof(ptr_guide_vectors[no_est_per_frame - 1].ptr_guide_vector_detected[0]));
|
|
} else {
|
|
start = 0;
|
|
}
|
|
} else {
|
|
start = 0;
|
|
}
|
|
|
|
for (est = start; est < tot_no_est; est++) {
|
|
if (est > 0) {
|
|
memcpy(ptr_guide_vectors[est].ptr_guide_vector_detected, ptr_detection_vectors[est - 1],
|
|
num_sfb * sizeof(ptr_guide_vectors[est].ptr_guide_vector_detected[0]));
|
|
}
|
|
|
|
memset(ptr_detection_vectors[est], 0, num_sfb * sizeof(ptr_detection_vectors[est][0]));
|
|
|
|
if (est < tot_no_est - 1) {
|
|
memset(ptr_guide_vectors[est + 1].ptr_guide_vec_diff, 0,
|
|
num_sfb * sizeof(ptr_guide_vectors[est + 1].ptr_guide_vec_diff[0]));
|
|
|
|
memset(ptr_guide_vectors[est + 1].ptr_guide_vec_orig, 0,
|
|
num_sfb * sizeof(ptr_guide_vectors[est + 1].ptr_guide_vec_orig[0]));
|
|
|
|
memset(ptr_guide_vectors[est + 1].ptr_guide_vector_detected, 0,
|
|
num_sfb * sizeof(ptr_guide_vectors[est + 1].ptr_guide_vector_detected[0]));
|
|
|
|
ia_enhaacplus_enc_detection(ptr_quota_buf[est], ptr_diff_vec_sfb[est], num_sfb,
|
|
ptr_detection_vectors[est], ptr_freq_band_tab,
|
|
ptr_sfm_orig[est], ptr_sfm_sbr[est], &(ptr_guide_vectors[est]),
|
|
&(ptr_guide_vectors[est + 1]));
|
|
} else {
|
|
memset(ptr_guide_vectors[est].ptr_guide_vec_diff, 0,
|
|
num_sfb * sizeof(ptr_guide_vectors[est].ptr_guide_vec_diff[0]));
|
|
|
|
memset(ptr_guide_vectors[est].ptr_guide_vec_orig, 0,
|
|
num_sfb * sizeof(ptr_guide_vectors[est].ptr_guide_vec_orig[0]));
|
|
|
|
memset(ptr_guide_vectors[est].ptr_guide_vector_detected, 0,
|
|
num_sfb * sizeof(ptr_guide_vectors[est].ptr_guide_vector_detected[0]));
|
|
|
|
ia_enhaacplus_enc_detection(ptr_quota_buf[est], ptr_diff_vec_sfb[est], num_sfb,
|
|
ptr_detection_vectors[est], ptr_freq_band_tab,
|
|
ptr_sfm_orig[est], ptr_sfm_sbr[est], &(ptr_guide_vectors[est]),
|
|
&(ptr_guide_vectors[est]));
|
|
}
|
|
}
|
|
|
|
if (new_detection_allowed) {
|
|
if (tot_no_est > 1) {
|
|
ia_enhaacplus_enc_transient_cleanup(ptr_quota_buf, num_sfb, ptr_detection_vectors,
|
|
ptr_freq_band_tab, ptr_guide_vectors[no_est_per_frame],
|
|
start, tot_no_est);
|
|
} else {
|
|
ia_enhaacplus_enc_transient_cleanup(ptr_quota_buf, num_sfb, ptr_detection_vectors,
|
|
ptr_freq_band_tab, ptr_guide_vectors[0], start,
|
|
tot_no_est);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < num_sfb; i++) {
|
|
for (est = start; est < tot_no_est; est++) {
|
|
ptr_add_harmonics_sfbs[i] = ptr_add_harmonics_sfbs[i] || ptr_detection_vectors[est][i];
|
|
}
|
|
}
|
|
|
|
if (!new_detection_allowed) {
|
|
for (i = 0; i < num_sfb; i++) {
|
|
if (ptr_add_harmonics_sfbs[i] - ptr_prev_frame_sfb_harm[i] > 0) {
|
|
ptr_add_harmonics_sfbs[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static VOID ia_enhaacplus_enc_calculate_comp_vector(
|
|
UWORD8 *ptr_add_harmonics_sfbs, FLOAT32 **ptr_tonality, WORD8 *ptr_env_compensation,
|
|
WORD32 num_sfb, const UWORD8 *ptr_freq_band_tab, FLOAT32 **ptr_diff, WORD32 tot_no_est,
|
|
WORD8 *ptr_prev_env_compensation, WORD32 new_detection_allowed) {
|
|
WORD32 i, j, l;
|
|
|
|
memset(ptr_env_compensation, 0, num_sfb * sizeof(ptr_env_compensation[0]));
|
|
|
|
FLOAT32 max_val;
|
|
WORD32 lower_band, upper_band;
|
|
WORD32 max_pos_band, max_pos_est;
|
|
WORD8 comp_val;
|
|
|
|
for (i = 0; i < num_sfb; i++) {
|
|
if (ptr_add_harmonics_sfbs[i]) {
|
|
lower_band = ptr_freq_band_tab[i];
|
|
upper_band = ptr_freq_band_tab[i + 1];
|
|
|
|
max_pos_band = 0;
|
|
max_pos_est = 0;
|
|
max_val = 0;
|
|
|
|
for (j = 0; j < tot_no_est; j++) {
|
|
for (l = lower_band; l < upper_band; l++) {
|
|
if (ptr_tonality[j][l] > max_val) {
|
|
max_val = ptr_tonality[j][l];
|
|
max_pos_band = l;
|
|
max_pos_est = j;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (max_pos_band == lower_band && i) {
|
|
comp_val =
|
|
(WORD8)(fabs(SBR_INV_LOG_2 * log(ptr_diff[max_pos_est][i - 1] + SBR_EPS)) + 0.5f);
|
|
if (comp_val > SBR_MAX_COMP) {
|
|
comp_val = SBR_MAX_COMP;
|
|
}
|
|
|
|
if (!ptr_add_harmonics_sfbs[i - 1]) {
|
|
if (ptr_tonality[max_pos_est][max_pos_band - 1] >
|
|
SBR_TONALITY_QUOTA * ptr_tonality[max_pos_est][max_pos_band]) {
|
|
ptr_env_compensation[i - 1] = -1 * comp_val;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (max_pos_band == (upper_band - 1) && (i + 1) < num_sfb) {
|
|
comp_val =
|
|
(WORD8)(fabs(SBR_INV_LOG_2 * log(ptr_diff[max_pos_est][i + 1] + SBR_EPS)) + 0.5f);
|
|
if (comp_val > SBR_MAX_COMP) {
|
|
comp_val = SBR_MAX_COMP;
|
|
}
|
|
|
|
if (!ptr_add_harmonics_sfbs[i + 1]) {
|
|
if (ptr_tonality[max_pos_est][max_pos_band + 1] >
|
|
SBR_TONALITY_QUOTA * ptr_tonality[max_pos_est][max_pos_band]) {
|
|
ptr_env_compensation[i + 1] = comp_val;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (i && i < (num_sfb - 1)) {
|
|
comp_val =
|
|
(WORD8)(fabs(SBR_INV_LOG_2 * log(ptr_diff[max_pos_est][i - 1] + SBR_EPS)) + 0.5f);
|
|
if (comp_val > SBR_MAX_COMP) {
|
|
comp_val = SBR_MAX_COMP;
|
|
}
|
|
|
|
if (ixheaace_div32((FLOAT32)1.0f, ptr_diff[max_pos_est][i - 1]) >
|
|
(SBR_DIFF_QUOTA * ptr_diff[max_pos_est][i])) {
|
|
ptr_env_compensation[i - 1] = -1 * comp_val;
|
|
}
|
|
|
|
comp_val =
|
|
(WORD8)(fabs(SBR_INV_LOG_2 * log(ptr_diff[max_pos_est][i + 1] + SBR_EPS)) + 0.5f);
|
|
if (comp_val > SBR_MAX_COMP) {
|
|
comp_val = SBR_MAX_COMP;
|
|
}
|
|
|
|
if (ixheaace_div32((FLOAT32)1.0f, ptr_diff[max_pos_est][i + 1]) >
|
|
(SBR_DIFF_QUOTA * ptr_diff[max_pos_est][i])) {
|
|
ptr_env_compensation[i + 1] = comp_val;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!new_detection_allowed) {
|
|
for (i = 0; i < num_sfb; i++) {
|
|
if (ptr_env_compensation[i] != 0 && ptr_prev_env_compensation[i] == 0) {
|
|
ptr_env_compensation[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID ixheaace_sbr_missing_harmonics_detector_qmf(
|
|
ixheaace_pstr_sbr_missing_harmonics_detector pstr_sbr_mhd_et, FLOAT32 **ptr_quota_buf,
|
|
WORD8 *ptr_idx_vx, const ixheaace_str_frame_info_sbr *ptr_frame_info,
|
|
const WORD32 *ptr_tran_info, WORD32 *ptr_add_harmonics_flag, UWORD8 *ptr_add_harmonics_sfbs,
|
|
const UWORD8 *ptr_freq_band_tab, WORD32 num_sfb, WORD8 *ptr_env_compensation) {
|
|
WORD32 i;
|
|
WORD32 transient_flag = ptr_tran_info[1];
|
|
WORD32 transient_pos = ptr_tran_info[0];
|
|
WORD32 new_detection_allowed;
|
|
|
|
UWORD8 **ptr_detection_vectors = pstr_sbr_mhd_et->ptr_detection_vectors;
|
|
WORD32 move = pstr_sbr_mhd_et->move;
|
|
WORD32 no_est_per_frame = pstr_sbr_mhd_et->no_est_per_frame;
|
|
WORD32 tot_no_est = pstr_sbr_mhd_et->tot_no_est;
|
|
WORD32 prev_trans_flag = pstr_sbr_mhd_et->prev_trans_flag;
|
|
WORD32 prev_transient_frame = pstr_sbr_mhd_et->prev_trans_frame;
|
|
WORD32 trans_pos_offset = pstr_sbr_mhd_et->trans_pos_offset;
|
|
WORD32 prev_transient_pos = pstr_sbr_mhd_et->prev_trans_pos;
|
|
ixheaace_str_guide_vectors *ptr_guide_vectors = pstr_sbr_mhd_et->guide_vectors;
|
|
|
|
FLOAT32 **ptr_sfm_sbr = pstr_sbr_mhd_et->ptr_sfm_sbr;
|
|
FLOAT32 **ptr_sfm_orig = pstr_sbr_mhd_et->ptr_sfm_orig;
|
|
FLOAT32 **ptr_tonal_diff = pstr_sbr_mhd_et->ptr_tonal_diff;
|
|
|
|
WORD32 no_qmf_bands = ptr_freq_band_tab[num_sfb] - ptr_freq_band_tab[0];
|
|
|
|
new_detection_allowed = ia_enhaacplus_enc_isDetectionOfNewToneAllowed(
|
|
ptr_frame_info, prev_transient_frame, prev_transient_pos, prev_trans_flag, trans_pos_offset,
|
|
transient_flag, transient_pos, pstr_sbr_mhd_et);
|
|
|
|
ia_enhaacplus_enc_calculate_detector_input(ptr_quota_buf, ptr_idx_vx, ptr_tonal_diff,
|
|
ptr_sfm_orig, ptr_sfm_sbr, ptr_freq_band_tab,
|
|
num_sfb, no_est_per_frame, move, no_qmf_bands);
|
|
|
|
ia_enhaacplus_enc_detection_with_prediction(
|
|
ptr_quota_buf, ptr_tonal_diff, num_sfb, ptr_freq_band_tab, ptr_sfm_orig, ptr_sfm_sbr,
|
|
ptr_detection_vectors, pstr_sbr_mhd_et->ptr_guide_scfb, ptr_guide_vectors, no_est_per_frame,
|
|
tot_no_est, new_detection_allowed, ptr_add_harmonics_sfbs);
|
|
|
|
ia_enhaacplus_enc_calculate_comp_vector(
|
|
ptr_add_harmonics_sfbs, ptr_quota_buf, ptr_env_compensation, num_sfb, ptr_freq_band_tab,
|
|
ptr_tonal_diff, tot_no_est, pstr_sbr_mhd_et->sbr_prev_env_compensation,
|
|
new_detection_allowed);
|
|
|
|
*ptr_add_harmonics_flag = 0;
|
|
|
|
for (i = 0; i < num_sfb; i++) {
|
|
if (ptr_add_harmonics_sfbs[i]) {
|
|
*ptr_add_harmonics_flag = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
memcpy(pstr_sbr_mhd_et->sbr_prev_env_compensation, ptr_env_compensation,
|
|
num_sfb * sizeof(pstr_sbr_mhd_et->sbr_prev_env_compensation[0]));
|
|
|
|
memcpy(pstr_sbr_mhd_et->ptr_guide_scfb, ptr_add_harmonics_sfbs,
|
|
num_sfb * sizeof(pstr_sbr_mhd_et->ptr_guide_scfb[0]));
|
|
|
|
memcpy(ptr_guide_vectors[0].ptr_guide_vector_detected, ptr_add_harmonics_sfbs,
|
|
num_sfb * sizeof(ptr_guide_vectors[0].ptr_guide_vector_detected[0]));
|
|
|
|
if (tot_no_est > no_est_per_frame) {
|
|
memcpy(ptr_guide_vectors[0].ptr_guide_vec_diff,
|
|
ptr_guide_vectors[no_est_per_frame].ptr_guide_vec_diff,
|
|
num_sfb * sizeof(ptr_guide_vectors[0].ptr_guide_vec_diff[0]));
|
|
memcpy(ptr_guide_vectors[0].ptr_guide_vec_orig,
|
|
ptr_guide_vectors[no_est_per_frame].ptr_guide_vec_orig,
|
|
num_sfb * sizeof(ptr_guide_vectors[0].ptr_guide_vec_orig[0]));
|
|
} else {
|
|
memcpy(ptr_guide_vectors[0].ptr_guide_vec_diff,
|
|
ptr_guide_vectors[no_est_per_frame - 1].ptr_guide_vec_diff,
|
|
num_sfb * sizeof(ptr_guide_vectors[0].ptr_guide_vec_diff[0]));
|
|
|
|
memcpy(ptr_guide_vectors[0].ptr_guide_vec_orig,
|
|
ptr_guide_vectors[no_est_per_frame - 1].ptr_guide_vec_orig,
|
|
num_sfb * sizeof(ptr_guide_vectors[0].ptr_guide_vec_orig[0]));
|
|
}
|
|
|
|
for (i = 0; i < num_sfb; i++) {
|
|
#ifdef _WIN32
|
|
#pragma warning(suppress : 6385)
|
|
#endif
|
|
if ((ptr_guide_vectors[0].ptr_guide_vec_diff[i] ||
|
|
ptr_guide_vectors[0].ptr_guide_vec_orig[i]) &&
|
|
!ptr_add_harmonics_sfbs[i]) {
|
|
ptr_guide_vectors[0].ptr_guide_vec_diff[i] = 0;
|
|
ptr_guide_vectors[0].ptr_guide_vec_orig[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID ixheaace_create_sbr_missing_harmonics_detector(
|
|
WORD32 ch, ixheaace_pstr_sbr_missing_harmonics_detector pstr_sbr_mhdet, WORD32 sample_freq,
|
|
WORD32 num_sfb, WORD32 qmf_num_ch, WORD32 tot_no_est, WORD32 move, WORD32 no_est_per_frame,
|
|
WORD32 *ptr_common_buffer) {
|
|
WORD32 i;
|
|
WORD32 *ptr_fix;
|
|
FLOAT32 *ptr_mem;
|
|
ixheaace_pstr_sbr_missing_harmonics_detector pstr_sbr_detector_handle = pstr_sbr_mhdet;
|
|
|
|
memset(pstr_sbr_detector_handle, 0, sizeof(ixheaace_str_sbr_missing_har_detector));
|
|
|
|
pstr_sbr_detector_handle->trans_pos_offset = 4;
|
|
pstr_sbr_detector_handle->time_slots = 16;
|
|
|
|
pstr_sbr_detector_handle->qmf_num_ch = qmf_num_ch;
|
|
pstr_sbr_detector_handle->sample_freq = sample_freq;
|
|
pstr_sbr_detector_handle->num_scf = num_sfb;
|
|
|
|
pstr_sbr_detector_handle->tot_no_est = tot_no_est;
|
|
pstr_sbr_detector_handle->move = move;
|
|
pstr_sbr_detector_handle->no_est_per_frame = no_est_per_frame;
|
|
|
|
ptr_fix = &ptr_common_buffer[ch * 5 * NO_OF_ESTIMATES * MAXIMUM_FREQ_COEFFS];
|
|
ptr_mem = (FLOAT32 *)ptr_fix;
|
|
for (i = 0; i < tot_no_est; i++) {
|
|
pstr_sbr_detector_handle->ptr_tonal_diff[i] = ptr_mem;
|
|
ptr_mem += MAXIMUM_FREQ_COEFFS;
|
|
|
|
memset(pstr_sbr_detector_handle->ptr_tonal_diff[i], 0,
|
|
sizeof(pstr_sbr_detector_handle->ptr_tonal_diff[0][0]) * MAXIMUM_FREQ_COEFFS);
|
|
|
|
pstr_sbr_detector_handle->ptr_sfm_orig[i] = ptr_mem;
|
|
ptr_mem += MAXIMUM_FREQ_COEFFS;
|
|
|
|
memset(pstr_sbr_detector_handle->ptr_sfm_orig[i], 0,
|
|
sizeof(pstr_sbr_detector_handle->ptr_sfm_orig[0][0]) * MAXIMUM_FREQ_COEFFS);
|
|
|
|
pstr_sbr_detector_handle->ptr_sfm_sbr[i] = ptr_mem;
|
|
ptr_mem += MAXIMUM_FREQ_COEFFS;
|
|
|
|
memset(pstr_sbr_detector_handle->ptr_sfm_sbr[i], 0,
|
|
sizeof(pstr_sbr_detector_handle->ptr_sfm_sbr[0][0]) * MAXIMUM_FREQ_COEFFS);
|
|
|
|
pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vec_diff = ptr_mem;
|
|
ptr_mem += MAXIMUM_FREQ_COEFFS;
|
|
|
|
memset(pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vec_diff, 0,
|
|
sizeof(pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vec_diff[0]) *
|
|
MAXIMUM_FREQ_COEFFS);
|
|
|
|
pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vec_orig = ptr_mem;
|
|
ptr_mem += MAXIMUM_FREQ_COEFFS;
|
|
|
|
memset(pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vec_orig, 0,
|
|
sizeof(pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vec_orig[0]) *
|
|
MAXIMUM_FREQ_COEFFS);
|
|
|
|
pstr_sbr_detector_handle->ptr_detection_vectors[i] =
|
|
&(pstr_sbr_detector_handle->sbr_detection_vectors[i * MAXIMUM_FREQ_COEFFS]);
|
|
|
|
memset(pstr_sbr_detector_handle->ptr_detection_vectors[i], 0,
|
|
sizeof(pstr_sbr_detector_handle->ptr_detection_vectors[0][0]) * MAXIMUM_FREQ_COEFFS);
|
|
|
|
pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vector_detected =
|
|
&(pstr_sbr_detector_handle->sbr_guide_vector_detected[i * MAXIMUM_FREQ_COEFFS]);
|
|
|
|
memset(pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vector_detected, 0,
|
|
sizeof(pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vector_detected[0]) *
|
|
MAXIMUM_FREQ_COEFFS);
|
|
}
|
|
|
|
pstr_sbr_detector_handle->ptr_prev_env_compensation =
|
|
&(pstr_sbr_detector_handle->sbr_prev_env_compensation[0]);
|
|
|
|
memset(pstr_sbr_detector_handle->ptr_prev_env_compensation, 0,
|
|
sizeof(pstr_sbr_detector_handle->ptr_prev_env_compensation[0]) * MAXIMUM_FREQ_COEFFS);
|
|
|
|
pstr_sbr_detector_handle->ptr_guide_scfb = &(pstr_sbr_detector_handle->sbr_guide_scfb[0]);
|
|
|
|
memset(pstr_sbr_detector_handle->ptr_guide_scfb, 0,
|
|
sizeof(pstr_sbr_detector_handle->ptr_guide_scfb[0]) * MAXIMUM_FREQ_COEFFS);
|
|
|
|
pstr_sbr_detector_handle->prev_trans_flag = 0;
|
|
pstr_sbr_detector_handle->prev_trans_frame = 0;
|
|
pstr_sbr_detector_handle->prev_trans_pos = 0;
|
|
}
|