1
0
mirror of https://github.com/mstorsjo/fdk-aac.git synced 2025-06-05 22:39:13 +02:00

Avoid decoder internal clipping by converting the whole audio sample data path from 16 to 32 bit data width (FDKdec v3.2.0).

Bug: 149514474
Test: atest DecoderTestXheAac DecoderTestAacDrc
Change-Id: I8a504ab709e42e27a61fe29840212953742283a5
This commit is contained in:
Fraunhofer IIS FDK
2019-12-19 17:28:15 +01:00
committed by Jean-Michel Trivi
parent 57c9355de0
commit e016635f0d
41 changed files with 488 additions and 442 deletions

View File

@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -109,8 +109,6 @@ amm-info@iis.fraunhofer.de
#define TDL_ATTACK_DEFAULT_MS (15) /* default attack time in ms */
#define TDL_RELEASE_DEFAULT_MS (50) /* default release time in ms */
#define TDL_GAIN_SCALING (15) /* scaling of gain value. */
#ifdef __cplusplus
extern "C" {
#endif
@@ -128,10 +126,7 @@ struct TDLimiter {
unsigned int maxBufIdx, delayBufIdx;
FIXP_DBL smoothState0;
FIXP_DBL minGain;
FIXP_DBL additionalGainPrev;
FIXP_DBL additionalGainFilterState;
FIXP_DBL additionalGainFilterState1;
INT scaling;
};
typedef enum {
@@ -255,27 +250,16 @@ TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter,
/******************************************************************************
* pcmLimiter_Apply *
* limiter: limiter handle *
* pGain : pointer to gains to be applied to the signal before limiting, *
* which are downscaled by TDL_GAIN_SCALING bit. *
* These gains are delayed by gain_delay, and smoothed. *
* Smoothing is done by a butterworth lowpass filter with a cutoff *
* frequency which is fixed with respect to the sampling rate. *
* It is a substitute for the smoothing due to windowing and *
* overlap/add, if a gain is applied in frequency domain. *
* gain_scale: pointer to scaling exponents to be applied to the signal before *
* limiting, without delay and without smoothing *
* gain_size: number of elements in pGain, currently restricted to 1 *
* gain_delay: delay [samples] with which the gains in pGain shall be applied *
* gain_delay <= nSamples *
* samples: input/output buffer containing interleaved samples *
* precision of output will be DFRACT_BITS-TDL_GAIN_SCALING bits *
* nSamples: number of samples per channel *
* limiter: limiter handle *
* samplesIn: pointer to input buffer containing interleaved samples *
* samplesOut: pointer to output buffer containing interleaved samples *
* pGainPerSample: pointer to gains for each sample *
* scaling: scaling of output samples *
* nSamples: number of samples per channel *
* returns: error code *
******************************************************************************/
TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
INT_PCM* samplesOut, FIXP_DBL* pGain,
const INT* gain_scale, const UINT gain_size,
const UINT gain_delay, const UINT nSamples);
INT_PCM* samplesOut, FIXP_DBL* pGainPerSample,
const INT scaling, const UINT nSamples);
#endif /* #ifndef LIMITER_H */

View File

@@ -152,7 +152,7 @@ TDLimiterPtr pcmLimiter_Create(unsigned int maxAttackMs, unsigned int releaseMs,
limiter->attack = attack;
limiter->attackConst = attackConst;
limiter->releaseConst = releaseConst;
limiter->threshold = threshold >> TDL_GAIN_SCALING;
limiter->threshold = threshold;
limiter->channels = maxChannels;
limiter->maxChannels = maxChannels;
limiter->sampleRate = maxSampleRate;
@@ -165,18 +165,13 @@ TDLimiterPtr pcmLimiter_Create(unsigned int maxAttackMs, unsigned int releaseMs,
/* apply limiter */
TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
INT_PCM* samplesOut, FIXP_DBL* RESTRICT pGain,
const INT* RESTRICT gain_scale,
const UINT gain_size, const UINT gain_delay,
const UINT nSamples) {
INT_PCM* samplesOut, FIXP_DBL* pGainPerSample,
const INT scaling, const UINT nSamples) {
unsigned int i, j;
FIXP_DBL tmp1;
FIXP_DBL tmp2;
FIXP_DBL tmp, old, gain, additionalGain = 0, additionalGainUnfiltered;
FIXP_DBL tmp, old, gain, additionalGain = 0;
FIXP_DBL minGain = FL2FXCONST_DBL(1.0f / (1 << 1));
FDK_ASSERT(gain_size == 1);
FDK_ASSERT(gain_delay <= nSamples);
UINT additionalGainAvailable = 1;
if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
@@ -185,7 +180,7 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
unsigned int attack = limiter->attack;
FIXP_DBL attackConst = limiter->attackConst;
FIXP_DBL releaseConst = limiter->releaseConst;
FIXP_DBL threshold = limiter->threshold;
FIXP_DBL threshold = limiter->threshold >> scaling;
FIXP_DBL max = limiter->max;
FIXP_DBL* maxBuf = limiter->maxBuf;
@@ -195,55 +190,34 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
unsigned int delayBufIdx = limiter->delayBufIdx;
FIXP_DBL smoothState0 = limiter->smoothState0;
FIXP_DBL additionalGainSmoothState = limiter->additionalGainFilterState;
FIXP_DBL additionalGainSmoothState1 = limiter->additionalGainFilterState1;
if (!gain_delay) {
additionalGain = pGain[0];
if (gain_scale[0] > 0) {
additionalGain <<= gain_scale[0];
} else {
additionalGain >>= -gain_scale[0];
}
if (limiter->scaling != scaling) {
scaleValuesSaturate(delayBuf, attack * channels,
limiter->scaling - scaling);
scaleValuesSaturate(maxBuf, attack + 1, limiter->scaling - scaling);
max = scaleValueSaturate(max, limiter->scaling - scaling);
limiter->scaling = scaling;
}
if (pGainPerSample == NULL) {
additionalGainAvailable = 0;
}
for (i = 0; i < nSamples; i++) {
if (gain_delay) {
if (i < gain_delay) {
additionalGainUnfiltered = limiter->additionalGainPrev;
} else {
additionalGainUnfiltered = pGain[0];
}
/* Smooth additionalGain */
/* [b,a] = butter(1, 0.01) */
static const FIXP_SGL b[] = {FL2FXCONST_SGL(0.015466 * 2.0),
FL2FXCONST_SGL(0.015466 * 2.0)};
static const FIXP_SGL a[] = {(FIXP_SGL)MAXVAL_SGL,
FL2FXCONST_SGL(-0.96907)};
additionalGain = -fMult(additionalGainSmoothState, a[1]) +
fMultDiv2(additionalGainUnfiltered, b[0]) +
fMultDiv2(additionalGainSmoothState1, b[1]);
additionalGainSmoothState1 = additionalGainUnfiltered;
additionalGainSmoothState = additionalGain;
/* Apply the additional scaling that has no delay and no smoothing */
if (gain_scale[0] > 0) {
additionalGain <<= gain_scale[0];
} else {
additionalGain >>= -gain_scale[0];
}
}
/* get maximum absolute sample value of all channels, including the
* additional gain. */
tmp1 = (FIXP_DBL)0;
tmp = (FIXP_DBL)0;
for (j = 0; j < channels; j++) {
tmp2 = PCM_LIM2FIXP_DBL(samplesIn[j]);
tmp2 =
(tmp2 == (FIXP_DBL)MINVAL_DBL) ? (FIXP_DBL)MAXVAL_DBL : fAbs(tmp2);
tmp1 = fMax(tmp1, tmp2);
tmp = fMax(tmp, tmp2);
}
if (additionalGainAvailable) {
additionalGain = pGainPerSample[i];
tmp = fMult(tmp, additionalGain);
}
tmp = fMult(tmp1, additionalGain);
/* set threshold as lower border to save calculations in running maximum
* algorithm */
@@ -314,22 +288,42 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
/* lookahead delay, apply gain */
for (j = 0; j < channels; j++) {
tmp = p_delayBuf[j];
p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain);
if (additionalGainAvailable) {
p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain);
} else {
p_delayBuf[j] = PCM_LIM2FIXP_DBL(samplesIn[j]);
}
/* Apply gain to delayed signal */
tmp = fMultDiv2(tmp, gain);
#if (SAMPLE_BITS == DFRACT_BITS)
samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM(
(FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling + 1, DFRACT_BITS));
#else
samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT(
tmp, TDL_GAIN_SCALING + 1, DFRACT_BITS));
tmp + ((FIXP_DBL)0x8000 >> (scaling + 1)), scaling + 1,
DFRACT_BITS));
#endif
}
gain >>= 1;
} else {
/* lookahead delay, apply gain=1.0f */
for (j = 0; j < channels; j++) {
tmp = p_delayBuf[j];
p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain);
if (additionalGainAvailable) {
p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain);
} else {
p_delayBuf[j] = PCM_LIM2FIXP_DBL(samplesIn[j]);
}
#if (SAMPLE_BITS == DFRACT_BITS)
samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM(
(FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling, DFRACT_BITS));
#else
samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT(
tmp, TDL_GAIN_SCALING, DFRACT_BITS));
tmp + ((FIXP_DBL)0x8000 >> scaling), scaling, DFRACT_BITS));
#endif
}
}
@@ -354,13 +348,9 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
limiter->delayBufIdx = delayBufIdx;
limiter->smoothState0 = smoothState0;
limiter->additionalGainFilterState = additionalGainSmoothState;
limiter->additionalGainFilterState1 = additionalGainSmoothState1;
limiter->minGain = minGain;
limiter->additionalGainPrev = pGain[0];
return TDLIMIT_OK;
}
}
@@ -370,7 +360,7 @@ TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter,
FIXP_DBL threshold) {
if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
limiter->threshold = threshold >> TDL_GAIN_SCALING;
limiter->threshold = threshold;
return TDLIMIT_OK;
}
@@ -384,13 +374,7 @@ TDLIMITER_ERROR pcmLimiter_Reset(TDLimiterPtr limiter) {
limiter->cor = FL2FXCONST_DBL(1.0f / (1 << 1));
limiter->smoothState0 = FL2FXCONST_DBL(1.0f / (1 << 1));
limiter->minGain = FL2FXCONST_DBL(1.0f / (1 << 1));
limiter->additionalGainPrev =
FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING));
limiter->additionalGainFilterState =
FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING));
limiter->additionalGainFilterState1 =
FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING));
limiter->scaling = 0;
FDKmemset(limiter->maxBuf, 0, (limiter->attack + 1) * sizeof(FIXP_DBL));
FDKmemset(limiter->delayBuf, 0,

View File

@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -105,7 +105,7 @@ amm-info@iis.fraunhofer.de
/* library info */
#define PCMUTIL_LIB_VL0 3
#define PCMUTIL_LIB_VL1 0
#define PCMUTIL_LIB_VL1 1
#define PCMUTIL_LIB_VL2 0
#define PCMUTIL_LIB_TITLE "PCM Utility Lib"
#ifdef __ANDROID__