libxaac/decoder/drc_src/impd_drc_peak_limiter.c
Ray Essick 4908247643 Sanitization fixes from new CTS tests
Updates from vendor to remedy issues exposed by new CTS tests

Bug: 77287124
Test: CTS DecoderTest, DecoderTest{AacDrc,XheAac}

@ Sanitizer fixes in libxaac

Fixes few integer overflow sanitizer errors
Progagate few errors
ENABLE_DRC macro is removed
AMMENDMENT1 macro is removed

Change-Id: Ic61163dfd6318bd4a00ed45e1295c819cb0f637b

@ Add support for audio pre-roll and DRC effect type

Also includes the following
MPEG-D DRC parameters related changes
USAC config switch changes
SBR config switch changes

Bug: 80133175
Change-Id: I0ab25641768cf523b66f7b0fcb4137429c1c4a77

@ Fixed trailing spaces

Change-Id: I32de0c9d3f7237e1fbf8dfef1cac485ef8458173

@ Replaced tabs

Change-Id: Ic741ee13d7b978b37edc27d087903caaa40b8d90
2018-05-25 11:35:52 -07:00

193 lines
6.3 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 <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include "impd_type_def.h"
#include "impd_drc_peak_limiter.h"
#ifndef max
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
WORD32 impd_peak_limiter_init( ia_drc_peak_limiter_struct *peak_limiter,
FLOAT32 attack_time,
FLOAT32 release_time,
FLOAT32 limit_threshold,
UWORD32 num_channels,
UWORD32 sample_rate,
FLOAT32 *buffer
)
{
UWORD32 attack;
attack = (UWORD32)(attack_time * sample_rate / 1000);
if (attack < 1)
return 0;
peak_limiter->max_buf=buffer;
peak_limiter->delayed_input=buffer+attack*4+32;
peak_limiter->delayed_input_index = 0;
peak_limiter->attack_time = attack_time;
peak_limiter->release_time = release_time;
peak_limiter->attack_time_samples = attack;
peak_limiter->attack_constant = (FLOAT32)pow(0.1, 1.0 / (attack + 1));
peak_limiter->release_constant = (FLOAT32)pow(0.1, 1.0 / (release_time * sample_rate / 1000 + 1));
peak_limiter->limit_threshold = limit_threshold;
peak_limiter->num_channels = num_channels;
peak_limiter->sample_rate = sample_rate;
peak_limiter->min_gain = 1.0f;
peak_limiter->limiter_on=1;
peak_limiter->pre_smoothed_gain=1.0f;
peak_limiter->gain_modified=1.0f;
return 0;
}
WORD32 impd_peak_limiter_reinit(ia_drc_peak_limiter_struct *peak_limiter)
{
if (peak_limiter)
{
peak_limiter->delayed_input_index = 0;
peak_limiter->pre_smoothed_gain=1.0f;
peak_limiter->gain_modified=1.0f;
peak_limiter->min_gain = 1.0f;
memset(peak_limiter->max_buf, 0, (peak_limiter->attack_time_samples + 1) * sizeof(FLOAT32) );
memset(peak_limiter->delayed_input, 0, peak_limiter->attack_time_samples * peak_limiter->num_channels * sizeof(FLOAT32) );
}
return 0;
}
WORD32 impd_limiter_process(ia_drc_peak_limiter_struct *peak_limiter, FLOAT32 *samples, UWORD32 frame_len)
{
UWORD32 i, j;
FLOAT32 tmp, gain;
FLOAT32 min_gain = 1;
FLOAT32 maximum, sectionMaximum;
UWORD32 num_channels = peak_limiter->num_channels;
UWORD32 attack_time_samples = peak_limiter->attack_time_samples;
FLOAT32 attack_constant = peak_limiter->attack_constant;
FLOAT32 release_constant = peak_limiter->release_constant;
FLOAT32 limit_threshold = peak_limiter->limit_threshold;
FLOAT32* max_buf = peak_limiter->max_buf;
FLOAT32 gain_modified = peak_limiter->gain_modified;
FLOAT32* delayed_input = peak_limiter->delayed_input;
UWORD32 delayed_input_index = peak_limiter->delayed_input_index;
FLOAT64 pre_smoothed_gain = peak_limiter->pre_smoothed_gain;
if (peak_limiter->limiter_on || (FLOAT32)pre_smoothed_gain < 1.0f) {
for (i = 0; i < frame_len; i++) {
tmp =0.0f;
for (j = 0; j < num_channels; j++) {
tmp = max(tmp, (FLOAT32)fabs(samples[i * num_channels + j]));
}
for (j = attack_time_samples; j >0; j--) {
max_buf[j]=max_buf[j-1];
}
max_buf[0] = tmp;
sectionMaximum=tmp;
for (j = 1; j < (attack_time_samples+1); j++) {
if (max_buf[j] > sectionMaximum)
sectionMaximum = max_buf[j];
}
maximum=sectionMaximum;
if (maximum > limit_threshold) {
gain = limit_threshold / maximum;
}
else {
gain = 1;
}
if (gain < pre_smoothed_gain) {
gain_modified = min(gain_modified, (gain - 0.1f * (FLOAT32)pre_smoothed_gain) * 1.11111111f);
}
else {
gain_modified = gain;
}
if (gain_modified < pre_smoothed_gain) {
pre_smoothed_gain = attack_constant * (pre_smoothed_gain - gain_modified) + gain_modified;
pre_smoothed_gain = max(pre_smoothed_gain, gain);
}
else {
pre_smoothed_gain = release_constant * (pre_smoothed_gain - gain_modified) + gain_modified;
}
gain = (FLOAT32)pre_smoothed_gain;
for (j = 0; j < num_channels; j++) {
tmp = delayed_input[delayed_input_index * num_channels + j];
delayed_input[delayed_input_index * num_channels + j] = samples[i * num_channels + j];
tmp *= gain;
if (tmp > limit_threshold)
tmp = limit_threshold;
else if (tmp < -limit_threshold)
tmp = -limit_threshold;
samples[i * num_channels + j] = tmp;
}
delayed_input_index++;
if (delayed_input_index >= attack_time_samples)
delayed_input_index = 0;
if (gain < min_gain)
min_gain = gain;
}
}
else {
for (i = 0; i < frame_len; i++) {
for (j = 0; j < num_channels; j++) {
tmp = delayed_input[delayed_input_index * num_channels + j];
delayed_input[delayed_input_index * num_channels + j] = samples[i * num_channels + j];
samples[i * num_channels + j] = tmp;
}
delayed_input_index++;
if (delayed_input_index >= attack_time_samples)
delayed_input_index = 0;
}
}
peak_limiter->gain_modified = gain_modified;
peak_limiter->delayed_input_index = delayed_input_index;
peak_limiter->pre_smoothed_gain = pre_smoothed_gain;
peak_limiter->min_gain = min_gain;
return 0;
}