aboutsummaryrefslogtreecommitdiffstats
path: root/libAACdec/src
diff options
context:
space:
mode:
Diffstat (limited to 'libAACdec/src')
-rw-r--r--libAACdec/src/FDK_delay.cpp26
-rw-r--r--libAACdec/src/FDK_delay.h6
-rw-r--r--libAACdec/src/aac_ram.cpp10
-rw-r--r--libAACdec/src/aac_ram.h7
-rw-r--r--libAACdec/src/aac_rom.h3
-rw-r--r--libAACdec/src/aacdec_drc.cpp187
-rw-r--r--libAACdec/src/aacdec_drc.h51
-rw-r--r--libAACdec/src/aacdec_drc_types.h10
-rw-r--r--libAACdec/src/aacdec_hcr.cpp31
-rw-r--r--libAACdec/src/aacdec_hcrs.cpp6
-rw-r--r--libAACdec/src/aacdecoder.cpp89
-rw-r--r--libAACdec/src/aacdecoder.h11
-rw-r--r--libAACdec/src/aacdecoder_lib.cpp272
-rw-r--r--libAACdec/src/block.cpp12
-rw-r--r--libAACdec/src/block.h8
-rw-r--r--libAACdec/src/conceal.cpp57
-rw-r--r--libAACdec/src/conceal.h4
-rw-r--r--libAACdec/src/conceal_types.h4
-rw-r--r--libAACdec/src/ldfiltbank.cpp53
-rw-r--r--libAACdec/src/ldfiltbank.h5
-rw-r--r--libAACdec/src/stereo.cpp70
-rw-r--r--libAACdec/src/usacdec_acelp.cpp27
-rw-r--r--libAACdec/src/usacdec_fac.cpp36
-rw-r--r--libAACdec/src/usacdec_lpc.cpp36
-rw-r--r--libAACdec/src/usacdec_lpd.cpp56
-rw-r--r--libAACdec/src/usacdec_lpd.h19
26 files changed, 706 insertions, 390 deletions
diff --git a/libAACdec/src/FDK_delay.cpp b/libAACdec/src/FDK_delay.cpp
index 0ab1a66..0cc869c 100644
--- a/libAACdec/src/FDK_delay.cpp
+++ b/libAACdec/src/FDK_delay.cpp
@@ -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
@@ -113,7 +113,7 @@ INT FDK_Delay_Create(FDK_SignalDelay* data, const USHORT delay,
if (delay > 0) {
data->delay_line =
- (INT_PCM*)FDKcalloc(num_channels * delay, sizeof(INT_PCM));
+ (PCM_DEC*)FDKcalloc(num_channels * delay, sizeof(PCM_DEC));
if (data->delay_line == NULL) {
return -1;
}
@@ -126,36 +126,36 @@ INT FDK_Delay_Create(FDK_SignalDelay* data, const USHORT delay,
return 0;
}
-void FDK_Delay_Apply(FDK_SignalDelay* data, FIXP_PCM* time_buffer,
+void FDK_Delay_Apply(FDK_SignalDelay* data, PCM_DEC* time_buffer,
const UINT frame_length, const UCHAR channel) {
FDK_ASSERT(data != NULL);
if (data->delay > 0) {
- C_ALLOC_SCRATCH_START(tmp, FIXP_PCM, MAX_FRAME_LENGTH)
+ C_ALLOC_SCRATCH_START(tmp, PCM_DEC, MAX_FRAME_LENGTH)
FDK_ASSERT(frame_length <= MAX_FRAME_LENGTH);
FDK_ASSERT(channel < data->num_channels);
FDK_ASSERT(time_buffer != NULL);
if (frame_length >= data->delay) {
FDKmemcpy(tmp, &time_buffer[frame_length - data->delay],
- data->delay * sizeof(FIXP_PCM));
+ data->delay * sizeof(PCM_DEC));
FDKmemmove(&time_buffer[data->delay], &time_buffer[0],
- (frame_length - data->delay) * sizeof(FIXP_PCM));
+ (frame_length - data->delay) * sizeof(PCM_DEC));
FDKmemcpy(&time_buffer[0], &data->delay_line[channel * data->delay],
- data->delay * sizeof(FIXP_PCM));
+ data->delay * sizeof(PCM_DEC));
FDKmemcpy(&data->delay_line[channel * data->delay], tmp,
- data->delay * sizeof(FIXP_PCM));
+ data->delay * sizeof(PCM_DEC));
} else {
- FDKmemcpy(tmp, &time_buffer[0], frame_length * sizeof(FIXP_PCM));
+ FDKmemcpy(tmp, &time_buffer[0], frame_length * sizeof(PCM_DEC));
FDKmemcpy(&time_buffer[0], &data->delay_line[channel * data->delay],
- frame_length * sizeof(FIXP_PCM));
+ frame_length * sizeof(PCM_DEC));
FDKmemcpy(&data->delay_line[channel * data->delay],
&data->delay_line[channel * data->delay + frame_length],
- (data->delay - frame_length) * sizeof(FIXP_PCM));
+ (data->delay - frame_length) * sizeof(PCM_DEC));
FDKmemcpy(&data->delay_line[channel * data->delay +
(data->delay - frame_length)],
- tmp, frame_length * sizeof(FIXP_PCM));
+ tmp, frame_length * sizeof(PCM_DEC));
}
- C_ALLOC_SCRATCH_END(tmp, FIXP_PCM, MAX_FRAME_LENGTH)
+ C_ALLOC_SCRATCH_END(tmp, PCM_DEC, MAX_FRAME_LENGTH)
}
return;
diff --git a/libAACdec/src/FDK_delay.h b/libAACdec/src/FDK_delay.h
index f89c3a2..6317d9d 100644
--- a/libAACdec/src/FDK_delay.h
+++ b/libAACdec/src/FDK_delay.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,7 +109,7 @@ amm-info@iis.fraunhofer.de
* Structure representing one delay element for multiple channels.
*/
typedef struct {
- INT_PCM* delay_line; /*!< Pointer which stores allocated delay line. */
+ PCM_DEC* delay_line; /*!< Pointer which stores allocated delay line. */
USHORT delay; /*!< Delay required in samples (per channel). */
UCHAR num_channels; /*!< Number of channels to delay. */
} FDK_SignalDelay;
@@ -137,7 +137,7 @@ INT FDK_Delay_Create(FDK_SignalDelay* data, const USHORT delay,
*
* \return void
*/
-void FDK_Delay_Apply(FDK_SignalDelay* data, FIXP_PCM* time_buffer,
+void FDK_Delay_Apply(FDK_SignalDelay* data, PCM_DEC* time_buffer,
const UINT frame_length, const UCHAR channel);
/**
diff --git a/libAACdec/src/aac_ram.cpp b/libAACdec/src/aac_ram.cpp
index e13167d..aa8f6a6 100644
--- a/libAACdec/src/aac_ram.cpp
+++ b/libAACdec/src/aac_ram.cpp
@@ -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,12 +105,7 @@ amm-info@iis.fraunhofer.de
#define WORKBUFFER1_TAG 0
#define WORKBUFFER2_TAG 1
-
-#define WORKBUFFER3_TAG 4
-#define WORKBUFFER4_TAG 5
-
#define WORKBUFFER5_TAG 6
-
#define WORKBUFFER6_TAG 7
/*! The structure AAC_DECODER_INSTANCE is the top level structure holding all
@@ -169,9 +164,6 @@ C_ALLOC_MEM2(TimeDataFlush, INT_PCM, TIME_DATA_FLUSH_SIZE, (8))
C_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL, ((8) * 1024), SECT_DATA_L2,
WORKBUFFER2_TAG)
-C_ALLOC_MEM_OVERLAY(WorkBufferCore3, FIXP_DBL, WB_SECTION_SIZE, SECT_DATA_L2,
- WORKBUFFER3_TAG)
-C_AALLOC_MEM(WorkBufferCore4, FIXP_DBL, WB_SECTION_SIZE)
C_ALLOC_MEM_OVERLAY(WorkBufferCore6, SCHAR,
fMax((INT)(sizeof(FIXP_DBL) * WB_SECTION_SIZE),
(INT)sizeof(CAacDecoderCommonData)),
diff --git a/libAACdec/src/aac_ram.h b/libAACdec/src/aac_ram.h
index a861e25..b9b95b7 100644
--- a/libAACdec/src/aac_ram.h
+++ b/libAACdec/src/aac_ram.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
@@ -136,12 +136,7 @@ H_ALLOC_MEM(TimeDataFlush, INT_PCM)
H_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1)
H_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL)
-
-H_ALLOC_MEM_OVERLAY(WorkBufferCore3, FIXP_DBL)
-H_ALLOC_MEM(WorkBufferCore4, FIXP_DBL)
-
H_ALLOC_MEM_OVERLAY(WorkBufferCore5, PCM_DEC)
-
H_ALLOC_MEM_OVERLAY(WorkBufferCore6, SCHAR)
#endif /* #ifndef AAC_RAM_H */
diff --git a/libAACdec/src/aac_rom.h b/libAACdec/src/aac_rom.h
index ffaf951..7a1597c 100644
--- a/libAACdec/src/aac_rom.h
+++ b/libAACdec/src/aac_rom.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
@@ -108,6 +108,7 @@ amm-info@iis.fraunhofer.de
#include "aacdec_hcr_types.h"
#include "aacdec_hcrs.h"
+#define PCM_AAC LONG
#define PCM_DEC FIXP_DBL
#define MAXVAL_PCM_DEC MAXVAL_DBL
#define MINVAL_PCM_DEC MINVAL_DBL
diff --git a/libAACdec/src/aacdec_drc.cpp b/libAACdec/src/aacdec_drc.cpp
index 4129d0f..b6f5b49 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
@@ -176,7 +190,6 @@ void aacDecoder_drcInit(HANDLE_AAC_DRC self) {
pParams->usrBoost = FL2FXCONST_DBL(0.0f);
pParams->targetRefLevel = 96;
pParams->expiryFrame = AACDEC_DRC_DFLT_EXPIRY_FRAMES;
- pParams->applyDigitalNorm = ON;
pParams->applyHeavyCompression = OFF;
pParams->usrApplyHeavyCompression = OFF;
@@ -192,6 +205,8 @@ void aacDecoder_drcInit(HANDLE_AAC_DRC self) {
self->progRefLevelPresent = 0;
self->presMode = -1;
self->uniDrcPrecedence = 0;
+
+ aacDecoder_drcReset(self);
}
/*!
@@ -258,11 +273,8 @@ AAC_DECODER_ERROR aacDecoder_drcSetParam(HANDLE_AAC_DRC self,
return AAC_DEC_INVALID_HANDLE;
}
if (value < 0) {
- self->params.applyDigitalNorm = OFF;
self->params.targetRefLevel = -1;
} else {
- /* ref_level must be between 0 and MAX_REFERENCE_LEVEL, inclusive */
- self->params.applyDigitalNorm = ON;
if (self->params.targetRefLevel != (SCHAR)value) {
self->params.targetRefLevel = (SCHAR)value;
self->progRefLevel = (SCHAR)value; /* Always set the program reference
@@ -273,16 +285,6 @@ AAC_DECODER_ERROR aacDecoder_drcSetParam(HANDLE_AAC_DRC self,
self->update = 1;
}
break;
- case APPLY_NORMALIZATION:
- if ((value != OFF) && (value != ON)) {
- return AAC_DEC_SET_PARAM_FAIL;
- }
- if (self == NULL) {
- return AAC_DEC_INVALID_HANDLE;
- }
- /* Store new parameter value */
- self->params.applyDigitalNorm = (UCHAR)value;
- break;
case APPLY_HEAVY_COMPRESSION:
if ((value != OFF) && (value != ON)) {
return AAC_DEC_SET_PARAM_FAIL;
@@ -910,11 +912,9 @@ void aacDecoder_drcApply(HANDLE_AAC_DRC self, void *pSbrDec,
FDK_ASSERT(0);
}
}
- if (self->params.applyDigitalNorm == OFF) {
- /* Reset normalization gain since this module must not apply it */
- norm_mantissa = FL2FXCONST_DBL(0.5f);
- norm_exponent = 1;
- }
+ /* Reset normalization gain since this module must not apply it */
+ norm_mantissa = FL2FXCONST_DBL(0.5f);
+ norm_exponent = 1;
/* calc scale factors */
for (band = 0; band < numBands; band++) {
@@ -1353,3 +1353,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..76a44d6 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 */
@@ -125,7 +130,6 @@ typedef enum {
TARGET_REF_LEVEL,
DRC_BS_DELAY,
DRC_DATA_EXPIRY_FRAME,
- APPLY_NORMALIZATION,
APPLY_HEAVY_COMPRESSION,
DEFAULT_PRESENTATION_MODE,
ENCODER_TARGET_LEVEL,
@@ -136,6 +140,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 +195,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..d4393f7 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
@@ -168,7 +168,6 @@ typedef struct {
UINT expiryFrame;
UCHAR bsDelayEnable;
- UCHAR applyDigitalNorm;
AACDEC_DRC_PARAMETER_HANDLING defaultPresentationMode;
UCHAR encoderTargetLevel;
@@ -213,6 +212,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;
diff --git a/libAACdec/src/aacdec_hcr.cpp b/libAACdec/src/aacdec_hcr.cpp
index 26fdd97..a7e9cce 100644
--- a/libAACdec/src/aacdec_hcr.cpp
+++ b/libAACdec/src/aacdec_hcr.cpp
@@ -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
@@ -137,7 +137,7 @@ static void DeriveNumberOfExtendedSortedSectionsInSets(
static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor,
INT quantSpecCoef, INT *pLeftStartOfSegment,
SCHAR *pRemainingBitsInSegment,
- int *pNumDecodedBits);
+ int *pNumDecodedBits, UINT *errorWord);
static int DecodePCW_Sign(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor,
UINT codebookDim, const SCHAR *pQuantVal,
@@ -1179,8 +1179,8 @@ static void DecodePCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr) {
bs, pHcr->decInOut.bitstreamAnchor,
pQuantizedSpectralCoefficients
[quantizedSpectralCoefficientsIdx],
- pLeftStartOfSegment, pRemainingBitsInSegment,
- &numDecodedBits);
+ pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits,
+ &pHcr->decInOut.errorLog);
}
quantizedSpectralCoefficientsIdx++;
if (quantizedSpectralCoefficientsIdx >= 1024) {
@@ -1195,8 +1195,8 @@ static void DecodePCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr) {
bs, pHcr->decInOut.bitstreamAnchor,
pQuantizedSpectralCoefficients
[quantizedSpectralCoefficientsIdx],
- pLeftStartOfSegment, pRemainingBitsInSegment,
- &numDecodedBits);
+ pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits,
+ &pHcr->decInOut.errorLog);
}
quantizedSpectralCoefficientsIdx++;
if (quantizedSpectralCoefficientsIdx >= 1024) {
@@ -1386,7 +1386,7 @@ value == 16, a escapeSequence is decoded in two steps:
static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor,
INT quantSpecCoef, INT *pLeftStartOfSegment,
SCHAR *pRemainingBitsInSegment,
- int *pNumDecodedBits) {
+ int *pNumDecodedBits, UINT *errorWord) {
UINT i;
INT sign;
UINT escapeOnesCounter = 0;
@@ -1400,6 +1400,9 @@ static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor,
FROM_LEFT_TO_RIGHT);
*pRemainingBitsInSegment -= 1;
*pNumDecodedBits += 1;
+ if (*pRemainingBitsInSegment < 0) {
+ return Q_VALUE_INVALID;
+ }
if (carryBit != 0) {
escapeOnesCounter += 1;
@@ -1416,6 +1419,9 @@ static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor,
FROM_LEFT_TO_RIGHT);
*pRemainingBitsInSegment -= 1;
*pNumDecodedBits += 1;
+ if (*pRemainingBitsInSegment < 0) {
+ return Q_VALUE_INVALID;
+ }
escape_word <<= 1;
escape_word = escape_word | carryBit;
@@ -1423,11 +1429,12 @@ static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor,
sign = (quantSpecCoef >= 0) ? 1 : -1;
- if (escapeOnesCounter > 30)
- escapeOnesCounter = 30;
-
- quantSpecCoef = sign * (((INT)1 << escapeOnesCounter) + escape_word);
-
+ if (escapeOnesCounter < 13) {
+ quantSpecCoef = sign * (((INT)1 << escapeOnesCounter) + escape_word);
+ } else {
+ *errorWord |= TOO_MANY_PCW_BODY_SIGN_ESC_BITS_DECODED;
+ quantSpecCoef = Q_VALUE_INVALID;
+ }
return quantSpecCoef;
}
diff --git a/libAACdec/src/aacdec_hcrs.cpp b/libAACdec/src/aacdec_hcrs.cpp
index d2bc867..44b32a5 100644
--- a/libAACdec/src/aacdec_hcrs.cpp
+++ b/libAACdec/src/aacdec_hcrs.cpp
@@ -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
@@ -1324,6 +1324,10 @@ UINT Hcr_State_BODY_SIGN_ESC__ESC_PREFIX(HANDLE_FDK_BITSTREAM bs, void *ptr) {
/* count ones and store sum in escapePrefixUp */
if (carryBit == 1) {
escapePrefixUp += 1; /* update conter for ones */
+ if (escapePrefixUp > 8) {
+ pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_PREFIX;
+ return BODY_SIGN_ESC__ESC_PREFIX;
+ }
/* store updated counter in sideinfo of current codeword */
pEscapeSequenceInfo[codewordOffset] &=
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp
index 7617937..965631b 100644
--- a/libAACdec/src/aacdecoder.cpp
+++ b/libAACdec/src/aacdecoder.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -1225,6 +1225,8 @@ static void CStreamInfoInit(CStreamInfo *pStreamInfo) {
pStreamInfo->drcProgRefLev =
-1; /* set program reference level to not indicated */
pStreamInfo->drcPresMode = -1; /* default: presentation mode not indicated */
+
+ pStreamInfo->outputLoudness = -1; /* default: no loudness metadata present */
}
/*!
@@ -1279,6 +1281,7 @@ LINKSPEC_CPP HANDLE_AACDECODER CAacDecoder_Open(
/* Set default frame delay */
aacDecoder_drcSetParam(self->hDrcInfo, DRC_BS_DELAY,
CConcealment_GetDelay(&self->concealCommonData));
+ self->workBufferCore1 = (FIXP_DBL *)GetWorkBufferCore1();
self->workBufferCore2 = GetWorkBufferCore2();
if (self->workBufferCore2 == NULL) goto bail;
@@ -1303,7 +1306,8 @@ static void CAacDecoder_DeInit(HANDLE_AACDECODER self,
const int subStreamIndex) {
int ch;
int aacChannelOffset = 0, aacChannels = (8);
- int numElements = (((8)) + (8)), elementOffset = 0;
+ int numElements = (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1),
+ elementOffset = 0;
if (self == NULL) return;
@@ -1453,6 +1457,10 @@ LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self) {
FreeDrcInfo(&self->hDrcInfo);
}
+ if (self->workBufferCore1 != NULL) {
+ FreeWorkBufferCore1((CWorkBufferCore1 **)&self->workBufferCore1);
+ }
+
/* Free WorkBufferCore2 */
if (self->workBufferCore2 != NULL) {
FreeWorkBufferCore2(&self->workBufferCore2);
@@ -1490,6 +1498,8 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
UCHAR downscaleFactor = self->downscaleFactor;
UCHAR downscaleFactorInBS = self->downscaleFactorInBS;
+ self->aacOutDataHeadroom = (3);
+
// set profile and check for supported aot
// leave profile on default (=-1) for all other supported MPEG-4 aot's except
// aot=2 (=AAC-LC)
@@ -1847,6 +1857,12 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
self->streamInfo.extSamplingRate / self->downscaleFactor;
}
}
+ if ((asc->m_aot == AOT_AAC_LC) && (asc->m_sbrPresentFlag == 1) &&
+ (asc->m_extensionSamplingFrequency > (2 * asc->m_samplingFrequency))) {
+ return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; /* Core decoder supports at most a
+ 1:2 upsampling for HE-AAC and
+ HE-AACv2 */
+ }
/* --------- vcb11 ------------ */
self->flags[streamIndex] |= (asc->m_vcb11Flag) ? AC_ER_VCB11 : 0;
@@ -1928,6 +1944,9 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
self->samplingRateInfo[0].samplingRate / self->downscaleFactor;
self->streamInfo.aacSamplesPerFrame =
asc->m_samplesPerFrame / self->downscaleFactor;
+ if (self->streamInfo.aacSampleRate <= 0) {
+ return AAC_DEC_UNSUPPORTED_SAMPLINGRATE;
+ }
}
}
@@ -2362,6 +2381,13 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
goto bail;
}
+ if (*configChanged) {
+ if (asc->m_aot == AOT_USAC) {
+ self->hDrcInfo->enable = 0;
+ self->hDrcInfo->progRefLevelPresent = 0;
+ }
+ }
+
if (asc->m_aot == AOT_USAC) {
pcmLimiter_SetAttack(self->hLimiter, (5));
pcmLimiter_SetThreshold(self->hLimiter, FL2FXCONST_DBL(0.89125094f));
@@ -2375,7 +2401,7 @@ bail:
}
LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
- HANDLE_AACDECODER self, const UINT flags, FIXP_PCM *pTimeData,
+ HANDLE_AACDECODER self, const UINT flags, PCM_DEC *pTimeData,
const INT timeDataSize, const int timeDataChannelOffset) {
AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
@@ -3151,11 +3177,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
FDKmemcpy(drcChMap, self->chMapping, (8) * sizeof(UCHAR));
}
- /* Turn on/off DRC modules level normalization in digital domain depending
- * on the limiter status. */
- aacDecoder_drcSetParam(self->hDrcInfo, APPLY_NORMALIZATION,
- (self->limiterEnableCurr) ? 0 : 1);
-
/* deactivate legacy DRC in case uniDrc is active, i.e. uniDrc payload is
* present and one of DRC or Loudness Normalization is switched on */
aacDecoder_drcSetParam(
@@ -3168,9 +3189,15 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
self->hDrcInfo, bs, self->pAacDecoderStaticChannelInfo,
pce->ElementInstanceTag, drcChMap, aacChannels);
if (mapped > 0) {
- /* If at least one DRC thread has been mapped to a channel threre was DRC
- * data in the bitstream. */
- self->flags[streamIndex] |= AC_DRC_PRESENT;
+ if (!(self->flags[streamIndex] & (AC_USAC | AC_RSV603DA))) {
+ /* If at least one DRC thread has been mapped to a channel there was DRC
+ * data in the bitstream. */
+ self->flags[streamIndex] |= AC_DRC_PRESENT;
+ } else {
+ self->hDrcInfo->enable = 0;
+ self->hDrcInfo->progRefLevelPresent = 0;
+ ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT;
+ }
}
/* Create a reverse mapping table */
@@ -3300,9 +3327,11 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
&pAacDecoderStaticChannelInfo->drcData);
}
}
+
/* The DRC module demands to be called with the gain field holding the
* gain scale. */
- self->extGain[0] = (FIXP_DBL)TDL_GAIN_SCALING;
+ self->extGain[0] = (FIXP_DBL)AACDEC_DRC_GAIN_SCALING;
+
/* DRC processing */
aacDecoder_drcApply(
self->hDrcInfo, self->hSbrDecoder, pAacDecoderChannelInfo,
@@ -3318,7 +3347,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
if (self->flushStatus && (self->flushCnt > 0) &&
!(flags & AACDEC_CONCEAL)) {
FDKmemclear(pTimeData + offset,
- sizeof(FIXP_PCM) * self->streamInfo.aacSamplesPerFrame);
+ sizeof(PCM_DEC) * self->streamInfo.aacSamplesPerFrame);
} else
switch (pAacDecoderChannelInfo->renderMode) {
case AACDEC_RENDER_IMDCT:
@@ -3330,7 +3359,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
!frameOk_butConceal),
pAacDecoderChannelInfo->pComStaticData->pWorkBufferCore1
->mdctOutTemp,
- self->elFlags[el], elCh);
+ self->aacOutDataHeadroom, self->elFlags[el], elCh);
self->extGainDelay = self->streamInfo.aacSamplesPerFrame;
break;
@@ -3351,7 +3380,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
&self->samplingRateInfo[streamIndex],
(self->frameOK && !(flags & AACDEC_CONCEAL) &&
!frameOk_butConceal),
- flags, self->flags[streamIndex]);
+ self->aacOutDataHeadroom, flags, self->flags[streamIndex]);
self->extGainDelay = self->streamInfo.aacSamplesPerFrame;
break;
@@ -3363,7 +3392,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
if (!CConceal_TDFading_Applied[c]) {
CConceal_TDFading_Applied[c] = CConcealment_TDFading(
self->streamInfo.aacSamplesPerFrame,
- &self->pAacDecoderStaticChannelInfo[c], pTimeData + offset, 0);
+ &self->pAacDecoderStaticChannelInfo[c], self->aacOutDataHeadroom,
+ pTimeData + offset, 0);
if (c + 1 < (8) && c < aacChannels - 1) {
/* update next TDNoise Seed to avoid muting in case of Parametric
* Stereo */
@@ -3385,22 +3415,17 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
if ((aacChannels == 2) && bsPseudoLr) {
int i, offset2;
const FIXP_SGL invSqrt2 = FL2FXCONST_SGL(0.707106781186547f);
- FIXP_PCM *pTD = pTimeData;
+ PCM_DEC *pTD = pTimeData;
offset2 = timeDataChannelOffset;
for (i = 0; i < self->streamInfo.aacSamplesPerFrame; i++) {
- FIXP_DBL L = FX_PCM2FX_DBL(pTD[0]);
- FIXP_DBL R = FX_PCM2FX_DBL(pTD[offset2]);
+ FIXP_DBL L = PCM_DEC2FIXP_DBL(pTD[0]);
+ FIXP_DBL R = PCM_DEC2FIXP_DBL(pTD[offset2]);
L = fMult(L, invSqrt2);
R = fMult(R, invSqrt2);
-#if (SAMPLE_BITS == 16)
- pTD[0] = FX_DBL2FX_PCM(fAddSaturate(L + R, (FIXP_DBL)0x8000));
- pTD[offset2] = FX_DBL2FX_PCM(fAddSaturate(L - R, (FIXP_DBL)0x8000));
-#else
- pTD[0] = FX_DBL2FX_PCM(L + R);
- pTD[offset2] = FX_DBL2FX_PCM(L - R);
-#endif
+ pTD[0] = L + R;
+ pTD[offset2] = L - R;
pTD++;
}
}
@@ -3411,9 +3436,15 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
self->hDrcInfo, bs, self->pAacDecoderStaticChannelInfo,
pce->ElementInstanceTag, drcChMap, aacChannels);
if (mapped > 0) {
- /* If at least one DRC thread has been mapped to a channel threre was DRC
- * data in the bitstream. */
- self->flags[streamIndex] |= AC_DRC_PRESENT;
+ if (!(self->flags[streamIndex] & (AC_USAC | AC_RSV603DA))) {
+ /* If at least one DRC thread has been mapped to a channel there was DRC
+ * data in the bitstream. */
+ self->flags[streamIndex] |= AC_DRC_PRESENT;
+ } else {
+ self->hDrcInfo->enable = 0;
+ self->hDrcInfo->progRefLevelPresent = 0;
+ ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT;
+ }
}
}
diff --git a/libAACdec/src/aacdecoder.h b/libAACdec/src/aacdecoder.h
index 20f4c45..bd1f38f 100644
--- a/libAACdec/src/aacdecoder.h
+++ b/libAACdec/src/aacdecoder.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
@@ -191,6 +191,9 @@ struct AAC_DECODER_INSTANCE {
INT outputInterleaved; /*!< PCM output format (interleaved/none interleaved).
*/
+ INT aacOutDataHeadroom; /*!< Headroom of the output time signal to prevent
+ clipping */
+
HANDLE_TRANSPORTDEC hInput; /*!< Transport layer handle. */
SamplingRateInfo
@@ -235,6 +238,7 @@ struct AAC_DECODER_INSTANCE {
CAacDecoderStaticChannelInfo
*pAacDecoderStaticChannelInfo[(8)]; /*!< Persistent channel memory */
+ FIXP_DBL *workBufferCore1;
FIXP_DBL *workBufferCore2;
PCM_DEC *pTimeData2;
INT timeData2Size;
@@ -311,11 +315,10 @@ This structure is allocated once for each CPE. */
UCHAR limiterEnableUser; /*!< The limiter configuration requested by the
library user */
UCHAR limiterEnableCurr; /*!< The current limiter configuration. */
+
FIXP_DBL extGain[1]; /*!< Gain that must be applied to the output signal. */
UINT extGainDelay; /*!< Delay that must be accounted for extGain. */
- INT_PCM pcmOutputBuffer[(8) * (1024 * 2)];
-
HANDLE_DRC_DECODER hUniDrcDecoder;
UCHAR multibandDrcPresent;
UCHAR numTimeSlots;
@@ -427,7 +430,7 @@ LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self,
\return error status
*/
LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
- HANDLE_AACDECODER self, const UINT flags, FIXP_PCM *pTimeData,
+ HANDLE_AACDECODER self, const UINT flags, PCM_DEC *pTimeData,
const INT timeDataSize, const int timeDataChannelOffset);
/* Free config dependent AAC memory */
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp
index 8685a30..bcbd46c 100644
--- a/libAACdec/src/aacdecoder_lib.cpp
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -119,10 +119,10 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */
#define AACDECODER_LIB_VL0 3
-#define AACDECODER_LIB_VL1 1
-#define AACDECODER_LIB_VL2 2
+#define AACDECODER_LIB_VL1 2
+#define AACDECODER_LIB_VL2 0
#define AACDECODER_LIB_TITLE "AAC Decoder Lib"
-#ifdef __ANDROID__
+#ifdef SUPPRESS_BUILD_DATE_INFO
#define AACDECODER_LIB_BUILD_DATE ""
#define AACDECODER_LIB_BUILD_TIME ""
#else
@@ -1133,35 +1133,31 @@ static INT aacDecoder_EstimateNumberOfLostFrames(HANDLE_AACDECODER self) {
return n;
}
-LINKSPEC_CPP AAC_DECODER_ERROR
-aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
- const INT timeDataSize_extern, const UINT flags) {
+LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
+ INT_PCM *pTimeData,
+ const INT timeDataSize,
+ const UINT flags) {
AAC_DECODER_ERROR ErrorStatus;
INT layer;
INT nBits;
+ INT timeData2Size;
+ INT timeData3Size;
+ INT timeDataHeadroom;
HANDLE_FDK_BITSTREAM hBs;
int fTpInterruption = 0; /* Transport originated interruption detection. */
int fTpConceal = 0; /* Transport originated concealment. */
- INT_PCM *pTimeData = NULL;
- INT timeDataSize = 0;
UINT accessUnit = 0;
UINT numAccessUnits = 1;
UINT numPrerollAU = 0;
- int fEndAuNotAdjusted = 0; /* The end of the access unit was not adjusted */
- int applyCrossfade = 1; /* flag indicates if flushing was possible */
- FIXP_PCM *pTimeDataFixpPcm; /* Signal buffer for decoding process before PCM
- processing */
- INT timeDataFixpPcmSize;
- PCM_DEC *pTimeDataPcmPost; /* Signal buffer for PCM post-processing */
- INT timeDataPcmPostSize;
+ int fEndAuNotAdjusted = 0; /* The end of the access unit was not adjusted */
+ int applyCrossfade = 1; /* flag indicates if flushing was possible */
+ PCM_DEC *pTimeData2;
+ PCM_AAC *pTimeData3;
if (self == NULL) {
return AAC_DEC_INVALID_HANDLE;
}
- pTimeData = self->pcmOutputBuffer;
- timeDataSize = sizeof(self->pcmOutputBuffer) / sizeof(*self->pcmOutputBuffer);
-
if (flags & AACDEC_INTR) {
self->streamInfo.numLostAccessUnits = 0;
}
@@ -1271,9 +1267,9 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
}
/* Signal bit stream interruption to other modules if required. */
- if (fTpInterruption || (flags & AACDEC_INTR)) {
+ if (fTpInterruption || ((flags & AACDEC_INTR) && (accessUnit == 0))) {
aacDecoder_SignalInterruption(self);
- if (!(flags & AACDEC_INTR)) {
+ if (!((flags & AACDEC_INTR) && (accessUnit == 0))) {
ErrorStatus = AAC_DEC_TRANSPORT_SYNC_ERROR;
goto bail;
}
@@ -1317,19 +1313,23 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
/* Use limiter configuration as requested. */
self->limiterEnableCurr = self->limiterEnableUser;
}
- /* reset limiter gain on a per frame basis */
- self->extGain[0] = FL2FXCONST_DBL(1.0f / (float)(1 << TDL_GAIN_SCALING));
- pTimeDataFixpPcm = pTimeData;
- timeDataFixpPcmSize = timeDataSize;
+ /* reset DRC level normalization gain on a per frame basis */
+ self->extGain[0] = AACDEC_DRC_GAIN_INIT_VALUE;
+
+ pTimeData2 = self->pTimeData2;
+ timeData2Size = self->timeData2Size / sizeof(PCM_DEC);
+ pTimeData3 = (PCM_AAC *)self->pTimeData2;
+ timeData3Size = self->timeData2Size / sizeof(PCM_AAC);
ErrorStatus = CAacDecoder_DecodeFrame(
self,
flags | (fTpConceal ? AACDEC_CONCEAL : 0) |
((self->flushStatus && !(flags & AACDEC_CONCEAL)) ? AACDEC_FLUSH
: 0),
- pTimeDataFixpPcm + 0, timeDataFixpPcmSize,
- self->streamInfo.aacSamplesPerFrame + 0);
+ pTimeData2 + 0, timeData2Size, self->streamInfo.aacSamplesPerFrame + 0);
+
+ timeDataHeadroom = self->aacOutDataHeadroom;
/* if flushing for USAC DASH IPF was not possible go on with decoding
* preroll */
@@ -1354,7 +1354,7 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
}
}
- /* If the current pTimeDataFixpPcm does not contain a valid signal, there
+ /* If the current pTimeData2 does not contain a valid signal, there
* nothing else we can do, so bail. */
if (!IS_OUTPUT_VALID(ErrorStatus)) {
goto bail;
@@ -1368,10 +1368,10 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
self->streamInfo.numChannels = self->streamInfo.aacNumChannels;
{
- FDK_Delay_Apply(&self->usacResidualDelay,
- pTimeDataFixpPcm +
- 1 * (self->streamInfo.aacSamplesPerFrame + 0) + 0,
- self->streamInfo.frameSize, 0);
+ FDK_Delay_Apply(
+ &self->usacResidualDelay,
+ pTimeData2 + 1 * (self->streamInfo.aacSamplesPerFrame + 0) + 0,
+ self->streamInfo.frameSize, 0);
}
/* Setting of internal MPS state; may be reset in CAacDecoder_SyncQmfMode
@@ -1418,8 +1418,6 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
}
}
- self->qmfDomain.globalConf.TDinput = pTimeData;
-
switch (FDK_QmfDomain_Configure(&self->qmfDomain)) {
default:
case QMF_DOMAIN_INIT_ERROR:
@@ -1476,18 +1474,18 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF,
(self->mpsEnableCurr) ? 2 : 0);
- INT_PCM *input;
- input = (INT_PCM *)self->workBufferCore2;
- FDKmemcpy(input, pTimeData,
- sizeof(INT_PCM) * (self->streamInfo.numChannels) *
+ PCM_AAC *input;
+ input = (PCM_AAC *)self->workBufferCore2;
+ FDKmemcpy(input, pTimeData3,
+ sizeof(PCM_AAC) * (self->streamInfo.numChannels) *
(self->streamInfo.frameSize));
/* apply SBR processing */
- sbrError = sbrDecoder_Apply(self->hSbrDecoder, input, pTimeData,
- timeDataSize, &self->streamInfo.numChannels,
- &self->streamInfo.sampleRate,
- &self->mapDescr, self->chMapIndex,
- self->frameOK, &self->psPossible);
+ sbrError = sbrDecoder_Apply(
+ self->hSbrDecoder, input, pTimeData3, timeData3Size,
+ &self->streamInfo.numChannels, &self->streamInfo.sampleRate,
+ &self->mapDescr, self->chMapIndex, self->frameOK, &self->psPossible,
+ self->aacOutDataHeadroom, &timeDataHeadroom);
if (sbrError == SBRDEC_OK) {
/* Update data in streaminfo structure. Assume that the SBR upsampling
@@ -1566,10 +1564,11 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
if (err == 0) {
err = mpegSurroundDecoder_Apply(
(CMpegSurroundDecoder *)self->pMpegSurroundDecoder,
- (INT_PCM *)self->workBufferCore2, pTimeData, timeDataSize,
+ (PCM_AAC *)self->workBufferCore2, pTimeData3, timeData3Size,
self->streamInfo.aacSamplesPerFrame, &nChannels, &frameSize,
self->streamInfo.sampleRate, self->streamInfo.aot,
- self->channelType, self->channelIndices, &self->mapDescr);
+ self->channelType, self->channelIndices, &self->mapDescr,
+ self->aacOutDataHeadroom, &timeDataHeadroom);
}
if (err == MPS_OUTPUT_BUFFER_TOO_SMALL) {
@@ -1592,8 +1591,8 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
self->streamInfo.frameSize = self->mpsFrameSizeLast;
/* ... and clear output buffer so that potentially corrupted data does
* not reach the framework. */
- FDKmemclear(pTimeData, self->mpsOutChannelsLast *
- self->mpsFrameSizeLast * sizeof(INT_PCM));
+ FDKmemclear(pTimeData3, self->mpsOutChannelsLast *
+ self->mpsFrameSizeLast * sizeof(PCM_AAC));
/* Additionally proclaim that this frame had errors during decoding.
*/
ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
@@ -1614,11 +1613,11 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF, 1);
/* apply SBR processing */
- sbrError = sbrDecoder_Apply(self->hSbrDecoder, pTimeData, pTimeData,
- timeDataSize, &self->streamInfo.numChannels,
- &self->streamInfo.sampleRate,
- &self->mapDescr, self->chMapIndex,
- self->frameOK, &self->psPossible);
+ sbrError = sbrDecoder_Apply(
+ self->hSbrDecoder, pTimeData3, pTimeData3, timeData3Size,
+ &self->streamInfo.numChannels, &self->streamInfo.sampleRate,
+ &self->mapDescr, self->chMapIndex, self->frameOK, &self->psPossible,
+ self->aacOutDataHeadroom, &timeDataHeadroom);
if (sbrError == SBRDEC_OK) {
/* Update data in streaminfo structure. Assume that the SBR upsampling
@@ -1646,17 +1645,15 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
}
}
- /* Use dedicated memory for PCM postprocessing */
- pTimeDataPcmPost = self->pTimeData2;
- timeDataPcmPostSize = self->timeData2Size;
-
{
- const int size =
- self->streamInfo.frameSize * self->streamInfo.numChannels;
- FDK_ASSERT(timeDataPcmPostSize >= size);
- for (int i = 0; i < size; i++) {
- pTimeDataPcmPost[i] =
- (PCM_DEC)FX_PCM2PCM_DEC(pTimeData[i]) >> PCM_OUT_HEADROOM;
+ if ((INT)PCM_OUT_HEADROOM != timeDataHeadroom) {
+ for (int i = ((self->streamInfo.frameSize *
+ self->streamInfo.numChannels) -
+ 1);
+ i >= 0; i--) {
+ pTimeData2[i] =
+ (PCM_DEC)pTimeData3[i] >> (PCM_OUT_HEADROOM - timeDataHeadroom);
+ }
}
}
@@ -1711,22 +1708,21 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
if ((self->streamInfo.numChannels > 1) &&
(0 || (self->sbrEnabled) || (self->mpsEnableCurr))) {
/* interleaving/deinterleaving is performed on upper part of
- * pTimeDataPcmPost. Check if this buffer is large enough. */
- if (timeDataPcmPostSize <
- (INT)(2 * self->streamInfo.numChannels *
- self->streamInfo.frameSize * sizeof(PCM_DEC))) {
+ * pTimeData2. Check if this buffer is large enough. */
+ if (timeData2Size < (INT)(2 * self->streamInfo.numChannels *
+ self->streamInfo.frameSize)) {
ErrorStatus = AAC_DEC_UNKNOWN;
goto bail;
}
needsDeinterleaving = 1;
drcWorkBuffer =
- (FIXP_DBL *)pTimeDataPcmPost +
+ (FIXP_DBL *)pTimeData2 +
self->streamInfo.numChannels * self->streamInfo.frameSize;
FDK_deinterleave(
- pTimeDataPcmPost, drcWorkBuffer, self->streamInfo.numChannels,
+ pTimeData2, drcWorkBuffer, self->streamInfo.numChannels,
self->streamInfo.frameSize, self->streamInfo.frameSize);
} else {
- drcWorkBuffer = (FIXP_DBL *)pTimeDataPcmPost;
+ drcWorkBuffer = pTimeData2;
}
/* prepare Loudness Normalisation gain */
@@ -1761,16 +1757,51 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
if (needsDeinterleaving) {
FDK_interleave(
- drcWorkBuffer, pTimeDataPcmPost, self->streamInfo.numChannels,
+ drcWorkBuffer, pTimeData2, self->streamInfo.numChannels,
self->streamInfo.frameSize, self->streamInfo.frameSize);
}
}
}
+ if (FDK_drcDec_GetParam(self->hUniDrcDecoder, DRC_DEC_IS_ACTIVE)) {
+ /* return output loudness information for MPEG-D DRC */
+ LONG outputLoudness =
+ FDK_drcDec_GetParam(self->hUniDrcDecoder, DRC_DEC_OUTPUT_LOUDNESS);
+ if (outputLoudness == DRC_DEC_LOUDNESS_NOT_PRESENT) {
+ /* no valid MPEG-D DRC loudness value contained */
+ self->streamInfo.outputLoudness = -1;
+ } else {
+ if (outputLoudness > 0) {
+ /* positive output loudness values (very unusual) are limited to 0
+ * dB */
+ self->streamInfo.outputLoudness = 0;
+ } else {
+ self->streamInfo.outputLoudness =
+ -(INT)outputLoudness >>
+ 22; /* negate and scale from e = 7 to e = (31-2) */
+ }
+ }
+ } else {
+ /* return output loudness information for MPEG-4 DRC */
+ if (self->streamInfo.drcProgRefLev <
+ 0) { /* no MPEG-4 DRC loudness metadata contained */
+ self->streamInfo.outputLoudness = -1;
+ } else {
+ if (self->defaultTargetLoudness <
+ 0) { /* loudness normalization is off */
+ self->streamInfo.outputLoudness = self->streamInfo.drcProgRefLev;
+ } else {
+ self->streamInfo.outputLoudness = self->defaultTargetLoudness;
+ }
+ }
+ }
if (self->streamInfo.extAot != AOT_AAC_SLS) {
INT pcmLimiterScale = 0;
+ INT interleaved = 0;
+ interleaved |= (self->sbrEnabled) ? 1 : 0;
+ interleaved |= (self->mpsEnableCurr) ? 1 : 0;
PCMDMX_ERROR dmxErr = PCMDMX_OK;
- if (flags & (AACDEC_INTR)) {
+ if ((flags & AACDEC_INTR) && (accessUnit == 0)) {
/* delete data from the past (e.g. mixdown coeficients) */
pcmDmx_Reset(self->hPcmUtils, PCMDMX_RESET_BS_DATA);
}
@@ -1781,17 +1812,12 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
}
}
- INT interleaved = 0;
- interleaved |= (self->sbrEnabled) ? 1 : 0;
- interleaved |= (self->mpsEnableCurr) ? 1 : 0;
-
/* do PCM post processing */
- dmxErr = pcmDmx_ApplyFrame(
- self->hPcmUtils, pTimeDataPcmPost, timeDataFixpPcmSize,
- self->streamInfo.frameSize, &self->streamInfo.numChannels,
- interleaved, self->channelType, self->channelIndices,
- &self->mapDescr,
- (self->limiterEnableCurr) ? &pcmLimiterScale : NULL);
+ dmxErr = pcmDmx_ApplyFrame(self->hPcmUtils, pTimeData2, timeData2Size,
+ self->streamInfo.frameSize,
+ &self->streamInfo.numChannels, interleaved,
+ self->channelType, self->channelIndices,
+ &self->mapDescr, &pcmLimiterScale);
if (dmxErr == PCMDMX_OUTPUT_BUFFER_TOO_SMALL) {
ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL;
goto bail;
@@ -1803,13 +1829,35 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
}
+ pcmLimiterScale += PCM_OUT_HEADROOM;
+
if (flags & AACDEC_CLRHIST) {
if (!(self->flags[0] & AC_USAC)) {
+ /* Reset DRC data */
+ aacDecoder_drcReset(self->hDrcInfo);
/* Delete the delayed signal. */
pcmLimiter_Reset(self->hLimiter);
}
}
+ /* Set applyExtGain if DRC processing is enabled and if
+ progRefLevelPresent is present for the first time. Consequences: The
+ headroom of the output signal can be set to AACDEC_DRC_GAIN_SCALING
+ only for audio formats which support legacy DRC Level Normalization.
+ For all other audio formats the headroom of the output
+ signal is set to PCM_OUT_HEADROOM. */
+ if (self->hDrcInfo->enable &&
+ (self->hDrcInfo->progRefLevelPresent == 1)) {
+ self->hDrcInfo->applyExtGain |= 1;
+ }
+
+ /* Check whether time data buffer is large enough. */
+ if (timeDataSize <
+ (self->streamInfo.numChannels * self->streamInfo.frameSize)) {
+ ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL;
+ goto bail;
+ }
+
if (self->limiterEnableCurr) {
/* use workBufferCore2 buffer for interleaving */
PCM_LIM *pInterleaveBuffer;
@@ -1818,44 +1866,72 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
/* Set actual signal parameters */
pcmLimiter_SetNChannels(self->hLimiter, self->streamInfo.numChannels);
pcmLimiter_SetSampleRate(self->hLimiter, self->streamInfo.sampleRate);
- pcmLimiterScale += PCM_OUT_HEADROOM;
if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
(self->mpsEnableCurr)) {
- pInterleaveBuffer = (PCM_LIM *)pTimeDataPcmPost;
+ pInterleaveBuffer = (PCM_LIM *)pTimeData2;
} else {
- pInterleaveBuffer = (PCM_LIM *)pTimeData;
+ pInterleaveBuffer = (PCM_LIM *)self->workBufferCore2;
+
/* applyLimiter requests for interleaved data */
/* Interleave ouput buffer */
- FDK_interleave(pTimeDataPcmPost, pInterleaveBuffer,
+ FDK_interleave(pTimeData2, pInterleaveBuffer,
self->streamInfo.numChannels, blockLength,
self->streamInfo.frameSize);
}
+ FIXP_DBL *pGainPerSample = NULL;
+
+ if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) {
+ pGainPerSample = self->workBufferCore1;
+
+ if ((INT)GetRequiredMemWorkBufferCore1() <
+ (INT)(self->streamInfo.frameSize * sizeof(FIXP_DBL))) {
+ ErrorStatus = AAC_DEC_UNKNOWN;
+ goto bail;
+ }
+
+ pcmLimiterScale = applyDrcLevelNormalization(
+ self->hDrcInfo, (PCM_DEC *)pInterleaveBuffer, self->extGain,
+ pGainPerSample, pcmLimiterScale, self->extGainDelay,
+ self->streamInfo.frameSize, self->streamInfo.numChannels, 1, 1);
+ }
+
pcmLimiter_Apply(self->hLimiter, pInterleaveBuffer, pTimeData,
- self->extGain, &pcmLimiterScale, 1,
- self->extGainDelay, self->streamInfo.frameSize);
+ pGainPerSample, pcmLimiterScale,
+ self->streamInfo.frameSize);
{
/* Announce the additional limiter output delay */
self->streamInfo.outputDelay += pcmLimiter_GetDelay(self->hLimiter);
}
} else {
+ if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) {
+ pcmLimiterScale = applyDrcLevelNormalization(
+ self->hDrcInfo, pTimeData2, self->extGain, NULL,
+ pcmLimiterScale, self->extGainDelay, self->streamInfo.frameSize,
+ self->streamInfo.numChannels,
+ (interleaved || (self->streamInfo.numChannels == 1))
+ ? 1
+ : self->streamInfo.frameSize,
+ 0);
+ }
+
/* If numChannels = 1 we do not need interleaving. The same applies if
SBR or MPS are used, since their output is interleaved already
(resampled or not) */
if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
(self->mpsEnableCurr)) {
scaleValuesSaturate(
- pTimeData, pTimeDataPcmPost,
+ pTimeData, pTimeData2,
self->streamInfo.frameSize * self->streamInfo.numChannels,
- PCM_OUT_HEADROOM);
+ pcmLimiterScale);
} else {
scaleValuesSaturate(
- (INT_PCM *)self->workBufferCore2, pTimeDataPcmPost,
+ (INT_PCM *)self->workBufferCore2, pTimeData2,
self->streamInfo.frameSize * self->streamInfo.numChannels,
- PCM_OUT_HEADROOM);
+ pcmLimiterScale);
/* Interleave ouput buffer */
FDK_interleave((INT_PCM *)self->workBufferCore2, pTimeData,
self->streamInfo.numChannels,
@@ -1951,20 +2027,8 @@ bail:
ErrorStatus = AAC_DEC_UNKNOWN;
}
- /* Check whether external output buffer is large enough. */
- if (timeDataSize_extern <
- self->streamInfo.numChannels * self->streamInfo.frameSize) {
- ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL;
- }
-
- /* Update external output buffer. */
- if (IS_OUTPUT_VALID(ErrorStatus)) {
- FDKmemcpy(pTimeData_extern, pTimeData,
- self->streamInfo.numChannels * self->streamInfo.frameSize *
- sizeof(*pTimeData));
- } else {
- FDKmemclear(pTimeData_extern,
- timeDataSize_extern * sizeof(*pTimeData_extern));
+ if (!IS_OUTPUT_VALID(ErrorStatus)) {
+ FDKmemclear(pTimeData, timeDataSize * sizeof(*pTimeData));
}
return ErrorStatus;
diff --git a/libAACdec/src/block.cpp b/libAACdec/src/block.cpp
index b3d09a6..0bca577 100644
--- a/libAACdec/src/block.cpp
+++ b/libAACdec/src/block.cpp
@@ -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
@@ -1015,9 +1015,9 @@ FIXP_DBL get_gain(const FIXP_DBL *x, const FIXP_DBL *y, int n) {
void CBlock_FrequencyToTime(
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
- CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[],
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[],
const SHORT frameLen, const int frameOk, FIXP_DBL *pWorkBuffer1,
- UINT elFlags, INT elCh) {
+ const INT aacOutDataHeadroom, UINT elFlags, INT elCh) {
int fr, fl, tl, nSpec;
#if defined(FDK_ASSERT_ENABLE)
@@ -1213,6 +1213,7 @@ void CBlock_FrequencyToTime(
bass_pf_1sf_delay(p2_synth, pitch, pit_gain, frameLen,
(LpdSfd + 2) * L_SUBFR + BPF_SFD * L_SUBFR,
frameLen - (LpdSfd + 4) * L_SUBFR, outSamples,
+ aacOutDataHeadroom,
pAacDecoderStaticChannelInfo->mem_bpf);
}
@@ -1236,7 +1237,8 @@ void CBlock_FrequencyToTime(
? MLT_FLAG_CURR_ALIAS_SYMMETRY
: 0);
- scaleValuesSaturate(outSamples, tmp, frameLen, MDCT_OUT_HEADROOM);
+ scaleValuesSaturate(outSamples, tmp, frameLen,
+ MDCT_OUT_HEADROOM - aacOutDataHeadroom);
}
}
@@ -1251,7 +1253,7 @@ void CBlock_FrequencyToTime(
#include "ldfiltbank.h"
void CBlock_FrequencyToTimeLowDelay(
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
- CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[],
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[],
const short frameLen) {
InvMdctTransformLowDelay_fdk(
SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient),
diff --git a/libAACdec/src/block.h b/libAACdec/src/block.h
index f0f56cd..f5118a2 100644
--- a/libAACdec/src/block.h
+++ b/libAACdec/src/block.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
@@ -218,16 +218,16 @@ void ApplyTools(CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
*/
void CBlock_FrequencyToTime(
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
- CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[],
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[],
const SHORT frameLen, const int frameOk, FIXP_DBL *pWorkBuffer1,
- UINT elFlags, INT elCh);
+ const INT aacOutDataHeadroom, UINT elFlags, INT elCh);
/**
* \brief Transform double lapped MDCT (AAC-ELD) spectral data into time domain.
*/
void CBlock_FrequencyToTimeLowDelay(
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
- CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[],
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[],
const short frameLen);
AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData(
diff --git a/libAACdec/src/conceal.cpp b/libAACdec/src/conceal.cpp
index 5895cb8..0939bb5 100644
--- a/libAACdec/src/conceal.cpp
+++ b/libAACdec/src/conceal.cpp
@@ -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
@@ -226,7 +226,7 @@ static void CConcealment_ApplyRandomSign(int iRandomPhase, FIXP_DBL *spec,
/* TimeDomainFading */
static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart,
- FIXP_DBL fadeStop, FIXP_PCM *pcmdata);
+ FIXP_DBL fadeStop, PCM_DEC *pcmdata);
static void CConcealment_TDFadeFillFadingStations(FIXP_DBL *fadingStations,
int *fadingSteps,
FIXP_DBL fadeStop,
@@ -242,7 +242,9 @@ static int CConcealment_ApplyFadeOut(
static int CConcealment_TDNoise_Random(ULONG *seed);
static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo,
- const int len, FIXP_PCM *const pcmdata);
+ const int len,
+ const INT aacOutDataHeadroom,
+ PCM_DEC *const pcmdata);
static BLOCK_TYPE CConcealment_GetWinSeq(int prevWinSeq) {
BLOCK_TYPE newWinSeq = BLOCK_LONG;
@@ -1228,7 +1230,6 @@ static void CConcealment_InterpolateBuffer(FIXP_DBL *spectrum,
int sfb, line = 0;
int fac_shift;
int fac_mod;
- FIXP_DBL accu;
for (sfb = 0; sfb < sfbCnt; sfb++) {
fac_shift =
@@ -1236,15 +1237,11 @@ static void CConcealment_InterpolateBuffer(FIXP_DBL *spectrum,
fac_mod = fac_shift & 3;
fac_shift = (fac_shift >> 2) + 1;
fac_shift += *pSpecScalePrv - fixMax(*pSpecScalePrv, *pSpecScaleAct);
+ fac_shift = fMax(fMin(fac_shift, DFRACT_BITS - 1), -(DFRACT_BITS - 1));
for (; line < pSfbOffset[sfb + 1]; line++) {
- accu = fMult(*(spectrum + line), facMod4Table[fac_mod]);
- if (fac_shift < 0) {
- accu >>= -fac_shift;
- } else {
- accu <<= fac_shift;
- }
- *(spectrum + line) = accu;
+ FIXP_DBL accu = fMult(*(spectrum + line), facMod4Table[fac_mod]);
+ *(spectrum + line) = scaleValue(accu, fac_shift);
}
}
*pSpecScaleOut = fixMax(*pSpecScalePrv, *pSpecScaleAct);
@@ -1618,7 +1615,7 @@ static void CConcealment_ApplyRandomSign(int randomPhase, FIXP_DBL *spec,
}
if (packedSign & 0x1) {
- spec[i] = -spec[i];
+ spec[i] = -fMax(spec[i], (FIXP_DBL)(MINVAL_DBL + 1));
}
packedSign >>= 1;
@@ -1849,7 +1846,7 @@ Target fading level is determined by fading index cntFadeFrames.
INT CConcealment_TDFading(
int len, CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo,
- FIXP_PCM *pcmdata, FIXP_PCM *pcmdata_1) {
+ const INT aacOutDataHeadroom, PCM_DEC *pcmdata, PCM_DEC *pcmdata_1) {
/*
Do the fading in Time domain based on concealment states and core mode
*/
@@ -1962,7 +1959,8 @@ INT CConcealment_TDFading(
start += len;
}
}
- CConcealment_TDNoise_Apply(pConcealmentInfo, len, pcmdata);
+ CConcealment_TDNoise_Apply(pConcealmentInfo, len, aacOutDataHeadroom,
+ pcmdata);
/* Save end-of-frame attenuation and fading type */
pConcealmentInfo->lastFadingType = fadingType;
@@ -1974,12 +1972,11 @@ INT CConcealment_TDFading(
/* attenuate pcmdata in Time Domain Fading process */
static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart,
- FIXP_DBL fadeStop, FIXP_PCM *pcmdata) {
+ FIXP_DBL fadeStop, PCM_DEC *pcmdata) {
int i;
FIXP_DBL dStep;
FIXP_DBL dGain;
FIXP_DBL dGain_apply;
- int bitshift = (DFRACT_BITS - SAMPLE_BITS);
/* set start energy */
dGain = fadeStart;
@@ -1992,7 +1989,7 @@ static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart,
*/
dGain_apply = fMax((FIXP_DBL)0, dGain);
/* finally, attenuate samples */
- pcmdata[i] = (FIXP_PCM)((fMult(pcmdata[i], (dGain_apply))) >> bitshift);
+ pcmdata[i] = FIXP_DBL2PCM_DEC(fMult(pcmdata[i], dGain_apply));
}
}
@@ -2055,9 +2052,11 @@ static int CConcealment_TDNoise_Random(ULONG *seed) {
}
static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo,
- const int len, FIXP_PCM *const pcmdata) {
- FIXP_PCM *states = pConcealmentInfo->TDNoiseStates;
- FIXP_PCM noiseVal;
+ const int len,
+ const INT aacOutDataHeadroom,
+ PCM_DEC *const pcmdata) {
+ PCM_DEC *states = pConcealmentInfo->TDNoiseStates;
+ PCM_DEC noiseVal;
FIXP_DBL noiseValLong;
FIXP_SGL *coef = pConcealmentInfo->TDNoiseCoef;
FIXP_DBL TDNoiseAtt;
@@ -2075,18 +2074,20 @@ static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo,
/* create filtered noise */
states[2] = states[1];
states[1] = states[0];
- states[0] = ((FIXP_PCM)CConcealment_TDNoise_Random(&seed));
+ states[0] =
+ FIXP_DBL2PCM_DEC((FIXP_DBL)CConcealment_TDNoise_Random(&seed));
noiseValLong = fMult(states[0], coef[0]) + fMult(states[1], coef[1]) +
fMult(states[2], coef[2]);
- noiseVal = FX_DBL2FX_PCM(fMult(noiseValLong, TDNoiseAtt));
+ noiseVal = FIXP_DBL2PCM_DEC(fMult(noiseValLong, TDNoiseAtt) >>
+ aacOutDataHeadroom);
/* add filtered noise - check for clipping, before */
- if (noiseVal > (FIXP_PCM)0 &&
- pcmdata[ii] > (FIXP_PCM)MAXVAL_FIXP_PCM - noiseVal) {
- noiseVal = noiseVal * (FIXP_PCM)-1;
- } else if (noiseVal < (FIXP_PCM)0 &&
- pcmdata[ii] < (FIXP_PCM)MINVAL_FIXP_PCM - noiseVal) {
- noiseVal = noiseVal * (FIXP_PCM)-1;
+ if (noiseVal > (PCM_DEC)0 &&
+ pcmdata[ii] > (PCM_DEC)MAXVAL_PCM_DEC - noiseVal) {
+ noiseVal = noiseVal * (PCM_DEC)-1;
+ } else if (noiseVal < (PCM_DEC)0 &&
+ pcmdata[ii] < (PCM_DEC)MINVAL_PCM_DEC - noiseVal) {
+ noiseVal = noiseVal * (PCM_DEC)-1;
}
pcmdata[ii] += noiseVal;
diff --git a/libAACdec/src/conceal.h b/libAACdec/src/conceal.h
index e01a796..0c002a5 100644
--- a/libAACdec/src/conceal.h
+++ b/libAACdec/src/conceal.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
@@ -147,6 +147,6 @@ int CConcealment_GetLastFrameOk(CConcealmentInfo *hConcealmentInfo,
INT CConcealment_TDFading(
int len, CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo,
- FIXP_PCM *pcmdata, FIXP_PCM *pcmdata_1);
+ const INT aacOutDataHeadroom, PCM_DEC *pcmdata, PCM_DEC *pcmdata_1);
#endif /* #ifndef CONCEAL_H */
diff --git a/libAACdec/src/conceal_types.h b/libAACdec/src/conceal_types.h
index d90374e..36e7dec 100644
--- a/libAACdec/src/conceal_types.h
+++ b/libAACdec/src/conceal_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
@@ -194,7 +194,7 @@ typedef struct {
FIXP_DBL last_tcx_gain;
INT last_tcx_gain_e;
ULONG TDNoiseSeed;
- FIXP_PCM TDNoiseStates[3];
+ PCM_DEC TDNoiseStates[3];
FIXP_SGL TDNoiseCoef[3];
FIXP_SGL TDNoiseAtt;
diff --git a/libAACdec/src/ldfiltbank.cpp b/libAACdec/src/ldfiltbank.cpp
index c7d2928..13e61a5 100644
--- a/libAACdec/src/ldfiltbank.cpp
+++ b/libAACdec/src/ldfiltbank.cpp
@@ -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
@@ -112,17 +112,20 @@ amm-info@iis.fraunhofer.de
#if defined(__arm__)
#endif
-static void multE2_DinvF_fdk(FIXP_PCM *output, FIXP_DBL *x, const FIXP_WTB *fb,
+static void multE2_DinvF_fdk(PCM_DEC *output, FIXP_DBL *x, const FIXP_WTB *fb,
FIXP_DBL *z, const int N) {
int i;
- /* scale for FIXP_DBL -> INT_PCM conversion. */
- const int scale = (DFRACT_BITS - SAMPLE_BITS) - LDFB_HEADROOM;
-#if ((DFRACT_BITS - SAMPLE_BITS - LDFB_HEADROOM) > 0)
+ /* scale for FIXP_DBL -> PCM_DEC conversion: */
+ const int scale = (DFRACT_BITS - PCM_OUT_BITS) - LDFB_HEADROOM + (3);
+
+#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - 1) > 0)
FIXP_DBL rnd_val_wts0 = (FIXP_DBL)0;
FIXP_DBL rnd_val_wts1 = (FIXP_DBL)0;
+#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - WTS0 - 1) > 0)
if (-WTS0 - 1 + scale)
rnd_val_wts0 = (FIXP_DBL)(1 << (-WTS0 - 1 + scale - 1));
+#endif
if (-WTS1 - 1 + scale)
rnd_val_wts1 = (FIXP_DBL)(1 << (-WTS1 - 1 + scale - 1));
#endif
@@ -131,24 +134,26 @@ static void multE2_DinvF_fdk(FIXP_PCM *output, FIXP_DBL *x, const FIXP_WTB *fb,
FIXP_DBL z0, z2, tmp;
z2 = x[N / 2 + i];
- z0 = z2 + (fMultDiv2(z[N / 2 + i], fb[2 * N + i]) >> (-WTS2 - 1));
+ z0 = fAddSaturate(z2,
+ (fMultDiv2(z[N / 2 + i], fb[2 * N + i]) >> (-WTS2 - 1)));
- z[N / 2 + i] = x[N / 2 - 1 - i] +
- (fMultDiv2(z[N + i], fb[2 * N + N / 2 + i]) >> (-WTS2 - 1));
+ z[N / 2 + i] = fAddSaturate(
+ x[N / 2 - 1 - i],
+ (fMultDiv2(z[N + i], fb[2 * N + N / 2 + i]) >> (-WTS2 - 1)));
tmp = (fMultDiv2(z[N / 2 + i], fb[N + N / 2 - 1 - i]) +
fMultDiv2(z[i], fb[N + N / 2 + i]));
-#if ((DFRACT_BITS - SAMPLE_BITS - LDFB_HEADROOM) > 0)
+#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - 1) > 0)
FDK_ASSERT((-WTS1 - 1 + scale) >= 0);
FDK_ASSERT(tmp <= ((FIXP_DBL)0x7FFFFFFF -
rnd_val_wts1)); /* rounding must not cause overflow */
- output[(N * 3 / 4 - 1 - i)] = (FIXP_PCM)SATURATE_RIGHT_SHIFT(
+ output[(N * 3 / 4 - 1 - i)] = (PCM_DEC)SATURATE_RIGHT_SHIFT(
tmp + rnd_val_wts1, -WTS1 - 1 + scale, PCM_OUT_BITS);
#else
FDK_ASSERT((WTS1 + 1 - scale) >= 0);
output[(N * 3 / 4 - 1 - i)] =
- (FIXP_PCM)SATURATE_LEFT_SHIFT(tmp, WTS1 + 1 - scale, PCM_OUT_BITS);
+ (PCM_DEC)SATURATE_LEFT_SHIFT(tmp, WTS1 + 1 - scale, PCM_OUT_BITS);
#endif
z[i] = z0;
@@ -159,32 +164,34 @@ static void multE2_DinvF_fdk(FIXP_PCM *output, FIXP_DBL *x, const FIXP_WTB *fb,
FIXP_DBL z0, z2, tmp0, tmp1;
z2 = x[N / 2 + i];
- z0 = z2 + (fMultDiv2(z[N / 2 + i], fb[2 * N + i]) >> (-WTS2 - 1));
+ z0 = fAddSaturate(z2,
+ (fMultDiv2(z[N / 2 + i], fb[2 * N + i]) >> (-WTS2 - 1)));
- z[N / 2 + i] = x[N / 2 - 1 - i] +
- (fMultDiv2(z[N + i], fb[2 * N + N / 2 + i]) >> (-WTS2 - 1));
+ z[N / 2 + i] = fAddSaturate(
+ x[N / 2 - 1 - i],
+ (fMultDiv2(z[N + i], fb[2 * N + N / 2 + i]) >> (-WTS2 - 1)));
tmp0 = (fMultDiv2(z[N / 2 + i], fb[N / 2 - 1 - i]) +
fMultDiv2(z[i], fb[N / 2 + i]));
tmp1 = (fMultDiv2(z[N / 2 + i], fb[N + N / 2 - 1 - i]) +
fMultDiv2(z[i], fb[N + N / 2 + i]));
-#if ((DFRACT_BITS - SAMPLE_BITS - LDFB_HEADROOM) > 0)
+#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - 1) > 0)
FDK_ASSERT((-WTS0 - 1 + scale) >= 0);
FDK_ASSERT(tmp0 <= ((FIXP_DBL)0x7FFFFFFF -
rnd_val_wts0)); /* rounding must not cause overflow */
FDK_ASSERT(tmp1 <= ((FIXP_DBL)0x7FFFFFFF -
rnd_val_wts1)); /* rounding must not cause overflow */
- output[(i - N / 4)] = (FIXP_PCM)SATURATE_RIGHT_SHIFT(
+ output[(i - N / 4)] = (PCM_DEC)SATURATE_RIGHT_SHIFT(
tmp0 + rnd_val_wts0, -WTS0 - 1 + scale, PCM_OUT_BITS);
- output[(N * 3 / 4 - 1 - i)] = (FIXP_PCM)SATURATE_RIGHT_SHIFT(
+ output[(N * 3 / 4 - 1 - i)] = (PCM_DEC)SATURATE_RIGHT_SHIFT(
tmp1 + rnd_val_wts1, -WTS1 - 1 + scale, PCM_OUT_BITS);
#else
FDK_ASSERT((WTS0 + 1 - scale) >= 0);
output[(i - N / 4)] =
- (FIXP_PCM)SATURATE_LEFT_SHIFT(tmp0, WTS0 + 1 - scale, PCM_OUT_BITS);
+ (PCM_DEC)SATURATE_LEFT_SHIFT(tmp0, WTS0 + 1 - scale, PCM_OUT_BITS);
output[(N * 3 / 4 - 1 - i)] =
- (FIXP_PCM)SATURATE_LEFT_SHIFT(tmp1, WTS1 + 1 - scale, PCM_OUT_BITS);
+ (PCM_DEC)SATURATE_LEFT_SHIFT(tmp1, WTS1 + 1 - scale, PCM_OUT_BITS);
#endif
z[i] = z0;
z[N + i] = z2;
@@ -194,22 +201,22 @@ static void multE2_DinvF_fdk(FIXP_PCM *output, FIXP_DBL *x, const FIXP_WTB *fb,
for (i = 0; i < N / 4; i++) {
FIXP_DBL tmp0 = fMultDiv2(z[i], fb[N / 2 + i]);
-#if ((DFRACT_BITS - SAMPLE_BITS - LDFB_HEADROOM) > 0)
+#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - 1) > 0)
FDK_ASSERT((-WTS0 - 1 + scale) >= 0);
FDK_ASSERT(tmp0 <= ((FIXP_DBL)0x7FFFFFFF -
rnd_val_wts0)); /* rounding must not cause overflow */
- output[(N * 3 / 4 + i)] = (FIXP_PCM)SATURATE_RIGHT_SHIFT(
+ output[(N * 3 / 4 + i)] = (PCM_DEC)SATURATE_RIGHT_SHIFT(
tmp0 + rnd_val_wts0, -WTS0 - 1 + scale, PCM_OUT_BITS);
#else
FDK_ASSERT((WTS0 + 1 - scale) >= 0);
output[(N * 3 / 4 + i)] =
- (FIXP_PCM)SATURATE_LEFT_SHIFT(tmp0, WTS0 + 1 - scale, PCM_OUT_BITS);
+ (PCM_DEC)SATURATE_LEFT_SHIFT(tmp0, WTS0 + 1 - scale, PCM_OUT_BITS);
#endif
}
}
int InvMdctTransformLowDelay_fdk(FIXP_DBL *mdctData, const int mdctData_e,
- FIXP_PCM *output, FIXP_DBL *fs_buffer,
+ PCM_DEC *output, FIXP_DBL *fs_buffer,
const int N) {
const FIXP_WTB *coef;
FIXP_DBL gain = (FIXP_DBL)0;
diff --git a/libAACdec/src/ldfiltbank.h b/libAACdec/src/ldfiltbank.h
index b63da6b..02971d0 100644
--- a/libAACdec/src/ldfiltbank.h
+++ b/libAACdec/src/ldfiltbank.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
@@ -104,9 +104,10 @@ amm-info@iis.fraunhofer.de
#define LDFILTBANK_H
#include "common_fix.h"
+#include "aac_rom.h"
int InvMdctTransformLowDelay_fdk(FIXP_DBL *mdctdata_m, const int mdctdata_e,
- FIXP_PCM *mdctOut, FIXP_DBL *fs_buffer,
+ PCM_DEC *mdctOut, FIXP_DBL *fs_buffer,
const int frameLength);
#endif
diff --git a/libAACdec/src/stereo.cpp b/libAACdec/src/stereo.cpp
index eed826b..47f1a31 100644
--- a/libAACdec/src/stereo.cpp
+++ b/libAACdec/src/stereo.cpp
@@ -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
@@ -807,19 +807,17 @@ void CJointStereo_ApplyMS(
for (int i = 0; i < windowLen; i++) {
dmx_re_prev[i] =
((staticSpectralCoeffsL[index_offset + i] >>
- srLeftChan) +
+ fMin(DFRACT_BITS - 1, srLeftChan + 1)) +
(staticSpectralCoeffsR[index_offset + i] >>
- srRightChan)) >>
- 1;
+ fMin(DFRACT_BITS - 1, srRightChan + 1)));
}
} else {
for (int i = 0; i < windowLen; i++) {
dmx_re_prev[i] =
((staticSpectralCoeffsL[index_offset + i] >>
- srLeftChan) -
+ fMin(DFRACT_BITS - 1, srLeftChan + 1)) -
(staticSpectralCoeffsR[index_offset + i] >>
- srRightChan)) >>
- 1;
+ fMin(DFRACT_BITS - 1, srRightChan + 1)));
}
}
}
@@ -854,12 +852,13 @@ void CJointStereo_ApplyMS(
if (window == 0) {
if (dmx_re_prev_e < frameMaxScale) {
if (mainband_flag == 0) {
- scaleValues(dmx_re_prev, store_dmx_re_prev, windowLen,
- -(frameMaxScale - dmx_re_prev_e));
+ scaleValues(
+ dmx_re_prev, store_dmx_re_prev, windowLen,
+ -fMin(DFRACT_BITS - 1, (frameMaxScale - dmx_re_prev_e)));
} else {
- for (int i = 0; i < windowLen; i++) {
- dmx_re_prev[i] >>= (frameMaxScale - dmx_re_prev_e);
- }
+ scaleValues(
+ dmx_re_prev, windowLen,
+ -fMin(DFRACT_BITS - 1, (frameMaxScale - dmx_re_prev_e)));
}
} else {
if (mainband_flag == 0) {
@@ -873,10 +872,9 @@ void CJointStereo_ApplyMS(
FDK_ASSERT(pAacDecoderChannelInfo[L]->icsInfo.WindowSequence ==
BLOCK_SHORT);
if (specScaleL[window - 1] < frameMaxScale) {
- for (int i = 0; i < windowLen; i++) {
- dmx_re[windowLen * (window - 1) + i] >>=
- (frameMaxScale - specScaleL[window - 1]);
- }
+ scaleValues(&dmx_re[windowLen * (window - 1)], windowLen,
+ -fMin(DFRACT_BITS - 1,
+ (frameMaxScale - specScaleL[window - 1])));
} else {
specScaleL[window] = specScaleL[window - 1];
specScaleR[window] = specScaleR[window - 1];
@@ -991,7 +989,7 @@ void CJointStereo_ApplyMS(
} /* if ( pJointStereoData->complex_coef == 1 ) */
/* 4. upmix process */
- INT pred_dir = cplxPredictionData->pred_dir ? -1 : 1;
+ LONG pred_dir = cplxPredictionData->pred_dir ? -1 : 1;
/* 0.1 in Q-3.34 */
const FIXP_DBL pointOne = 0x66666666; /* 0.8 */
/* Shift value for the downmix */
@@ -1041,34 +1039,24 @@ void CJointStereo_ApplyMS(
the downmix. "dmx_re" and "specL" are two different pointers
pointing to separate arrays, which may or may not contain the
same data (with different scaling).
- */
-
- /* help1: alpha_re[i] * dmx_re[i] */
- FIXP_DBL help1 = fMultDiv2(alpha_re_tmp, *p2dmxRe++);
- /* tmp: dmx_im[i] */
- FIXP_DBL tmp = (*p2dmxIm++) << shift_dmx;
-
- /* help2: alpha_im[i] * dmx_im[i] */
- FIXP_DBL help2 = fMultDiv2(alpha_im_tmp, tmp);
-
- /* help3: alpha_re[i] * dmx_re[i] + alpha_im[i] * dmx_im[i] */
- FIXP_DBL help3 = help1 + help2;
+ specL[i] = + (specL[i] + side);
+ specR[i] = -/+ (specL[i] - side);
+ */
+ FIXP_DBL side, left, right;
- /* side (= help4) = specR[i] - (dmx_re[i] * specL[i] + alpha_im[i]
- * * dmx_im[i]) */
- FIXP_DBL help4 = *p2CoeffR - scaleValue(help3, help3_shift);
+ side = fMultAddDiv2(fMultDiv2(alpha_re_tmp, *p2dmxRe++),
+ alpha_im_tmp, (*p2dmxIm++) << shift_dmx);
+ side = ((*p2CoeffR) >> 2) -
+ (FIXP_DBL)SATURATE_SHIFT(side, -(help3_shift - 2),
+ DFRACT_BITS - 2);
- /* We calculate the left and right output by using the helper
- * function */
- /* specR[i] = -/+ (specL[i] - side); */
- *p2CoeffR =
- (FIXP_DBL)((LONG)(*p2CoeffL - help4) * (LONG)pred_dir);
- p2CoeffR++;
+ left = ((*p2CoeffL) >> 2) + side;
+ right = ((*p2CoeffL) >> 2) - side;
+ right = (FIXP_DBL)((LONG)right * pred_dir);
- /* specL[i] = specL[i] + side; */
- *p2CoeffL = *p2CoeffL + help4;
- p2CoeffL++;
+ *p2CoeffL++ = SATURATE_LEFT_SHIFT_ALT(left, 2, DFRACT_BITS);
+ *p2CoeffR++ = SATURATE_LEFT_SHIFT_ALT(right, 2, DFRACT_BITS);
}
}
diff --git a/libAACdec/src/usacdec_acelp.cpp b/libAACdec/src/usacdec_acelp.cpp
index a606459..fbe3188 100644
--- a/libAACdec/src/usacdec_acelp.cpp
+++ b/libAACdec/src/usacdec_acelp.cpp
@@ -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
@@ -131,7 +131,7 @@ void E_UTIL_preemph(const FIXP_DBL *in, FIXP_DBL *out, INT L) {
int i;
for (i = 0; i < L; i++) {
- out[i] = in[i] - fMult(PREEMPH_FAC, in[i - 1]);
+ out[i] = fAddSaturate(in[i], -fMult(PREEMPH_FAC, in[i - 1]));
}
return;
@@ -465,7 +465,9 @@ void BuildAdaptiveExcitation(
/* Note: code[L_SUBFR] and exc2[L_SUBFR] share the same memory!
If exc2[i] is written, code[i] will be destroyed!
*/
-#define SF (SF_CODE + SF_GAIN_C + 1 - SF_EXC)
+#define SF_HEADROOM (1)
+#define SF (SF_CODE + SF_GAIN_C + 1 - SF_EXC - SF_HEADROOM)
+#define SF_GAIN_P2 (SF_GAIN_P - SF_HEADROOM)
int i;
FIXP_DBL tmp, cpe, code_smooth_prev, code_smooth;
@@ -477,8 +479,8 @@ void BuildAdaptiveExcitation(
cpe = (period_fac >> (2 - SF_PFAC)) + FL2FXCONST_DBL(0.25f);
/* u'(n) */
- tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P + 1); /* v(0)*g_p */
- *exc++ = tmp + (fMultDiv2(code[0], gain_code) << SF);
+ tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P2 + 1); /* v(0)*g_p */
+ *exc++ = (tmp + (fMultDiv2(code[0], gain_code) << SF)) << SF_HEADROOM;
/* u(n) */
code_smooth_prev = fMultDiv2(*code++, gain_code_smoothed)
@@ -487,15 +489,15 @@ void BuildAdaptiveExcitation(
code_smooth = fMultDiv2(code_i, gain_code_smoothed) << SF; /* c(1) * g_sc */
tmp += code_smooth_prev; /* tmp = v(0)*g_p + c(0)*g_sc */
cpe_code_smooth = fMultDiv2(cpe, code_smooth);
- *exc2++ = tmp - cpe_code_smooth;
+ *exc2++ = (tmp - cpe_code_smooth) << SF_HEADROOM;
cpe_code_smooth_prev = fMultDiv2(cpe, code_smooth_prev);
i = L_SUBFR - 2;
do /* ARM926: 22 cycles per iteration */
{
/* u'(n) */
- tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P + 1);
- *exc++ = tmp + (fMultDiv2(code_i, gain_code) << SF);
+ tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P2 + 1);
+ *exc++ = (tmp + (fMultDiv2(code_i, gain_code) << SF)) << SF_HEADROOM;
/* u(n) */
tmp += code_smooth; /* += g_sc * c(i) */
tmp -= cpe_code_smooth_prev;
@@ -503,16 +505,17 @@ void BuildAdaptiveExcitation(
code_i = *code++;
code_smooth = fMultDiv2(code_i, gain_code_smoothed) << SF;
cpe_code_smooth = fMultDiv2(cpe, code_smooth);
- *exc2++ = tmp - cpe_code_smooth; /* tmp - c_pe * g_sc * c(i+1) */
+ *exc2++ = (tmp - cpe_code_smooth)
+ << SF_HEADROOM; /* tmp - c_pe * g_sc * c(i+1) */
} while (--i != 0);
/* u'(n) */
- tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P + 1);
- *exc = tmp + (fMultDiv2(code_i, gain_code) << SF);
+ tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P2 + 1);
+ *exc = (tmp + (fMultDiv2(code_i, gain_code) << SF)) << SF_HEADROOM;
/* u(n) */
tmp += code_smooth;
tmp -= cpe_code_smooth_prev;
- *exc2++ = tmp;
+ *exc2++ = tmp << SF_HEADROOM;
return;
}
diff --git a/libAACdec/src/usacdec_fac.cpp b/libAACdec/src/usacdec_fac.cpp
index 0d3d844..b246171 100644
--- a/libAACdec/src/usacdec_fac.cpp
+++ b/libAACdec/src/usacdec_fac.cpp
@@ -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
@@ -344,7 +344,7 @@ INT CLpd_FAC_Mdct2Acelp(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *pFac,
/* Overlap Add */
x0 = -fMult(*pOvl--, pWindow[i].v.re);
- *pOut0 += IMDCT_SCALE_DBL(x0);
+ *pOut0 = fAddSaturate(*pOut0, IMDCT_SCALE_DBL(x0));
pOut0++;
}
} else {
@@ -354,7 +354,7 @@ INT CLpd_FAC_Mdct2Acelp(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *pFac,
/* Overlap Add */
x0 = fMult(*pOvl--, pWindow[i].v.re);
- *pOut0 += IMDCT_SCALE_DBL(x0);
+ *pOut0 = fAddSaturate(*pOut0, IMDCT_SCALE_DBL(x0));
pOut0++;
}
}
@@ -362,7 +362,7 @@ INT CLpd_FAC_Mdct2Acelp(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *pFac,
0) { /* this should only happen for ACELP -> TCX20 -> ACELP transition */
FIXP_DBL *pOut = pOut0 - fl / 2; /* fl/2 == fac_length */
for (i = 0; i < fl / 2; i++) {
- pOut[i] += IMDCT_SCALE_DBL(hMdct->pFacZir[i]);
+ pOut[i] = fAddSaturate(pOut[i], IMDCT_SCALE_DBL(hMdct->pFacZir[i]));
}
hMdct->pFacZir = NULL;
}
@@ -493,9 +493,7 @@ INT CLpd_FAC_Acelp2Mdct(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *_pSpec,
/* Div2 is compensated by table scaling */
x = fMultDiv2(pTmp2[i], FacWindowZir[w]);
x += fMultDiv2(pTmp1[-i - 1], FacWindowSynth[w]);
- x += pFAC_and_FAC_ZIR[i];
- pOut1[i] = x;
-
+ pOut1[i] = fAddSaturate(x, pFAC_and_FAC_ZIR[i]);
w++;
}
}
@@ -552,7 +550,7 @@ INT CLpd_FAC_Acelp2Mdct(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *_pSpec,
FDK_ASSERT((pOut1 >= hMdct->overlap.time &&
pOut1 < hMdct->overlap.time + hMdct->ov_size) ||
(pOut1 >= output && pOut1 < output + 1024));
- *pOut1 += IMDCT_SCALE_DBL(-x1);
+ *pOut1 = fAddSaturate(*pOut1, IMDCT_SCALE_DBL(-x1));
pOut1--;
}
@@ -578,7 +576,7 @@ INT CLpd_FAC_Acelp2Mdct(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *_pSpec,
FIXP_DBL x = -(*pCurr--);
/* 5) (item 4) Synthesis filter Zir component, FAC ZIR (another one). */
if (i < f_len) {
- x += *pF++;
+ x = fAddSaturate(x, *pF++);
}
FDK_ASSERT((pOut1 >= hMdct->overlap.time &&
@@ -668,9 +666,9 @@ INT CLpd_FAC_Acelp2Mdct(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *_pSpec,
for (i = 0; i < fl / 2; i++) {
FIXP_DBL x0, x1;
- cplxMult(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]);
- *pOut0 = IMDCT_SCALE_DBL(x0);
- *pOut1 = IMDCT_SCALE_DBL(-x1);
+ cplxMultDiv2(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]);
+ *pOut0 = IMDCT_SCALE_DBL_LSH1(x0);
+ *pOut1 = IMDCT_SCALE_DBL_LSH1(-x1);
pOut0++;
pOut1--;
}
@@ -680,9 +678,9 @@ INT CLpd_FAC_Acelp2Mdct(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *_pSpec,
for (i = 0; i < fl / 2; i++) {
FIXP_DBL x0, x1;
- cplxMult(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]);
- *pOut0 = IMDCT_SCALE_DBL(x0);
- *pOut1 = IMDCT_SCALE_DBL(x1);
+ cplxMultDiv2(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]);
+ *pOut0 = IMDCT_SCALE_DBL_LSH1(x0);
+ *pOut1 = IMDCT_SCALE_DBL_LSH1(x1);
pOut0++;
pOut1--;
}
@@ -691,9 +689,9 @@ INT CLpd_FAC_Acelp2Mdct(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *_pSpec,
for (i = 0; i < fl / 2; i++) {
FIXP_DBL x0, x1;
- cplxMult(&x1, &x0, *pCurr++, *pOvl--, pWindow_prev[i]);
- *pOut0 = IMDCT_SCALE_DBL(x0);
- *pOut1 = IMDCT_SCALE_DBL(x1);
+ cplxMultDiv2(&x1, &x0, *pCurr++, *pOvl--, pWindow_prev[i]);
+ *pOut0 = IMDCT_SCALE_DBL_LSH1(x0);
+ *pOut1 = IMDCT_SCALE_DBL_LSH1(x1);
pOut0++;
pOut1--;
}
@@ -705,7 +703,7 @@ INT CLpd_FAC_Acelp2Mdct(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *_pSpec,
FIXP_DBL *pOut = pOut0 - fl / 2;
FDK_ASSERT(fl / 2 <= 128);
for (i = 0; i < fl / 2; i++) {
- pOut[i] += IMDCT_SCALE_DBL(hMdct->pFacZir[i]);
+ pOut[i] = fAddSaturate(pOut[i], IMDCT_SCALE_DBL(hMdct->pFacZir[i]));
}
hMdct->pFacZir = NULL;
}
diff --git a/libAACdec/src/usacdec_lpc.cpp b/libAACdec/src/usacdec_lpc.cpp
index 271463f..88601b7 100644
--- a/libAACdec/src/usacdec_lpc.cpp
+++ b/libAACdec/src/usacdec_lpc.cpp
@@ -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
@@ -231,7 +231,7 @@ void nearest_neighbor_2D8(FIXP_ZF x[8], int y[8]) {
void RE8_PPV(FIXP_ZF x[], SHORT y[], int r) {
int i, y0[8], y1[8];
FIXP_ZF x1[8], tmp;
- FIXP_DBL e;
+ INT64 e;
/* find the nearest neighbor y0 of x in 2D8 */
nearest_neighbor_2D8(x, y0);
@@ -245,16 +245,16 @@ void RE8_PPV(FIXP_ZF x[], SHORT y[], int r) {
}
/* compute e0=||x-y0||^2 and e1=||x-y1||^2 */
- e = (FIXP_DBL)0;
+ e = 0;
for (i = 0; i < 8; i++) {
tmp = x[i] - INT2ZF(y0[i], 0);
- e += fPow2Div2(
+ e += (INT64)fPow2Div2(
tmp << r); /* shift left to ensure that no fract part bits get lost. */
tmp = x[i] - INT2ZF(y1[i], 0);
- e -= fPow2Div2(tmp << r);
+ e -= (INT64)fPow2Div2(tmp << r);
}
/* select best candidate y0 or y1 to minimize distortion */
- if (e < (FIXP_DBL)0) {
+ if (e < 0) {
for (i = 0; i < 8; i++) {
y[i] = y0[i];
}
@@ -565,7 +565,8 @@ static void lsf_weight_2st(FIXP_LPC *lsfq, FIXP_DBL *xq, int nk_mode) {
/* add non-weighted residual LSF vector to LSF1st */
for (i = 0; i < M_LP_FILTER_ORDER; i++) {
w = (LONG)fMultDiv2(factor, sqrtFixp(fMult(d[i], d[i + 1])));
- lsfq[i] = fAddSaturate(lsfq[i], FX_DBL2FX_LPC((FIXP_DBL)(w * (LONG)xq[i])));
+ lsfq[i] = fAddSaturate(lsfq[i],
+ FX_DBL2FX_LPC((FIXP_DBL)((INT64)w * (LONG)xq[i])));
}
return;
@@ -1138,9 +1139,12 @@ static void get_lsppol(FIXP_LPC lsp[], FIXP_DBL f[], int n, int flag) {
for (i = 2; i <= n; i++) {
plsp += 2;
b = -FX_LPC2FX_DBL(*plsp);
- f[i] = ((fMultDiv2(b, f[i - 1]) << 1) + (f[i - 2])) << 1;
+ f[i] = SATURATE_LEFT_SHIFT((fMultDiv2(b, f[i - 1]) + (f[i - 2] >> 1)), 2,
+ DFRACT_BITS);
for (j = i - 1; j > 1; j--) {
- f[j] = f[j] + (fMultDiv2(b, f[j - 1]) << 2) + f[j - 2];
+ f[j] = SATURATE_LEFT_SHIFT(
+ ((f[j] >> 2) + fMultDiv2(b, f[j - 1]) + (f[j - 2] >> 2)), 2,
+ DFRACT_BITS);
}
f[1] = f[1] + (b >> (SF_F - 1));
}
@@ -1167,6 +1171,9 @@ void E_LPC_f_lsp_a_conversion(FIXP_LPC *lsp, FIXP_LPC *a, INT *a_exp) {
/*-----------------------------------------------------*
* Multiply F1(z) by (1+z^-1) and F2(z) by (1-z^-1) *
*-----------------------------------------------------*/
+ scaleValues(f1, NC + 1, -2);
+ scaleValues(f2, NC + 1, -2);
+
for (i = NC; i > 0; i--) {
f1[i] += f1[i - 1];
f2[i] -= f2[i - 1];
@@ -1175,13 +1182,8 @@ void E_LPC_f_lsp_a_conversion(FIXP_LPC *lsp, FIXP_LPC *a, INT *a_exp) {
FIXP_DBL aDBL[M_LP_FILTER_ORDER];
for (i = 1, k = M_LP_FILTER_ORDER - 1; i <= NC; i++, k--) {
- FIXP_DBL tmp1, tmp2;
-
- tmp1 = f1[i] >> 1;
- tmp2 = f2[i] >> 1;
-
- aDBL[i - 1] = (tmp1 + tmp2);
- aDBL[k] = (tmp1 - tmp2);
+ aDBL[i - 1] = f1[i] + f2[i];
+ aDBL[k] = f1[i] - f2[i];
}
int headroom_a = getScalefactor(aDBL, M_LP_FILTER_ORDER);
@@ -1190,5 +1192,5 @@ void E_LPC_f_lsp_a_conversion(FIXP_LPC *lsp, FIXP_LPC *a, INT *a_exp) {
a[i] = FX_DBL2FX_LPC(aDBL[i] << headroom_a);
}
- *a_exp = 8 - headroom_a;
+ *a_exp = SF_F + (2 - 1) - headroom_a;
}
diff --git a/libAACdec/src/usacdec_lpd.cpp b/libAACdec/src/usacdec_lpd.cpp
index e0a2631..fbf6fab 100644
--- a/libAACdec/src/usacdec_lpd.cpp
+++ b/libAACdec/src/usacdec_lpd.cpp
@@ -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
@@ -122,17 +122,21 @@ amm-info@iis.fraunhofer.de
#include "ac_arith_coder.h"
-void filtLP(const FIXP_DBL *syn, FIXP_PCM *syn_out, FIXP_DBL *noise,
- const FIXP_SGL *filt, INT stop, int len) {
+void filtLP(const FIXP_DBL *syn, PCM_DEC *syn_out, FIXP_DBL *noise,
+ const FIXP_SGL *filt, const INT aacOutDataHeadroom, INT stop,
+ int len) {
INT i, j;
FIXP_DBL tmp;
+ FDK_ASSERT((aacOutDataHeadroom - 1) >= -(MDCT_OUTPUT_SCALE));
+
for (i = 0; i < stop; i++) {
tmp = fMultDiv2(noise[i], filt[0]); // Filt in Q-1.16
for (j = 1; j <= len; j++) {
- tmp += fMultDiv2((noise[i - j] + noise[i + j]), filt[j]);
+ tmp += fMult((noise[i - j] >> 1) + (noise[i + j] >> 1), filt[j]);
}
- syn_out[i] = (FIXP_PCM)(IMDCT_SCALE(syn[i] - tmp));
+ syn_out[i] = (PCM_DEC)(
+ IMDCT_SCALE((syn[i] >> 1) - (tmp >> 1), aacOutDataHeadroom - 1));
}
}
@@ -142,8 +146,10 @@ void bass_pf_1sf_delay(
FIXP_DBL *pit_gain,
const int frame_length, /* (i) : frame length (should be 768|1024) */
const INT l_frame,
- const INT l_next, /* (i) : look ahead for symmetric filtering */
- FIXP_PCM *synth_out, /* (o) : filtered synthesis (with delay of 1 subfr) */
+ const INT l_next, /* (i) : look ahead for symmetric filtering */
+ PCM_DEC *synth_out, /* (o) : filtered synthesis (with delay of 1 subfr) */
+ const INT aacOutDataHeadroom, /* (i) : headroom of the output time signal to
+ prevent clipping */
FIXP_DBL mem_bpf[]) /* i/o : memory state [L_FILT+L_SUBFR] */
{
INT i, sf, i_subfr, T, T2, lg;
@@ -335,17 +341,22 @@ void bass_pf_1sf_delay(
{
for (i = 0; i < lg; i++) {
- /* scaled with SF_SYNTH + gain_sf + 1 */
+ /* scaled with SF_SYNTH + gain_sf + 1; composition of scalefactor 2:
+ * one additional shift of syn values + fMult => fMultDiv2 */
noise_in[i] =
- (fMult(gainSGL, syn[i + i_subfr] - (syn[i + i_subfr - T] >> 1) -
- (syn[i + i_subfr + T] >> 1))) >>
- s1;
+ scaleValue(fMultDiv2(gainSGL, (syn[i + i_subfr] >> 1) -
+ (syn[i + i_subfr - T] >> 2) -
+ (syn[i + i_subfr + T] >> 2)),
+ 2 - s1);
}
for (i = lg; i < L_SUBFR; i++) {
- /* scaled with SF_SYNTH + gain_sf + 1 */
+ /* scaled with SF_SYNTH + gain_sf + 1; composition of scalefactor 2:
+ * one additional shift of syn values + fMult => fMultDiv2 */
noise_in[i] =
- (fMult(gainSGL, syn[i + i_subfr] - syn[i + i_subfr - T])) >> s1;
+ scaleValue(fMultDiv2(gainSGL, (syn[i + i_subfr] >> 1) -
+ (syn[i + i_subfr - T] >> 1)),
+ 2 - s1);
}
}
} else {
@@ -364,7 +375,7 @@ void bass_pf_1sf_delay(
{
filtLP(&syn[i_subfr - L_SUBFR], &synth_out[i_subfr], noise,
- fdk_dec_filt_lp, L_SUBFR, L_FILT);
+ fdk_dec_filt_lp, aacOutDataHeadroom, L_SUBFR, L_FILT);
}
}
@@ -377,9 +388,9 @@ void bass_pf_1sf_delay(
/* Output scaling of the BPF memory */
scaleValues(mem_bpf, (L_FILT + L_SUBFR), -1);
/* Copy the rest of the signal (after the fac) */
- scaleValuesSaturate((FIXP_PCM *)&synth_out[l_frame],
- (FIXP_DBL *)&syn[l_frame - L_SUBFR],
- (frame_length - l_frame), MDCT_OUT_HEADROOM);
+ scaleValuesSaturate(
+ (PCM_DEC *)&synth_out[l_frame], (FIXP_DBL *)&syn[l_frame - L_SUBFR],
+ (frame_length - l_frame), MDCT_OUT_HEADROOM - aacOutDataHeadroom);
}
return;
@@ -1222,7 +1233,7 @@ AAC_DECODER_ERROR CLpdChannelStream_Read(
(INT)(samplingRate * PIT_MIN_12k8 + (FSCALE_DENOM / 2)) / FSCALE_DENOM -
(INT)PIT_MIN_12k8;
- if ((samplingRate < 6000) || (samplingRate > 24000)) {
+ if ((samplingRate < FAC_FSCALE_MIN) || (samplingRate > FAC_FSCALE_MAX)) {
error = AAC_DEC_PARSE_ERROR;
goto bail;
}
@@ -1546,9 +1557,9 @@ void CLpdChannelStream_Decode(
AAC_DECODER_ERROR CLpd_RenderTimeSignal(
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
- CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM *pTimeData,
- INT lFrame, SamplingRateInfo *pSamplingRateInfo, UINT frameOk, UINT flags,
- UINT strmFlags) {
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC *pTimeData,
+ INT lFrame, SamplingRateInfo *pSamplingRateInfo, UINT frameOk,
+ const INT aacOutDataHeadroom, UINT flags, UINT strmFlags) {
UCHAR *mod = pAacDecoderChannelInfo->data.usac.mod;
AAC_DECODER_ERROR error = AAC_DEC_OK;
int k, i_offset;
@@ -2011,7 +2022,8 @@ AAC_DECODER_ERROR CLpd_RenderTimeSignal(
{
bass_pf_1sf_delay(p2_synth, pitch, pit_gain, lFrame, lFrame / facFB,
mod[nbDiv - 1] ? (SynDelay - (lDiv / 2)) : SynDelay,
- pTimeData, pAacDecoderStaticChannelInfo->mem_bpf);
+ pTimeData, aacOutDataHeadroom,
+ pAacDecoderStaticChannelInfo->mem_bpf);
}
}
diff --git a/libAACdec/src/usacdec_lpd.h b/libAACdec/src/usacdec_lpd.h
index 3e7938d..448dc55 100644
--- a/libAACdec/src/usacdec_lpd.h
+++ b/libAACdec/src/usacdec_lpd.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
@@ -140,13 +140,14 @@ void CLpdChannelStream_Decode(
* \param pTimeData pointer to output buffer
* \param samplesPerFrame amount of output samples
* \param pSamplingRateInfo holds the sampling rate information
- * \param pWorkBuffer1 pointer to work buffer for temporal data
+ * \param aacOutDataHeadroom headroom of the output time signal to prevent
+ * clipping
*/
AAC_DECODER_ERROR CLpd_RenderTimeSignal(
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
- CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM *pTimeData,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC *pTimeData,
INT samplesPerFrame, SamplingRateInfo *pSamplingRateInfo, UINT frameOk,
- UINT flags, UINT strmFlags);
+ const INT aacOutDataHeadroom, UINT flags, UINT strmFlags);
static inline INT CLpd_FAC_getLength(int fNotShortBlock, int fac_length_long) {
if (fNotShortBlock) {
@@ -156,8 +157,9 @@ static inline INT CLpd_FAC_getLength(int fNotShortBlock, int fac_length_long) {
}
}
-void filtLP(const FIXP_DBL *syn, FIXP_PCM *syn_out, FIXP_DBL *noise,
- const FIXP_SGL *filt, INT stop, int len);
+void filtLP(const FIXP_DBL *syn, PCM_DEC *syn_out, FIXP_DBL *noise,
+ const FIXP_SGL *filt, const INT aacOutDataHeadroom, INT stop,
+ int len);
/**
* \brief perform a low-frequency pitch enhancement on time domain signal
@@ -171,13 +173,14 @@ void filtLP(const FIXP_DBL *syn, FIXP_PCM *syn_out, FIXP_DBL *noise,
* \param[in] l_frame length of filtering, must be multiple of L_SUBFR
* \param[in] l_next length of allowed look ahead on syn[i], i < l_frame+l_next
* \param[out] synth_out pointer to time domain output signal
+ * \param[in] headroom of the output time signal to prevent clipping
* \param[in,out] mem_bpf pointer to filter memory (L_FILT+L_SUBFR)
*/
void bass_pf_1sf_delay(FIXP_DBL syn[], const INT T_sf[], FIXP_DBL *pit_gain,
const int frame_length, const INT l_frame,
- const INT l_next, FIXP_PCM *synth_out,
- FIXP_DBL mem_bpf[]);
+ const INT l_next, PCM_DEC *synth_out,
+ const INT aacOutDataHeadroom, FIXP_DBL mem_bpf[]);
/**
* \brief random sign generator for FD and TCX noise filling