libxaac/decoder/drc_src/impd_drc_process.c
Ray Essick 48f5fd9660 Import xHE-AAC decoder from Ittiam
Clean copy of version XHEAAC_V1_36 as delivered 2018/4/13
Sole change is to map cr/lf line termination to unix lf.

Added appropriate LICENSE, MODULE_LICENSE_APACHE2, and NOTICE files
as part of folding into internal master.

Bug: 77287124
Test: CTS audio/media
Change-Id: I3c8d124033f967b29d6e384cce5c843ee17a7bb1
2018-05-04 11:48:02 -07:00

557 lines
24 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 "impd_type_def.h"
#include "impd_drc_extr_delta_coded_info.h"
#include "impd_drc_common.h"
#include "impd_drc_struct.h"
#include "impd_drc_filter_bank.h"
#include "impd_drc_multi_band.h"
#include "impd_drc_gain_dec.h"
#include "impd_drc_process_audio.h"
WORD32 impd_apply_gains_and_add(ia_drc_instructions_struct* pstr_drc_instruction_arr,
const WORD32 drc_instructions_index,
ia_drc_params_struct* ia_drc_params_struct,
ia_gain_buffer_struct* pstr_gain_buf,
shape_filter_block shape_filter_block[],
FLOAT32* deinterleaved_audio[],
FLOAT32* channel_audio[],
WORD32 impd_apply_gains)
{
WORD32 c, b, g, i;
WORD32 offset = 0, signalIndex = 0;
WORD32 gainIndexForGroup[CHANNEL_GROUP_COUNT_MAX];
WORD32 signalIndexForChannel[MAX_CHANNEL_COUNT];
FLOAT32* lpcm_gains;
FLOAT32 sum;
FLOAT32 drc_gain_last, gainThr;
WORD32 iEnd, iStart;
ia_drc_instructions_struct* str_drc_instruction_str = &(pstr_drc_instruction_arr[drc_instructions_index]);
if (drc_instructions_index >= 0)
{
str_drc_instruction_str = &(pstr_drc_instruction_arr[drc_instructions_index]);
{
if (str_drc_instruction_str->drc_set_id > 0)
{
if (ia_drc_params_struct->delay_mode == DELAY_MODE_LOW_DELAY)
{
offset = ia_drc_params_struct->drc_frame_size;
}
gainIndexForGroup[0] = 0;
for (g=0; g<str_drc_instruction_str->num_drc_ch_groups-1; g++)
{
gainIndexForGroup[g+1] = gainIndexForGroup[g] + str_drc_instruction_str->band_count_of_ch_group[g];
}
signalIndexForChannel[0] = 0;
for (c=0; c<str_drc_instruction_str->audio_num_chan-1; c++)
{
if (str_drc_instruction_str->channel_group_of_ch[c] >= 0)
{
signalIndexForChannel[c+1] = signalIndexForChannel[c] + str_drc_instruction_str->band_count_of_ch_group[str_drc_instruction_str->channel_group_of_ch[c]];
}
else
{
signalIndexForChannel[c+1] = signalIndexForChannel[c] + 1;
}
}
for (g=0; g<str_drc_instruction_str->num_drc_ch_groups; g++)
{
for (b=0; b<str_drc_instruction_str->band_count_of_ch_group[g]; b++)
{
if (str_drc_instruction_str->ch_group_parametric_drc_flag[g] == 0) {
lpcm_gains = pstr_gain_buf->buf_interpolation[gainIndexForGroup[g]+b].lpcm_gains + MAX_SIGNAL_DELAY - ia_drc_params_struct->gain_delay_samples - ia_drc_params_struct->audio_delay_samples + offset;
} else {
lpcm_gains = pstr_gain_buf->buf_interpolation[gainIndexForGroup[g]+b].lpcm_gains + MAX_SIGNAL_DELAY + str_drc_instruction_str->parametric_drc_look_ahead_samples[g] - ia_drc_params_struct->audio_delay_samples;
}
iEnd = 0;
iStart = 0;
while (iEnd < ia_drc_params_struct->drc_frame_size)
{
if (shape_filter_block[g].shape_flter_block_flag) {
drc_gain_last = shape_filter_block[g].drc_gain_last;
gainThr = 0.0001f * drc_gain_last;
while ((iEnd<ia_drc_params_struct->drc_frame_size) && (fabs(lpcm_gains[iEnd] - drc_gain_last) <= gainThr)) iEnd++;
}
else
{
iEnd = ia_drc_params_struct->drc_frame_size;
}
for (c=0; c<str_drc_instruction_str->audio_num_chan; c++)
{
if (g == str_drc_instruction_str->channel_group_of_ch[c])
{
signalIndex = signalIndexForChannel[c] + b;
if(impd_apply_gains == 1) {
impd_shape_filt_block_time_process(&shape_filter_block[g],
&lpcm_gains[0],
signalIndex,
&deinterleaved_audio[signalIndex][0],
iStart,
iEnd);
}
else {
for (i=iStart; i<iEnd; i++){
deinterleaved_audio[signalIndex][i] = lpcm_gains[i];
}
}
}
}
if ((iEnd < ia_drc_params_struct->drc_frame_size) && (shape_filter_block[g].shape_flter_block_flag))
{
impd_shape_filt_block_adapt(lpcm_gains[iEnd], &shape_filter_block[g]);
}
iStart = iEnd;
}
}
}
}
}
}
signalIndex=0;
if (str_drc_instruction_str->drc_set_id > 0)
{
for (c=0; c<str_drc_instruction_str->audio_num_chan; c++)
{
g = str_drc_instruction_str->channel_group_of_ch[c];
if (g>=0)
{
for (i=0; i<ia_drc_params_struct->drc_frame_size; i++)
{
sum = 0.0f;
for (b=0; b<str_drc_instruction_str->band_count_of_ch_group[g]; b++)
{
sum += deinterleaved_audio[signalIndex+b][i];
}
channel_audio[c][i] = sum;
}
signalIndex += str_drc_instruction_str->band_count_of_ch_group[g];
}
else
{
for (i=0; i<ia_drc_params_struct->drc_frame_size; i++)
{
channel_audio[c][i] = deinterleaved_audio[signalIndex][i];
}
signalIndex++;
}
}
}
else
{
for (c=0; c<str_drc_instruction_str->audio_num_chan; c++)
{
for (i=0; i<ia_drc_params_struct->drc_frame_size; i++)
{
channel_audio[c][i] = deinterleaved_audio[c][i];
}
}
}
return (0);
}
/* subband-domain DRC: in-place application of DRC gains to audio frame */
WORD32
impd_apply_gains_subband(ia_drc_instructions_struct* pstr_drc_instruction_arr,
const WORD32 drc_instructions_index,
ia_drc_params_struct* ia_drc_params_struct,
ia_gain_buffer_struct* pstr_gain_buf,
ia_overlap_params_struct* pstr_overlap_params,
FLOAT32* deinterleaved_audio_delayed_re[],
FLOAT32* deinterleaved_audio_delayed_im[],
FLOAT32* deinterleaved_audio_re[],
FLOAT32* deinterleaved_audio_im[])
{
WORD32 c, b, g, m, s;
WORD32 gainIndexForGroup[CHANNEL_GROUP_COUNT_MAX];
FLOAT32* lpcm_gains;
FLOAT32 gainSb, gainLr;
ia_drc_instructions_struct* str_drc_instruction_str;
WORD32 offset = 0, signalIndex = 0;
WORD32 drc_frame_sizeSb = 0;
WORD32 nDecoderSubbands = 0;
WORD32 L = 0; /* L: downsampling factor */
WORD32 analysisDelay = 0;
switch (ia_drc_params_struct->sub_band_domain_mode) {
case SUBBAND_DOMAIN_MODE_QMF64:
nDecoderSubbands = AUDIO_CODEC_SUBBAND_COUNT_QMF64;
L = AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR_QMF64;
analysisDelay = AUDIO_CODEC_SUBBAND_ANALYSE_DELAY_QMF64;
break;
case SUBBAND_DOMAIN_MODE_QMF71:
nDecoderSubbands = AUDIO_CODEC_SUBBAND_COUNT_QMF71;
L = AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR_QMF71;
analysisDelay = AUDIO_CODEC_SUBBAND_ANALYSE_DELAY_QMF71;
break;
case SUBBAND_DOMAIN_MODE_STFT256:
nDecoderSubbands = AUDIO_CODEC_SUBBAND_COUNT_STFT256;
L = AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR_STFT256;
analysisDelay = AUDIO_CODEC_SUBBAND_ANALYSE_DELAY_STFT256;
break;
default:
return -1;
break;
}
drc_frame_sizeSb = ia_drc_params_struct->drc_frame_size/L;
if (drc_instructions_index >= 0)
{
str_drc_instruction_str = &(pstr_drc_instruction_arr[drc_instructions_index]);
{
if (str_drc_instruction_str->drc_set_id > 0)
{
if (ia_drc_params_struct->delay_mode == DELAY_MODE_LOW_DELAY)
{
offset = ia_drc_params_struct->drc_frame_size;
}
gainIndexForGroup[0] = 0;
for (g=0; g<str_drc_instruction_str->num_drc_ch_groups-1; g++)
{
gainIndexForGroup[g+1] = gainIndexForGroup[g] + str_drc_instruction_str->band_count_of_ch_group[g]; /* index of first gain sequence in channel group */
}
for (c=0; c<str_drc_instruction_str->audio_num_chan; c++)
{
g = str_drc_instruction_str->channel_group_of_ch[c];
if (g>=0)
{
for (m=0; m<drc_frame_sizeSb; m++)
{
if (str_drc_instruction_str->band_count_of_ch_group[g] > 1)
{ /* multiband DRC */
for (s=0; s<nDecoderSubbands; s++)
{
gainSb = 0.0f;
for (b=0; b<str_drc_instruction_str->band_count_of_ch_group[g]; b++)
{
if (str_drc_instruction_str->ch_group_parametric_drc_flag[g] == 0) {
lpcm_gains = pstr_gain_buf->buf_interpolation[gainIndexForGroup[g]+b].lpcm_gains + MAX_SIGNAL_DELAY - ia_drc_params_struct->gain_delay_samples - ia_drc_params_struct->audio_delay_samples + offset;
} else {
lpcm_gains = pstr_gain_buf->buf_interpolation[gainIndexForGroup[g]+b].lpcm_gains + MAX_SIGNAL_DELAY + str_drc_instruction_str->parametric_drc_look_ahead_samples[g] - ia_drc_params_struct->audio_delay_samples + analysisDelay;
}
/* get gain for this timeslot by downsampling */
gainLr = lpcm_gains[(m*L+(L-1)/2)];
gainSb += pstr_overlap_params->str_group_overlap_params[g].str_band_overlap_params[b].overlap_weight[s] * gainLr;
}
deinterleaved_audio_re[signalIndex][m*nDecoderSubbands+s] = gainSb * deinterleaved_audio_delayed_re[signalIndex][m*nDecoderSubbands+s];
if (ia_drc_params_struct->sub_band_domain_mode == SUBBAND_DOMAIN_MODE_STFT256) { /* For STFT filterbank, the real value of the nyquist band is stored at the imag value of the first band */
if (s != 0)
deinterleaved_audio_im[signalIndex][m*nDecoderSubbands+s] = gainSb * deinterleaved_audio_delayed_im[signalIndex][m*nDecoderSubbands+s];
if (s == (nDecoderSubbands-1))
deinterleaved_audio_im[signalIndex][m*nDecoderSubbands+0] = gainSb * deinterleaved_audio_delayed_im[signalIndex][m*nDecoderSubbands+0];
} else {
deinterleaved_audio_im[signalIndex][m*nDecoderSubbands+s] = gainSb * deinterleaved_audio_delayed_im[signalIndex][m*nDecoderSubbands+s];
}
}
}
else
{ /* single-band DRC */
if (str_drc_instruction_str->ch_group_parametric_drc_flag[g] == 0) {
lpcm_gains = pstr_gain_buf->buf_interpolation[gainIndexForGroup[g]].lpcm_gains + MAX_SIGNAL_DELAY - ia_drc_params_struct->gain_delay_samples - ia_drc_params_struct->audio_delay_samples + offset;
} else {
lpcm_gains = pstr_gain_buf->buf_interpolation[gainIndexForGroup[g]].lpcm_gains + MAX_SIGNAL_DELAY + str_drc_instruction_str->parametric_drc_look_ahead_samples[g] - ia_drc_params_struct->audio_delay_samples + analysisDelay;
}
/* get gain for this timeslot by downsampling */
gainSb = lpcm_gains[(m*L+(L-1)/2)];
for (s=0; s<nDecoderSubbands; s++)
{
deinterleaved_audio_re[signalIndex][m*nDecoderSubbands+s] = gainSb * deinterleaved_audio_delayed_re[signalIndex][m*nDecoderSubbands+s];
deinterleaved_audio_im[signalIndex][m*nDecoderSubbands+s] = gainSb * deinterleaved_audio_delayed_im[signalIndex][m*nDecoderSubbands+s];
}
}
}
}
signalIndex++;
}
}
}
}
return (0);
}
WORD32
impd_filter_banks_process(ia_drc_instructions_struct* pstr_drc_instruction_arr,
const WORD32 drc_instructions_index,
ia_drc_params_struct* ia_drc_params_struct,
FLOAT32* audio_io_buf[],
ia_audio_band_buffer_struct* audio_band_buffer,
ia_filter_banks_struct* ia_filter_banks_struct,
const WORD32 passThru)
{
WORD32 c, g, e, i, num_bands;
//WORD32 err = 0;
FLOAT32* audio_in;
FLOAT32** audio_out;
ia_drc_filter_bank_struct* str_drc_filter_bank;
ia_drc_instructions_struct* str_drc_instruction_str;
WORD32 drc_frame_size = ia_drc_params_struct->drc_frame_size;
if (drc_instructions_index >= 0) {
str_drc_instruction_str = &(pstr_drc_instruction_arr[drc_instructions_index]);
} else {
return -1;
}
e=0;
for (c=0; c<str_drc_instruction_str->audio_num_chan; c++)
{
str_drc_filter_bank = NULL;
audio_in = audio_io_buf[c];
audio_out = &(audio_band_buffer->non_interleaved_audio[e]);
if ((passThru == 0) && (drc_instructions_index >= 0))
{
if (str_drc_instruction_str->drc_set_id < 0)
{
num_bands = 1;
}
else
{
g = str_drc_instruction_str->channel_group_of_ch[c];
if (g== -1)
{
num_bands = 1;
//if (ia_filter_banks_struct->str_drc_filter_bank != NULL)
//{
str_drc_filter_bank = &(ia_filter_banks_struct->str_drc_filter_bank[str_drc_instruction_str->num_drc_ch_groups]);
//}
}
else
{
num_bands = str_drc_instruction_str->band_count_of_ch_group[g];
//if (ia_filter_banks_struct->str_drc_filter_bank != NULL)
//{
str_drc_filter_bank = &(ia_filter_banks_struct->str_drc_filter_bank[g]);
//}
}
//if (ia_filter_banks_struct->str_drc_filter_bank != NULL)
//{
//if (&str_drc_filter_bank->str_all_pass_cascade != NULL)
//{
impd_all_pass_cascade_process(&str_drc_filter_bank->str_all_pass_cascade, c, drc_frame_size, audio_in);
//}
//}
}
}
else
{
num_bands = 1;
}
switch (num_bands) {
case 1:
for (i=0; i<drc_frame_size; i++)
{
audio_out[0][i] = audio_in[i];
}
e++;
break;
case 2:
impd_two_band_filter_process(&str_drc_filter_bank->str_two_band_bank,
c,
drc_frame_size,
audio_in,
audio_out);
e+=2;
break;
case 3:
impd_three_band_filter_process(&str_drc_filter_bank->str_three_band_bank,
c,
drc_frame_size,
audio_in,
audio_out);
e+=3;
break;
case 4:
impd_four_band_filter_process(&str_drc_filter_bank->str_four_band_bank,
c,
drc_frame_size,
audio_in,
audio_out);
e+=4;
break;
default:
return (PARAM_ERROR);
break;
}
}
return (0);
}
WORD32
impd_store_audio_io_buffer_time(FLOAT32* audio_in_out_buf[],
ia_audio_in_out_buf* audio_io_buf_internal)
{
WORD32 i,j;
if (audio_io_buf_internal->audio_delay_samples) {
for (i=0; i<audio_io_buf_internal->audio_num_chan; i++) {
for (j=0; j<audio_io_buf_internal->frame_size; j++) {
audio_io_buf_internal->audio_io_buffer_delayed[i][audio_io_buf_internal->audio_delay_samples+j] = audio_in_out_buf[i][j];
}
}
} else {
audio_io_buf_internal->audio_io_buffer_delayed = audio_in_out_buf;
audio_io_buf_internal->audio_in_out_buf = audio_in_out_buf;
}
return 0;
}
WORD32
impd_store_audio_io_buffer_freq(FLOAT32* audio_real_buff[],
FLOAT32* audio_imag_buff[],
ia_audio_in_out_buf* audio_io_buf_internal)
{
WORD32 i,j;
if (audio_io_buf_internal->audio_delay_sub_band_samples) {
for (i=0; i<audio_io_buf_internal->audio_num_chan; i++) {
for (j=0; j<audio_io_buf_internal->audio_sub_band_frame_size*audio_io_buf_internal->audio_sub_band_count; j++) {
audio_io_buf_internal->audio_buffer_delayed_real[i][audio_io_buf_internal->audio_delay_sub_band_samples*audio_io_buf_internal->audio_sub_band_count+j] = audio_real_buff[i][j];
audio_io_buf_internal->audio_buffer_delayed_imag[i][audio_io_buf_internal->audio_delay_sub_band_samples*audio_io_buf_internal->audio_sub_band_count+j] = audio_imag_buff[i][j];
}
}
} else {
audio_io_buf_internal->audio_buffer_delayed_real = audio_real_buff;
audio_io_buf_internal->audio_buffer_delayed_imag = audio_imag_buff;
audio_io_buf_internal->audio_real_buff = audio_real_buff;
audio_io_buf_internal->audio_imag_buff = audio_imag_buff;
}
return 0;
}
WORD32
impd_retrieve_audio_io_buffer_time(FLOAT32* audio_in_out_buf[],
ia_audio_in_out_buf* audio_io_buf_internal)
{
WORD32 i,j;
if (audio_io_buf_internal->audio_delay_samples) {
for (i=0; i<audio_io_buf_internal->audio_num_chan; i++) {
for (j=0; j<audio_io_buf_internal->frame_size; j++) {
audio_in_out_buf[i][j] = audio_io_buf_internal->audio_io_buffer_delayed[i][j];
}
}
}
return 0;
}
WORD32
impd_retrieve_audio_buffer_freq(FLOAT32* audio_real_buff[],
FLOAT32* audio_imag_buff[],
ia_audio_in_out_buf* audio_io_buf_internal)
{
WORD32 i,j;
if (audio_io_buf_internal->audio_delay_sub_band_samples) {
for (i=0; i<audio_io_buf_internal->audio_num_chan; i++) {
for (j=0; j<audio_io_buf_internal->audio_sub_band_frame_size*audio_io_buf_internal->audio_sub_band_count; j++) {
audio_real_buff[i][j] = audio_io_buf_internal->audio_buffer_delayed_real[i][audio_io_buf_internal->audio_sub_band_count+j];
audio_imag_buff[i][j] = audio_io_buf_internal->audio_buffer_delayed_imag[i][audio_io_buf_internal->audio_sub_band_count+j];
}
}
}
return 0;
}
WORD32
impd_advance_audio_io_buffer_time(ia_audio_in_out_buf* audio_io_buf_internal)
{
WORD32 i;
if (audio_io_buf_internal->audio_delay_samples) {
for (i=0; i<audio_io_buf_internal->audio_num_chan; i++) {
memmove(audio_io_buf_internal->audio_io_buffer_delayed[i], &audio_io_buf_internal->audio_io_buffer_delayed[i][audio_io_buf_internal->frame_size],sizeof(FLOAT32) * audio_io_buf_internal->audio_delay_samples);
}
}
return 0;
}
WORD32
impd_advance_audio_buff_freq(ia_audio_in_out_buf* audio_io_buf_internal)
{
WORD32 i;
if (audio_io_buf_internal->audio_delay_sub_band_samples) {
for (i=0; i<audio_io_buf_internal->audio_num_chan; i++) {
memmove(audio_io_buf_internal->audio_buffer_delayed_real[i], &audio_io_buf_internal->audio_buffer_delayed_real[i][audio_io_buf_internal->audio_sub_band_frame_size * audio_io_buf_internal->audio_sub_band_count],sizeof(FLOAT32) * audio_io_buf_internal->audio_delay_sub_band_samples * audio_io_buf_internal->audio_sub_band_count);
memmove(audio_io_buf_internal->audio_buffer_delayed_imag[i], &audio_io_buf_internal->audio_buffer_delayed_imag[i][audio_io_buf_internal->audio_sub_band_frame_size * audio_io_buf_internal->audio_sub_band_count],sizeof(FLOAT32) * audio_io_buf_internal->audio_delay_sub_band_samples * audio_io_buf_internal->audio_sub_band_count);
}
}
return 0;
}