You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
575 lines
19 KiB
575 lines
19 KiB
/******************************************************************************
|
|
* *
|
|
* 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 <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "ixheaacd_type_def.h"
|
|
#include "ixheaacd_interface.h"
|
|
|
|
#include "ixheaacd_bitbuffer.h"
|
|
#include "ixheaacd_interface.h"
|
|
|
|
#include "ixheaacd_tns_usac.h"
|
|
#include "ixheaacd_cnst.h"
|
|
#include "ixheaacd_acelp_info.h"
|
|
|
|
#include "ixheaacd_td_mdct.h"
|
|
|
|
#include "ixheaacd_sbrdecsettings.h"
|
|
#include "ixheaacd_info.h"
|
|
#include "ixheaacd_sbr_common.h"
|
|
#include "ixheaacd_drc_data_struct.h"
|
|
#include "ixheaacd_drc_dec.h"
|
|
#include "ixheaacd_sbrdecoder.h"
|
|
#include "ixheaacd_mps_polyphase.h"
|
|
#include "ixheaacd_sbr_const.h"
|
|
#include "ixheaacd_main.h"
|
|
#include "ixheaacd_arith_dec.h"
|
|
#include "ixheaacd_windows.h"
|
|
|
|
#include "ixheaacd_vec_baisc_ops.h"
|
|
#include "ixheaacd_constants.h"
|
|
#include "ixheaacd_function_selector.h"
|
|
#include "ixheaacd_basic_ops32.h"
|
|
#include "ixheaacd_basic_ops40.h"
|
|
|
|
#include "ixheaacd_func_def.h"
|
|
|
|
#include "ixheaacd_windows.h"
|
|
|
|
extern const WORD32 ixheaacd_pre_post_twid_cos_512[512];
|
|
extern const WORD32 ixheaacd_pre_post_twid_sin_512[512];
|
|
extern const WORD32 ixheaacd_pre_post_twid_cos_384[384];
|
|
extern const WORD32 ixheaacd_pre_post_twid_sin_384[384];
|
|
extern const WORD32 ixheaacd_pre_post_twid_cos_64[64];
|
|
extern const WORD32 ixheaacd_pre_post_twid_sin_64[64];
|
|
extern const WORD32 ixheaacd_pre_post_twid_cos_48[48];
|
|
extern const WORD32 ixheaacd_pre_post_twid_sin_48[48];
|
|
extern const FLOAT64 ixheaacd_power_10_table[28];
|
|
|
|
#define ABS(A) ((A) < 0 ? (-A) : (A))
|
|
|
|
static WORD32 ixheaacd_calc_max_spectralline(WORD32 *p_in_ibuffer, WORD32 n) {
|
|
WORD32 k, shiftp, itemp = 0;
|
|
for (k = 0; k < n; k++) {
|
|
if (ixheaacd_abs32_sat(p_in_ibuffer[k]) > itemp)
|
|
itemp = ixheaacd_abs32_sat(p_in_ibuffer[k]);
|
|
}
|
|
|
|
shiftp = ixheaacd_norm32(itemp);
|
|
|
|
return (shiftp);
|
|
}
|
|
|
|
static void ixheaacd_normalize(WORD32 *buff, WORD32 shift, WORD len) {
|
|
WORD32 i;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
buff[i] = buff[i] << shift;
|
|
}
|
|
}
|
|
|
|
static FLOAT32 ixheaacd_pow10(WORD32 input) {
|
|
FLOAT32 output = 1;
|
|
while (input > 0) {
|
|
output *= 10;
|
|
input--;
|
|
}
|
|
return (output);
|
|
}
|
|
|
|
void ixheaacd_calc_pre_twid_dec(WORD32 *ptr_x, WORD32 *r_ptr, WORD32 *i_ptr,
|
|
WORD32 nlength, const WORD32 *cos_ptr,
|
|
const WORD32 *sin_ptr) {
|
|
WORD32 i;
|
|
WORD32 *ptr_y;
|
|
|
|
ptr_y = &ptr_x[2 * nlength - 1];
|
|
|
|
for (i = 0; i < nlength; i++) {
|
|
*r_ptr++ = ((ixheaacd_mult32(ixheaacd_negate32_sat(*ptr_x), (*cos_ptr)) -
|
|
ixheaacd_mult32((*ptr_y), (*sin_ptr))));
|
|
*i_ptr++ = ((ixheaacd_mult32((*ptr_y), (*cos_ptr++)) -
|
|
ixheaacd_mult32((*ptr_x), (*sin_ptr++))));
|
|
ptr_x += 2;
|
|
ptr_y -= 2;
|
|
}
|
|
}
|
|
|
|
void ixheaacd_calc_post_twid_dec(WORD32 *xptr, WORD32 *r_ptr, WORD32 *i_ptr,
|
|
WORD32 nlength, const WORD32 *cos_ptr,
|
|
const WORD32 *sin_ptr
|
|
|
|
) {
|
|
WORD32 i;
|
|
WORD32 *yptr;
|
|
|
|
yptr = &xptr[2 * nlength - 1];
|
|
|
|
for (i = 0; i < nlength; i++) {
|
|
*xptr = (-(ixheaacd_mult32((r_ptr[i]), (*cos_ptr)) -
|
|
ixheaacd_mult32((i_ptr[i]), (*sin_ptr))));
|
|
*yptr = (-(ixheaacd_mult32((i_ptr[i]), (*cos_ptr++)) +
|
|
ixheaacd_mult32((r_ptr[i]), (*sin_ptr++))));
|
|
xptr += 2;
|
|
yptr -= 2;
|
|
}
|
|
}
|
|
|
|
static WORD32 ixheaacd_fft_based_imdct(WORD32 *data, WORD32 npoints,
|
|
WORD32 *preshift, WORD32 *tmp_data) {
|
|
WORD32 *data_r;
|
|
WORD32 *data_i;
|
|
WORD32 nlength = npoints >> 1;
|
|
WORD32 err = 0;
|
|
const WORD32 *cos_ptr;
|
|
const WORD32 *sin_ptr;
|
|
|
|
data_r = tmp_data;
|
|
data_i = tmp_data + 512;
|
|
|
|
if (nlength == 512) {
|
|
cos_ptr = ixheaacd_pre_post_twid_cos_512;
|
|
sin_ptr = ixheaacd_pre_post_twid_sin_512;
|
|
} else if (nlength == 384) {
|
|
cos_ptr = ixheaacd_pre_post_twid_cos_384;
|
|
sin_ptr = ixheaacd_pre_post_twid_sin_384;
|
|
} else if (nlength == 64) {
|
|
cos_ptr = ixheaacd_pre_post_twid_cos_64;
|
|
sin_ptr = ixheaacd_pre_post_twid_sin_64;
|
|
} else if (nlength == 48) {
|
|
cos_ptr = ixheaacd_pre_post_twid_cos_48;
|
|
sin_ptr = ixheaacd_pre_post_twid_sin_48;
|
|
} else {
|
|
cos_ptr = ixheaacd_pre_post_twid_cos_48;
|
|
sin_ptr = ixheaacd_pre_post_twid_sin_48;
|
|
}
|
|
|
|
(*ixheaacd_calc_pre_twid)(data, data_r, data_i, nlength, cos_ptr, sin_ptr);
|
|
err = ixheaacd_complex_fft(data_r, data_i, nlength, 1, preshift);
|
|
if (err) return err;
|
|
(*ixheaacd_calc_post_twid)(data, data_r, data_i, nlength, cos_ptr, sin_ptr);
|
|
return err;
|
|
}
|
|
|
|
#define N_LONG_LEN_MAX 1024
|
|
|
|
WORD32 ixheaacd_acelp_imdct(WORD32 *imdct_in, WORD32 npoints, WORD8 *qshift,
|
|
WORD32 *tmp_data) {
|
|
WORD32 preshift = 0;
|
|
WORD32 i;
|
|
WORD32 k = (npoints / 2);
|
|
WORD32 err = 0;
|
|
|
|
while (((k & 1) == 0) & (k != 1)) {
|
|
k = k >> 1;
|
|
preshift++;
|
|
}
|
|
|
|
if ((k != 1)) {
|
|
for (i = 0; i < (npoints / 2); i++) {
|
|
imdct_in[i] = (imdct_in[i] / 3) << 1;
|
|
}
|
|
preshift++;
|
|
}
|
|
|
|
err = ixheaacd_fft_based_imdct(imdct_in, npoints / 2, &preshift, tmp_data);
|
|
if (err) return err;
|
|
preshift += 2;
|
|
*qshift -= preshift;
|
|
return err;
|
|
}
|
|
|
|
IA_ERRORCODE ixheaacd_cal_fac_data(ia_usac_data_struct *usac_data, WORD32 i_ch,
|
|
WORD32 n_long, WORD32 lfac,
|
|
WORD32 *fac_idata, WORD8 *q_fac) {
|
|
WORD32 gain_fac, scale, k, *i_aq, itemp = 0, *izir;
|
|
WORD32 int_aq[ORDER + 1] = {0};
|
|
WORD32 intzir[2 * LEN_FRAME] = {0};
|
|
WORD32 x_in[FAC_LENGTH] = {0};
|
|
FLOAT32 gain, ztemp, ftemp, pow10, rem10;
|
|
FLOAT32 qfac1;
|
|
WORD8 qshift1 = 0;
|
|
WORD8 qshift2 = 0;
|
|
WORD8 qshift3 = 0;
|
|
WORD32 preshift = 0;
|
|
IA_ERRORCODE err = IA_NO_ERROR;
|
|
|
|
FLOAT32 *last_lpc = usac_data->lpc_prev[i_ch];
|
|
FLOAT32 *acelp_in = usac_data->acelp_in[i_ch];
|
|
WORD32 *fac_data = usac_data->fac_data[i_ch];
|
|
WORD32 *ptr_scratch = &usac_data->scratch_buffer[0];
|
|
|
|
WORD32 quo = fac_data[0] / 28;
|
|
WORD32 rem = fac_data[0] % 28;
|
|
pow10 = ixheaacd_pow10(quo);
|
|
rem10 = (FLOAT32)ixheaacd_power_10_table[rem];
|
|
|
|
gain = pow10 * rem10;
|
|
scale = (WORD32)(ixheaacd_norm32((WORD32)((ABS(gain) + 1))));
|
|
gain_fac = (WORD32)(gain * (FLOAT32)((WORD64)1 << scale));
|
|
scale += 4;
|
|
qfac1 = 1.0f / (gain);
|
|
|
|
if (acelp_in != NULL) {
|
|
izir = intzir;
|
|
ftemp = 0.0;
|
|
for (k = 0; k < n_long / 4; k++) {
|
|
ztemp = acelp_in[k] * (qfac1);
|
|
if (ABS(ztemp) > ftemp) ftemp = ABS(ztemp);
|
|
}
|
|
|
|
itemp = (WORD32)(ftemp);
|
|
qshift3 = ixheaacd_norm32(itemp);
|
|
|
|
for (k = 0; k < n_long / 4; k++) {
|
|
izir[k] =
|
|
(WORD32)((acelp_in[k] * (qfac1)) * (FLOAT32)((WORD64)1 << qshift3));
|
|
}
|
|
} else
|
|
izir = NULL;
|
|
|
|
if (last_lpc != NULL) {
|
|
ftemp = 0.0;
|
|
i_aq = int_aq;
|
|
for (k = 0; k < ORDER + 1; k++) {
|
|
if (ABS(last_lpc[k]) > ftemp) ftemp = ABS(last_lpc[k]);
|
|
}
|
|
|
|
itemp = (WORD32)(ftemp);
|
|
qshift2 = ixheaacd_norm32(itemp);
|
|
|
|
for (k = 0; k < ORDER + 1; k++) {
|
|
i_aq[k] = (WORD32)(last_lpc[k] * (FLOAT32)((WORD64)1 << qshift2));
|
|
}
|
|
} else
|
|
i_aq = NULL;
|
|
|
|
for (k = 0; k < lfac; k++) {
|
|
if (ixheaacd_abs32_sat(fac_data[k + 1]) > itemp)
|
|
itemp = ixheaacd_abs32_sat(fac_data[k + 1]);
|
|
}
|
|
|
|
qshift1 = ixheaacd_norm32(itemp);
|
|
|
|
for (k = 0; k < lfac; k++) {
|
|
fac_data[k + 1] =
|
|
(WORD32)(fac_data[k + 1] * (FLOAT32)((WORD64)1 << qshift1));
|
|
}
|
|
|
|
for (k = 0; k < lfac / 2; k++) {
|
|
x_in[k] = fac_data[2 * k + 1];
|
|
x_in[lfac / 2 + k] = fac_data[lfac - 2 * k];
|
|
}
|
|
|
|
err = ixheaacd_fr_alias_cnx_fix(x_in, n_long / 4, lfac, i_aq, izir,
|
|
fac_idata + 16, &qshift1, qshift2, qshift3,
|
|
&preshift, ptr_scratch);
|
|
if (err) return err;
|
|
preshift += 4;
|
|
*q_fac = (qshift1 - preshift);
|
|
|
|
if (acelp_in != NULL) {
|
|
for (k = 0; k < 2 * lfac; k++) {
|
|
fac_idata[k] =
|
|
ixheaacd_mul32_sh(fac_idata[k + 16], gain_fac, (WORD8)(scale));
|
|
}
|
|
}
|
|
return IA_NO_ERROR;
|
|
}
|
|
|
|
static IA_ERRORCODE ixheaacd_fd_imdct_short(ia_usac_data_struct *usac_data,
|
|
WORD32 i_ch, WORD32 *fac_data_out,
|
|
offset_lengths *ixheaacd_drc_offset,
|
|
WORD8 fac_q) {
|
|
FLOAT32 qfac;
|
|
WORD32 overlap_data_buf[2 * N_LONG_LEN_MAX] = {0};
|
|
WORD32 *window_short, k, *window_short_prev_ptr;
|
|
WORD32 *overlap_data, *fp;
|
|
|
|
WORD32 *p_overlap_ibuffer = usac_data->overlap_data_ptr[i_ch];
|
|
WORD32 *p_in_ibuffer = usac_data->coef_fix[i_ch];
|
|
FLOAT32 *p_out_buffer = usac_data->time_sample_vector[i_ch];
|
|
WORD32 *p_out_ibuffer = usac_data->output_data_ptr[i_ch];
|
|
WORD32 *scratch_mem = usac_data->scratch_buffer;
|
|
WORD32 td_frame_prev = usac_data->td_frame_prev[i_ch];
|
|
WORD32 fac_apply = usac_data->fac_data_present[i_ch];
|
|
WORD8 shiftp, input_q, output_q, shift_olap = 14;
|
|
WORD32 max_shift;
|
|
|
|
WORD32 window_select = usac_data->window_shape[i_ch];
|
|
WORD32 window_select_prev = usac_data->window_shape_prev[i_ch];
|
|
ia_usac_lpd_decoder_handle st = usac_data->str_tddec[i_ch];
|
|
WORD32 err_code = 0;
|
|
|
|
max_shift =
|
|
ixheaacd_calc_max_spectralline(p_in_ibuffer, ixheaacd_drc_offset->n_long);
|
|
ixheaacd_normalize(p_in_ibuffer, max_shift, ixheaacd_drc_offset->n_long);
|
|
shiftp = max_shift + 6;
|
|
input_q = shiftp;
|
|
|
|
memcpy(overlap_data_buf, p_overlap_ibuffer,
|
|
sizeof(WORD32) * ixheaacd_drc_offset->n_long);
|
|
overlap_data = overlap_data_buf;
|
|
|
|
fp = overlap_data + ixheaacd_drc_offset->n_flat_ls;
|
|
|
|
for (k = 0; k < 8; k++) {
|
|
shiftp = input_q;
|
|
err_code = ixheaacd_acelp_imdct(
|
|
p_in_ibuffer + (k * ixheaacd_drc_offset->n_short),
|
|
2 * ixheaacd_drc_offset->n_short, &shiftp, scratch_mem);
|
|
if (err_code) return err_code;
|
|
}
|
|
|
|
max_shift =
|
|
ixheaacd_calc_max_spectralline(p_in_ibuffer, ixheaacd_drc_offset->n_long);
|
|
ixheaacd_normalize(p_in_ibuffer, max_shift - 1, ixheaacd_drc_offset->n_long);
|
|
shiftp += max_shift - 1;
|
|
|
|
err_code = ixheaacd_calc_window(&window_short, ixheaacd_drc_offset->n_short,
|
|
window_select);
|
|
if (err_code == -1) return err_code;
|
|
err_code =
|
|
ixheaacd_calc_window(&window_short_prev_ptr,
|
|
ixheaacd_drc_offset->n_trans_ls, window_select_prev);
|
|
if (err_code == -1) return err_code;
|
|
|
|
if (fac_apply)
|
|
ixheaacd_windowing_short1(p_in_ibuffer + ixheaacd_drc_offset->n_short / 2,
|
|
window_short_prev_ptr, fp, ixheaacd_drc_offset,
|
|
shiftp, shift_olap);
|
|
|
|
else
|
|
ixheaacd_windowing_short2(p_in_ibuffer + ixheaacd_drc_offset->n_short / 2,
|
|
window_short_prev_ptr, fp, ixheaacd_drc_offset,
|
|
shiftp, shift_olap);
|
|
|
|
output_q = ixheaacd_windowing_short3(
|
|
p_in_ibuffer, window_short + ixheaacd_drc_offset->n_short - 1,
|
|
fp + ixheaacd_drc_offset->n_short, ixheaacd_drc_offset->n_short, shiftp,
|
|
shift_olap);
|
|
p_in_ibuffer += ixheaacd_drc_offset->n_short;
|
|
fp += ixheaacd_drc_offset->n_short;
|
|
window_short_prev_ptr = window_short;
|
|
|
|
for (k = 1; k < 7; k++) {
|
|
output_q = ixheaacd_windowing_short4(
|
|
p_in_ibuffer, window_short_prev_ptr, fp,
|
|
window_short_prev_ptr + ixheaacd_drc_offset->n_short - 1,
|
|
ixheaacd_drc_offset->n_short, 1, shiftp, shift_olap, output_q);
|
|
p_in_ibuffer += ixheaacd_drc_offset->n_short;
|
|
fp += ixheaacd_drc_offset->n_short;
|
|
window_short_prev_ptr = window_short;
|
|
}
|
|
|
|
output_q = ixheaacd_windowing_short4(
|
|
p_in_ibuffer, window_short_prev_ptr, fp,
|
|
window_short_prev_ptr + ixheaacd_drc_offset->n_short - 1,
|
|
ixheaacd_drc_offset->n_short, 0, shiftp, shift_olap, output_q);
|
|
p_in_ibuffer += ixheaacd_drc_offset->n_short;
|
|
fp += ixheaacd_drc_offset->n_short;
|
|
|
|
if (fac_apply) {
|
|
ixheaacd_combine_fac(overlap_data + ixheaacd_drc_offset->n_flat_ls +
|
|
ixheaacd_drc_offset->lfac,
|
|
fac_data_out,
|
|
overlap_data + ixheaacd_drc_offset->n_flat_ls +
|
|
ixheaacd_drc_offset->lfac,
|
|
2 * ixheaacd_drc_offset->lfac, output_q, fac_q);
|
|
}
|
|
memset(overlap_data + 2 * ixheaacd_drc_offset->n_long -
|
|
ixheaacd_drc_offset->n_flat_ls,
|
|
0, sizeof(WORD32) * ixheaacd_drc_offset->n_flat_ls);
|
|
ixheaacd_scale_down(overlap_data, overlap_data,
|
|
ixheaacd_drc_offset->n_flat_ls, shift_olap, output_q);
|
|
|
|
ixheaacd_scale_down(p_overlap_ibuffer,
|
|
overlap_data + ixheaacd_drc_offset->n_long,
|
|
ixheaacd_drc_offset->n_long, output_q, shift_olap);
|
|
ixheaacd_scale_down(p_out_ibuffer, overlap_data, ixheaacd_drc_offset->n_long,
|
|
output_q, 15);
|
|
|
|
if (td_frame_prev) {
|
|
qfac = 1.0f / (FLOAT32)(1 << 15);
|
|
|
|
for (k = 0; k < ixheaacd_drc_offset->n_long; k++) {
|
|
p_out_buffer[k] = ((FLOAT32)p_out_ibuffer[k]) * qfac;
|
|
}
|
|
err_code = ixheaacd_lpd_bpf_fix(usac_data, 1, p_out_buffer, st);
|
|
if (err_code != 0) return err_code;
|
|
|
|
for (k = 0; k < ixheaacd_drc_offset->n_long; k++) {
|
|
p_out_ibuffer[k] = (WORD32)(p_out_buffer[k] * (1 << 15));
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static IA_ERRORCODE ixheaacd_fd_imdct_long(ia_usac_data_struct *usac_data,
|
|
WORD32 i_ch, WORD32 *fac_idata,
|
|
offset_lengths *ixheaacd_drc_offset,
|
|
WORD8 fac_q) {
|
|
FLOAT32 qfac;
|
|
WORD32 *window_long_prev, k, i, *window_short_prev_ptr;
|
|
|
|
WORD32 *p_in_ibuffer = usac_data->coef_fix[i_ch];
|
|
WORD32 *p_overlap_ibuffer = usac_data->overlap_data_ptr[i_ch];
|
|
WORD32 *p_out_ibuffer = usac_data->output_data_ptr[i_ch];
|
|
FLOAT32 *p_out_buffer = usac_data->time_sample_vector[i_ch];
|
|
WORD32 *scratch_mem = usac_data->scratch_buffer;
|
|
WORD32 n_long = usac_data->ccfl;
|
|
WORD32 td_frame_prev = usac_data->td_frame_prev[i_ch];
|
|
WORD32 fac_apply = usac_data->fac_data_present[i_ch];
|
|
WORD8 shiftp, output_q = 0, shift_olap = 14;
|
|
WORD32 max_shift;
|
|
|
|
WORD32 window_sequence = usac_data->window_sequence[i_ch];
|
|
WORD32 window_select_prev = usac_data->window_shape_prev[i_ch];
|
|
ia_usac_lpd_decoder_handle st = usac_data->str_tddec[i_ch];
|
|
|
|
WORD32 err_code = 0;
|
|
|
|
max_shift =
|
|
ixheaacd_calc_max_spectralline(p_in_ibuffer, ixheaacd_drc_offset->n_long);
|
|
ixheaacd_normalize(p_in_ibuffer, max_shift, ixheaacd_drc_offset->n_long);
|
|
shiftp = max_shift + 6;
|
|
|
|
err_code = ixheaacd_acelp_imdct(p_in_ibuffer, 2 * ixheaacd_drc_offset->n_long,
|
|
&shiftp, scratch_mem);
|
|
if (err_code) return err_code;
|
|
|
|
max_shift =
|
|
ixheaacd_calc_max_spectralline(p_in_ibuffer, ixheaacd_drc_offset->n_long);
|
|
ixheaacd_normalize(p_in_ibuffer, max_shift - 1, ixheaacd_drc_offset->n_long);
|
|
shiftp += max_shift - 1;
|
|
|
|
switch (window_sequence) {
|
|
case ONLY_LONG_SEQUENCE:
|
|
case LONG_START_SEQUENCE:
|
|
err_code = ixheaacd_calc_window(
|
|
&window_long_prev, ixheaacd_drc_offset->n_long, window_select_prev);
|
|
if (err_code == -1) return err_code;
|
|
output_q = ixheaacd_windowing_long1(
|
|
p_in_ibuffer + n_long / 2, p_overlap_ibuffer, window_long_prev,
|
|
window_long_prev + ixheaacd_drc_offset->n_long - 1, p_out_ibuffer,
|
|
ixheaacd_drc_offset->n_long, shiftp, shift_olap);
|
|
break;
|
|
|
|
case STOP_START_SEQUENCE:
|
|
case LONG_STOP_SEQUENCE:
|
|
err_code = ixheaacd_calc_window(&window_short_prev_ptr,
|
|
ixheaacd_drc_offset->n_trans_ls,
|
|
window_select_prev);
|
|
if (err_code == -1) return err_code;
|
|
if (fac_apply) {
|
|
output_q = ixheaacd_windowing_long2(
|
|
p_in_ibuffer + n_long / 2, window_short_prev_ptr, fac_idata,
|
|
p_overlap_ibuffer, p_out_ibuffer, ixheaacd_drc_offset, shiftp,
|
|
shift_olap, fac_q);
|
|
} else {
|
|
output_q = ixheaacd_windowing_long3(
|
|
p_in_ibuffer + n_long / 2, window_short_prev_ptr, p_overlap_ibuffer,
|
|
p_out_ibuffer,
|
|
window_short_prev_ptr + ixheaacd_drc_offset->n_trans_ls - 1,
|
|
ixheaacd_drc_offset, shiftp, shift_olap);
|
|
}
|
|
break;
|
|
}
|
|
|
|
for (i = 0; i < ixheaacd_drc_offset->n_long / 2; i++) {
|
|
p_overlap_ibuffer[ixheaacd_drc_offset->n_long / 2 + i] =
|
|
ixheaacd_negate32_sat(p_in_ibuffer[i]) >> (shiftp - shift_olap);
|
|
p_overlap_ibuffer[ixheaacd_drc_offset->n_long / 2 - i - 1] =
|
|
ixheaacd_negate32_sat(p_in_ibuffer[i]) >> (shiftp - shift_olap);
|
|
}
|
|
|
|
ixheaacd_scale_down_adj(p_out_ibuffer, p_out_ibuffer,
|
|
ixheaacd_drc_offset->n_long, output_q, 15);
|
|
|
|
if (td_frame_prev) {
|
|
qfac = 1.0f / (FLOAT32)(1 << 15);
|
|
|
|
for (k = 0; k < ixheaacd_drc_offset->n_long; k++) {
|
|
p_out_buffer[k] = ((FLOAT32)p_out_ibuffer[k]) * qfac;
|
|
}
|
|
err_code = ixheaacd_lpd_bpf_fix(usac_data, 0, p_out_buffer, st);
|
|
if (err_code != 0) return err_code;
|
|
|
|
for (k = 0; k < ixheaacd_drc_offset->n_long; k++) {
|
|
p_out_ibuffer[k] = (WORD32)(p_out_buffer[k] * (1 << 15));
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
WORD32 ixheaacd_fd_frm_dec(ia_usac_data_struct *usac_data, WORD32 i_ch) {
|
|
WORD32 fac_idata[2 * FAC_LENGTH + 16];
|
|
offset_lengths ixheaacd_drc_offset;
|
|
WORD8 fac_q = 0;
|
|
WORD32 td_frame_prev = usac_data->td_frame_prev[i_ch];
|
|
WORD32 fac_apply = usac_data->fac_data_present[i_ch];
|
|
WORD32 window_sequence = usac_data->window_sequence[i_ch];
|
|
IA_ERRORCODE err = IA_NO_ERROR;
|
|
ixheaacd_drc_offset.n_long = usac_data->ccfl;
|
|
ixheaacd_drc_offset.n_short = ixheaacd_drc_offset.n_long >> 3;
|
|
|
|
memset(fac_idata, 0, sizeof(fac_idata));
|
|
|
|
if (td_frame_prev) {
|
|
if (window_sequence == EIGHT_SHORT_SEQUENCE) {
|
|
ixheaacd_drc_offset.lfac = ixheaacd_drc_offset.n_long >> 4;
|
|
} else {
|
|
ixheaacd_drc_offset.lfac = ixheaacd_drc_offset.n_long >> 3;
|
|
}
|
|
ixheaacd_drc_offset.n_flat_ls =
|
|
(ixheaacd_drc_offset.n_long - (ixheaacd_drc_offset.lfac) * 2) >> 1;
|
|
|
|
ixheaacd_drc_offset.n_trans_ls = (ixheaacd_drc_offset.lfac) << 1;
|
|
} else {
|
|
ixheaacd_drc_offset.lfac = FAC_LENGTH;
|
|
ixheaacd_drc_offset.n_flat_ls =
|
|
(ixheaacd_drc_offset.n_long - ixheaacd_drc_offset.n_short) >> 1;
|
|
ixheaacd_drc_offset.n_trans_ls = ixheaacd_drc_offset.n_short;
|
|
}
|
|
|
|
if (fac_apply) {
|
|
err = ixheaacd_cal_fac_data(usac_data, i_ch, ixheaacd_drc_offset.n_long,
|
|
ixheaacd_drc_offset.lfac, fac_idata, &fac_q);
|
|
if (err) return err;
|
|
}
|
|
|
|
if (window_sequence != EIGHT_SHORT_SEQUENCE) {
|
|
err = ixheaacd_fd_imdct_long(usac_data, i_ch, fac_idata,
|
|
&ixheaacd_drc_offset, fac_q);
|
|
if (err) return err;
|
|
} else {
|
|
err = ixheaacd_fd_imdct_short(usac_data, i_ch, fac_idata,
|
|
&ixheaacd_drc_offset, fac_q);
|
|
if (err) return err;
|
|
}
|
|
|
|
return err;
|
|
}
|