aboutsummaryrefslogtreecommitdiffstats
path: root/libAACdec/src
diff options
context:
space:
mode:
Diffstat (limited to 'libAACdec/src')
-rw-r--r--libAACdec/src/aacdec_drc.cpp165
-rw-r--r--libAACdec/src/aacdec_drc.h50
-rw-r--r--libAACdec/src/aacdec_drc_types.h9
3 files changed, 222 insertions, 2 deletions
diff --git a/libAACdec/src/aacdec_drc.cpp b/libAACdec/src/aacdec_drc.cpp
index 4129d0f..6066a64 100644
--- a/libAACdec/src/aacdec_drc.cpp
+++ b/libAACdec/src/aacdec_drc.cpp
@@ -150,6 +150,20 @@ static INT convert_drcParam(FIXP_DBL param_dbl) {
}
/*!
+\brief Reset DRC information
+
+\self Handle of DRC info
+
+\return none
+*/
+void aacDecoder_drcReset(HANDLE_AAC_DRC self) {
+ self->applyExtGain = 0;
+ self->additionalGainPrev = AACDEC_DRC_GAIN_INIT_VALUE;
+ self->additionalGainFilterState = AACDEC_DRC_GAIN_INIT_VALUE;
+ self->additionalGainFilterState1 = AACDEC_DRC_GAIN_INIT_VALUE;
+}
+
+/*!
\brief Initialize DRC information
\self Handle of DRC info
@@ -192,6 +206,8 @@ void aacDecoder_drcInit(HANDLE_AAC_DRC self) {
self->progRefLevelPresent = 0;
self->presMode = -1;
self->uniDrcPrecedence = 0;
+
+ aacDecoder_drcReset(self);
}
/*!
@@ -1353,3 +1369,152 @@ void aacDecoder_drcGetInfo(HANDLE_AAC_DRC self, SCHAR *pPresMode,
}
}
}
+
+/**
+ * \brief Apply DRC Level Normalization.
+ *
+ * This function prepares/applies the gain values for the DRC Level
+ * Normalization and returns the exponent of the time data. The following two
+ * cases are handled:
+ *
+ * - Limiter enabled:
+ * The input data must be interleaved.
+ * One gain per sample is written to the buffer pGainPerSample.
+ * If necessary the time data is rescaled.
+ *
+ * - Limiter disabled:
+ * The input data can be interleaved or deinterleaved.
+ * The gain values are applied to the time data.
+ * If necessary the time data is rescaled.
+ *
+ * \param hDrcInfo [i/o] handle to drc data structure.
+ * \param samplesIn [i/o] pointer to time data.
+ * \param pGain [i ] pointer to gain to be applied to
+ * the time data.
+ * \param pGainPerSample [o ] pointer to the gain per sample to
+ * be applied to the time data in the limiter.
+ * \param gain_scale [i ] exponent to be applied to the time
+ * data.
+ * \param gain_delay [i ] delay[samples] with which the gains
+ * in pGain shall be applied (gain_delay <= nSamples).
+ * \param nSamples [i ] number of samples per frame.
+ * \param channels [i ] number of channels.
+ * \param stride [i ] channel stride of time data.
+ * \param limiterEnabled [i ] 1 if limiter is enabled, otherwise
+ * 0.
+ *
+ * \return exponent of time data
+ */
+INT applyDrcLevelNormalization(HANDLE_AAC_DRC hDrcInfo, PCM_DEC *samplesIn,
+ FIXP_DBL *pGain, FIXP_DBL *pGainPerSample,
+ const INT gain_scale, const UINT gain_delay,
+ const UINT nSamples, const UINT channels,
+ const UINT stride, const UINT limiterEnabled) {
+ UINT i;
+ INT additionalGain_scaling;
+ FIXP_DBL additionalGain;
+
+ FDK_ASSERT(gain_delay <= nSamples);
+
+ FIXP_DBL additionalGainSmoothState = hDrcInfo->additionalGainFilterState;
+ FIXP_DBL additionalGainSmoothState1 = hDrcInfo->additionalGainFilterState1;
+
+ if (!gain_delay) {
+ additionalGain = pGain[0];
+
+ /* Apply the additional scaling gain_scale[0] that has no delay and no
+ * smoothing */
+ additionalGain_scaling =
+ fMin(gain_scale, CntLeadingZeros(additionalGain) - 1);
+ additionalGain = scaleValue(additionalGain, additionalGain_scaling);
+
+ /* if it's not possible to fully apply gain_scale to additionalGain, apply
+ * it to the input signal */
+ additionalGain_scaling -= gain_scale;
+
+ if (additionalGain_scaling) {
+ scaleValuesSaturate(samplesIn, channels * nSamples,
+ -additionalGain_scaling);
+ }
+
+ if (limiterEnabled) {
+ FDK_ASSERT(pGainPerSample != NULL);
+
+ for (i = 0; i < nSamples; i++) {
+ pGainPerSample[i] = additionalGain;
+ }
+ } else {
+ for (i = 0; i < channels * nSamples; i++) {
+ samplesIn[i] = FIXP_DBL2PCM_DEC(fMult(samplesIn[i], additionalGain));
+ }
+ }
+ } else {
+ UINT inc;
+ FIXP_DBL additionalGainUnfiltered;
+
+ inc = (stride == 1) ? channels : 1;
+
+ for (i = 0; i < nSamples; i++) {
+ if (i < gain_delay) {
+ additionalGainUnfiltered = hDrcInfo->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 gain_scale[0] that has no delay and no
+ * smoothing */
+ additionalGain_scaling =
+ fMin(gain_scale, CntLeadingZeros(additionalGain) - 1);
+ additionalGain = scaleValue(additionalGain, additionalGain_scaling);
+
+ /* if it's not possible to fully apply gain_scale[0] to additionalGain,
+ * apply it to the input signal */
+ additionalGain_scaling -= gain_scale;
+
+ if (limiterEnabled) {
+ FDK_ASSERT(stride == 1);
+ FDK_ASSERT(pGainPerSample != NULL);
+
+ if (additionalGain_scaling) {
+ scaleValuesSaturate(samplesIn, channels, -additionalGain_scaling);
+ }
+
+ pGainPerSample[i] = additionalGain;
+ } else {
+ if (additionalGain_scaling) {
+ for (UINT k = 0; k < channels; k++) {
+ scaleValuesSaturate(&samplesIn[k * stride], 1,
+ -additionalGain_scaling);
+ }
+ }
+
+ for (UINT k = 0; k < channels; k++) {
+ samplesIn[k * stride] =
+ FIXP_DBL2PCM_DEC(fMult(samplesIn[k * stride], additionalGain));
+ }
+ }
+
+ samplesIn += inc;
+ }
+ }
+
+ hDrcInfo->additionalGainPrev = pGain[0];
+ hDrcInfo->additionalGainFilterState = additionalGainSmoothState;
+ hDrcInfo->additionalGainFilterState1 = additionalGainSmoothState1;
+
+ return (AACDEC_DRC_GAIN_SCALING);
+}
diff --git a/libAACdec/src/aacdec_drc.h b/libAACdec/src/aacdec_drc.h
index 924ec6f..1873c5b 100644
--- a/libAACdec/src/aacdec_drc.h
+++ b/libAACdec/src/aacdec_drc.h
@@ -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,6 +109,11 @@ amm-info@iis.fraunhofer.de
#include "channel.h"
#include "FDK_bitstream.h"
+#define AACDEC_DRC_GAIN_SCALING (11) /* Scaling of DRC gains */
+#define AACDEC_DRC_GAIN_INIT_VALUE \
+ (FL2FXCONST_DBL( \
+ 1.0f / (1 << AACDEC_DRC_GAIN_SCALING))) /* Init value for DRC gains */
+
#define AACDEC_DRC_DFLT_EXPIRY_FRAMES \
(0) /* Default DRC data expiry time in AAC frames */
@@ -136,6 +141,8 @@ typedef enum {
/**
* \brief DRC module interface functions
*/
+void aacDecoder_drcReset(HANDLE_AAC_DRC self);
+
void aacDecoder_drcInit(HANDLE_AAC_DRC self);
void aacDecoder_drcInitChannelData(CDrcChannelData *pDrcChannel);
@@ -189,4 +196,45 @@ int aacDecoder_drcEpilog(
void aacDecoder_drcGetInfo(HANDLE_AAC_DRC self, SCHAR *pPresMode,
SCHAR *pProgRefLevel);
+/**
+ * \brief Apply DRC Level Normalization.
+ *
+ * This function prepares/applies the gain values for the DRC Level
+ * Normalization and returns the exponent of the time data. The following two
+ * cases are handled:
+ *
+ * - Limiter enabled:
+ * The input data must be interleaved.
+ * One gain per sample is written to the buffer pGainPerSample.
+ * If necessary the time data is rescaled.
+ *
+ * - Limiter disabled:
+ * The input data can be interleaved or deinterleaved.
+ * The gain values are applied to the time data.
+ * If necessary the time data is rescaled.
+ *
+ * \param hDrcInfo [i/o] handle to drc data structure.
+ * \param samplesIn [i/o] pointer to time data.
+ * \param pGain [i ] pointer to gain to be applied to
+ * the time data.
+ * \param pGainPerSample [o ] pointer to the gain per sample to
+ * be applied to the time data in the limiter.
+ * \param gain_scale [i ] exponent to be applied to the time
+ * data.
+ * \param gain_delay [i ] delay[samples] with which the gains
+ * in pGain shall be applied (gain_delay <= nSamples).
+ * \param nSamples [i ] number of samples per frame.
+ * \param channels [i ] number of channels.
+ * \param stride [i ] channel stride of time data.
+ * \param limiterEnabled [i ] 1 if limiter is enabled, otherwise
+ * 0.
+ *
+ * \return exponent of time data
+ */
+INT applyDrcLevelNormalization(HANDLE_AAC_DRC hDrcInfo, PCM_DEC *samplesIn,
+ FIXP_DBL *pGain, FIXP_DBL *pGainPerSample,
+ const INT gain_scale, const UINT gain_delay,
+ const UINT nSamples, const UINT channels,
+ const UINT stride, const UINT limiterEnabled);
+
#endif /* AACDEC_DRC_H */
diff --git a/libAACdec/src/aacdec_drc_types.h b/libAACdec/src/aacdec_drc_types.h
index 76c35d0..873bd60 100644
--- a/libAACdec/src/aacdec_drc_types.h
+++ b/libAACdec/src/aacdec_drc_types.h
@@ -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
@@ -213,6 +213,13 @@ typedef struct {
uniDrcPrecedence; /* Flag for signalling that uniDrc is active and takes
precedence over legacy DRC */
+ UCHAR applyExtGain; /* Flag is 1 if extGain has to be applied, otherwise 0. */
+
+ FIXP_DBL additionalGainPrev; /* Gain of previous frame to be applied to the
+ time data */
+ FIXP_DBL additionalGainFilterState; /* Filter state for the gain smoothing */
+ FIXP_DBL additionalGainFilterState1; /* Filter state for the gain smoothing */
+
} CDrcInfo;
typedef CDrcInfo *HANDLE_AAC_DRC;