240 lines
8.4 KiB
C
240 lines
8.4 KiB
C
/******************************************************************************
|
|
* *
|
|
* Copyright (C) 2018 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <string.h>
|
|
#include "ixheaacd_type_def.h"
|
|
#include "ixheaacd_sbr_const.h"
|
|
|
|
#include "ixheaacd_pvc_dec.h"
|
|
#include "ixheaacd_pvc_rom.h"
|
|
|
|
static VOID ixheaacd_pvc_sb_parsing(ia_pvc_data_struct *ptr_pvc_data,
|
|
WORD16 first_bnd_idx, FLOAT32 *p_qmfh) {
|
|
WORD32 ksg, k;
|
|
WORD32 start_band, end_band;
|
|
WORD32 time_slot;
|
|
|
|
FLOAT32 *p_sbr_range_esg = &ptr_pvc_data->sbr_range_esg_arr[0];
|
|
|
|
for (time_slot = 0; time_slot < PVC_NUM_TIME_SLOTS; time_slot++) {
|
|
start_band = first_bnd_idx;
|
|
end_band = start_band + ptr_pvc_data->nb_high_per_grp - 1;
|
|
|
|
for (ksg = 0; ksg < ptr_pvc_data->nb_high; ksg++) {
|
|
for (k = start_band; k <= end_band; k++) {
|
|
p_qmfh[k] = (FLOAT32)pow(10.0f, (p_sbr_range_esg[ksg] / 10.0));
|
|
}
|
|
start_band += ptr_pvc_data->nb_high_per_grp;
|
|
if (ksg >= ptr_pvc_data->nb_high - 2) {
|
|
end_band = SBR_NUM_QMF_BANDS - 1;
|
|
} else {
|
|
end_band = start_band + ptr_pvc_data->nb_high_per_grp - 1;
|
|
if (end_band >= SBR_NUM_QMF_BANDS - 1) {
|
|
end_band = SBR_NUM_QMF_BANDS - 1;
|
|
}
|
|
}
|
|
}
|
|
p_sbr_range_esg = p_sbr_range_esg + 8;
|
|
p_qmfh = p_qmfh + SBR_NUM_QMF_BANDS;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static VOID ixheaacd_pvc_qmf_grouping(ia_pvc_data_struct *ptr_pvc_data,
|
|
WORD16 first_bnd_idx, FLOAT32 *p_qmf_ener,
|
|
WORD32 first_pvc_timeslot) {
|
|
WORD32 ksg, time_slot, ib;
|
|
WORD32 lbw, start_band, end_band;
|
|
FLOAT32 esg;
|
|
FLOAT32 *p_esg = (FLOAT32 *)ptr_pvc_data->esg;
|
|
|
|
lbw = 8 / ptr_pvc_data->pvc_rate;
|
|
|
|
for (time_slot = 0; time_slot < PVC_NUM_TIME_SLOTS; time_slot++) {
|
|
for (ksg = 0; ksg < PVC_NB_LOW; ksg++) {
|
|
start_band = first_bnd_idx - lbw * PVC_NB_LOW + lbw * ksg;
|
|
end_band = start_band + lbw - 1;
|
|
if (start_band >= 0) {
|
|
esg = 0.0f;
|
|
for (ib = start_band; ib <= end_band; ib++) {
|
|
esg += p_qmf_ener[ib];
|
|
}
|
|
esg = esg / lbw;
|
|
} else {
|
|
esg = PVC_ESG_MIN_VAL;
|
|
}
|
|
|
|
if (esg > PVC_ESG_MIN_VAL) {
|
|
p_esg[(time_slot + 16 - 1) * 3 + ksg] = 10 * ((FLOAT32)log10(esg));
|
|
} else {
|
|
p_esg[(time_slot + 16 - 1) * 3 + ksg] = PVC_10LOG10_ESG_MIN_VAL;
|
|
}
|
|
}
|
|
p_qmf_ener = p_qmf_ener + SBR_NUM_QMF_BANDS_2;
|
|
}
|
|
|
|
if ((ptr_pvc_data->prev_pvc_flg == 0) ||
|
|
((first_bnd_idx * ptr_pvc_data->pvc_rate) !=
|
|
(ptr_pvc_data->prev_first_bnd_idx * ptr_pvc_data->prev_pvc_rate))) {
|
|
for (time_slot = 0; time_slot < 16 - 1 + first_pvc_timeslot; time_slot++) {
|
|
for (ksg = 0; ksg < PVC_NB_LOW; ksg++) {
|
|
p_esg[time_slot * 3 + ksg] =
|
|
p_esg[(16 - 1 + first_pvc_timeslot) * 3 + ksg];
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static VOID ixheaacd_pvc_time_smoothing(ia_pvc_data_struct *ptr_pvc_data) {
|
|
WORD32 time_slot;
|
|
FLOAT32 *p_smooth_esg = (FLOAT32 *)&ptr_pvc_data->smooth_esg_arr[0];
|
|
for (time_slot = 0; time_slot < PVC_NUM_TIME_SLOTS; time_slot++) {
|
|
WORD32 ksg, time_slot_idx;
|
|
FLOAT32 *p_esg = (FLOAT32 *)&ptr_pvc_data->esg[time_slot + 16 - 1][2];
|
|
FLOAT32 *p_smth_wind_coeff = (FLOAT32 *)&ptr_pvc_data->p_smth_wind_coeff[0];
|
|
memset(p_smooth_esg, (WORD32)0.f, sizeof(FLOAT32) * PVC_NB_LOW);
|
|
for (time_slot_idx = 0; time_slot_idx < ptr_pvc_data->num_time_slots;
|
|
time_slot_idx++) {
|
|
ksg = PVC_NB_LOW - 1;
|
|
for (; ksg >= 0; ksg--) {
|
|
p_smooth_esg[ksg] += (*p_esg) * (*p_smth_wind_coeff);
|
|
p_esg--;
|
|
}
|
|
p_smth_wind_coeff++;
|
|
}
|
|
p_smooth_esg = p_smooth_esg + 3;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static VOID ixheaacd_pvc_pred_env_sf(ia_pvc_data_struct *ptr_pvc_data) {
|
|
WORD32 ksg, kb;
|
|
WORD32 tab_1_index, tab_2_index;
|
|
WORD32 time_slot;
|
|
WORD8 *pred_tab_1, *pred_tab_2;
|
|
|
|
FLOAT32 temp;
|
|
FLOAT32 *p_smooth_esg = &ptr_pvc_data->smooth_esg_arr[0];
|
|
FLOAT32 *p_sbr_range_esg = &ptr_pvc_data->sbr_range_esg_arr[0];
|
|
|
|
for (time_slot = 0; time_slot < PVC_NUM_TIME_SLOTS; time_slot++) {
|
|
tab_2_index = ptr_pvc_data->pvc_id[time_slot];
|
|
|
|
if (tab_2_index < ptr_pvc_data->p_pvc_id_boundary[0]) {
|
|
tab_1_index = 0;
|
|
} else if (tab_2_index < ptr_pvc_data->p_pvc_id_boundary[1]) {
|
|
tab_1_index = 1;
|
|
} else {
|
|
tab_1_index = 2;
|
|
}
|
|
|
|
pred_tab_1 =
|
|
(WORD8 *)(&(ptr_pvc_data->p_pred_coeff_tab_1[tab_1_index * PVC_NB_LOW *
|
|
ptr_pvc_data->nb_high]));
|
|
pred_tab_2 = (WORD8 *)(&(
|
|
ptr_pvc_data->p_pred_coeff_tab_2[tab_2_index * ptr_pvc_data->nb_high]));
|
|
|
|
for (ksg = 0; ksg < ptr_pvc_data->nb_high; ksg++) {
|
|
temp =
|
|
(FLOAT32)(WORD8)(*(pred_tab_2++)) * ptr_pvc_data->p_q_fac[PVC_NB_LOW];
|
|
p_sbr_range_esg[ksg] = temp;
|
|
}
|
|
for (kb = 0; kb < PVC_NB_LOW; kb++) {
|
|
for (ksg = 0; ksg < ptr_pvc_data->nb_high; ksg++) {
|
|
temp = (FLOAT32)(WORD8)(*(pred_tab_1++)) * ptr_pvc_data->p_q_fac[kb];
|
|
p_sbr_range_esg[ksg] += temp * p_smooth_esg[kb];
|
|
}
|
|
}
|
|
p_smooth_esg = p_smooth_esg + 3;
|
|
p_sbr_range_esg = p_sbr_range_esg + 8;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
WORD32 ixheaacd_pvc_process(ia_pvc_data_struct *ptr_pvc_data,
|
|
WORD16 first_bnd_idx, WORD32 first_pvc_timeslot,
|
|
FLOAT32 *p_qmf_ener, FLOAT32 *p_qmfh) {
|
|
switch (ptr_pvc_data->pvc_mode) {
|
|
case 1:
|
|
ptr_pvc_data->nb_high = PVC_NB_HIGH_MODE1;
|
|
ptr_pvc_data->nb_high_per_grp = 8 / ptr_pvc_data->pvc_rate;
|
|
ptr_pvc_data->p_pred_coeff_tab_1 =
|
|
(WORD8 *)ixheaacd_pred_coeff_table_1_mode_1;
|
|
ptr_pvc_data->p_pred_coeff_tab_2 =
|
|
(WORD8 *)ixheaacd_pred_coeff_table_2_mode_1;
|
|
ptr_pvc_data->p_pvc_id_boundary =
|
|
(UWORD8 *)ixheaacd_pred_coeff_pvc_id_boundaries_1;
|
|
ptr_pvc_data->p_q_fac = (FLOAT32 *)ixheaacd_q_factor_table_mode_1;
|
|
if (ptr_pvc_data->ns_mode) {
|
|
ptr_pvc_data->num_time_slots = 4;
|
|
ptr_pvc_data->p_smth_wind_coeff =
|
|
(FLOAT32 *)ixheaacd_pvc_smoothing_wind_tab_ns4;
|
|
} else {
|
|
ptr_pvc_data->num_time_slots = 16;
|
|
ptr_pvc_data->p_smth_wind_coeff =
|
|
(FLOAT32 *)ixheaacd_pvc_smoothing_wind_tab_ns16;
|
|
}
|
|
break;
|
|
case 2:
|
|
ptr_pvc_data->nb_high = PVC_NB_HIGH_MODE2;
|
|
ptr_pvc_data->nb_high_per_grp = 12 / ptr_pvc_data->pvc_rate;
|
|
ptr_pvc_data->p_pred_coeff_tab_1 =
|
|
(WORD8 *)ixheaacd_pred_coeff_table_1_mode_2;
|
|
ptr_pvc_data->p_pred_coeff_tab_2 =
|
|
(WORD8 *)ixheaacd_pred_coeff_table_2_mode_2;
|
|
ptr_pvc_data->p_pvc_id_boundary =
|
|
(UWORD8 *)ixheaacd_pred_coeff_pvc_id_boundaries_2;
|
|
ptr_pvc_data->p_q_fac = (FLOAT32 *)ixheaacd_q_factor_table_mode_2;
|
|
if (ptr_pvc_data->ns_mode) {
|
|
ptr_pvc_data->num_time_slots = 3;
|
|
ptr_pvc_data->p_smth_wind_coeff =
|
|
(FLOAT32 *)ixheaacd_pvc_smoothing_wind_tab_ns3;
|
|
} else {
|
|
ptr_pvc_data->num_time_slots = 12;
|
|
ptr_pvc_data->p_smth_wind_coeff =
|
|
(FLOAT32 *)ixheaacd_pvc_smoothing_wind_tab_ns12;
|
|
}
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
ptr_pvc_data->prev_pvc_id = ptr_pvc_data->pvc_id[PVC_NUM_TIME_SLOTS - 1];
|
|
|
|
ixheaacd_pvc_qmf_grouping(ptr_pvc_data, first_bnd_idx, p_qmf_ener,
|
|
first_pvc_timeslot);
|
|
|
|
ixheaacd_pvc_time_smoothing(ptr_pvc_data);
|
|
|
|
ixheaacd_pvc_pred_env_sf(ptr_pvc_data);
|
|
|
|
ixheaacd_pvc_sb_parsing(ptr_pvc_data, first_bnd_idx, p_qmfh);
|
|
|
|
memcpy((FLOAT32 *)(&ptr_pvc_data->esg[0][0]),
|
|
(FLOAT32 *)(&ptr_pvc_data->esg[PVC_NUM_TIME_SLOTS][0]),
|
|
sizeof(FLOAT32) * (PVC_NUM_TIME_SLOTS - 1) * 3);
|
|
|
|
return 0;
|
|
}
|