aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--documentation/aacDecoder.pdfbin490978 -> 490978 bytes
-rw-r--r--documentation/aacEncoder.pdfbin443582 -> 443728 bytes
-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.cpp165
-rw-r--r--libAACdec/src/aacdec_drc.h50
-rw-r--r--libAACdec/src/aacdec_drc_types.h9
-rw-r--r--libAACdec/src/aacdecoder.cpp49
-rw-r--r--libAACdec/src/aacdecoder.h11
-rw-r--r--libAACdec/src/aacdecoder_lib.cpp232
-rw-r--r--libAACdec/src/block.cpp12
-rw-r--r--libAACdec/src/block.h8
-rw-r--r--libAACdec/src/conceal.cpp42
-rw-r--r--libAACdec/src/conceal.h4
-rw-r--r--libAACdec/src/conceal_types.h4
-rw-r--r--libAACdec/src/ldfiltbank.cpp35
-rw-r--r--libAACdec/src/ldfiltbank.h5
-rw-r--r--libAACdec/src/usacdec_lpd.cpp34
-rw-r--r--libAACdec/src/usacdec_lpd.h19
-rw-r--r--libAACenc/include/aacenc_lib.h45
-rw-r--r--libAACenc/src/aacEnc_ram.cpp4
-rw-r--r--libAACenc/src/aacEnc_ram.h4
-rw-r--r--libAACenc/src/aacenc.cpp11
-rw-r--r--libAACenc/src/aacenc_lib.cpp30
-rw-r--r--libAACenc/src/adj_thr.cpp8
-rw-r--r--libAACenc/src/bandwidth.cpp12
-rw-r--r--libAACenc/src/qc_main.cpp17
-rw-r--r--libFDK/include/FDK_qmf_domain.h20
-rw-r--r--libFDK/include/mdct.h14
-rw-r--r--libFDK/include/qmf.h105
-rw-r--r--libFDK/include/qmf_pcm.h218
-rw-r--r--libFDK/src/FDK_core.cpp4
-rw-r--r--libFDK/src/FDK_qmf_domain.cpp49
-rw-r--r--libFDK/src/qmf.cpp333
-rw-r--r--libPCMutils/include/limiter.h36
-rw-r--r--libPCMutils/src/limiter.cpp116
-rw-r--r--libPCMutils/src/version.h4
-rw-r--r--libSACdec/include/sac_dec_lib.h13
-rw-r--r--libSACdec/src/sac_dec.cpp23
-rw-r--r--libSACdec/src/sac_dec.h5
-rw-r--r--libSACdec/src/sac_dec_interface.h8
-rw-r--r--libSACdec/src/sac_dec_lib.cpp24
-rw-r--r--libSACdec/src/sac_process.cpp30
-rw-r--r--libSACdec/src/sac_qmf.cpp4
-rw-r--r--libSACdec/src/sac_qmf.h4
-rw-r--r--libSACdec/src/sac_reshapeBBEnv.cpp18
-rw-r--r--libSACdec/src/sac_rom.h15
-rw-r--r--libSBRdec/include/sbrdecoder.h15
-rw-r--r--libSBRdec/src/HFgen_preFlat.cpp4
-rw-r--r--libSBRdec/src/hbe.cpp2
-rw-r--r--libSBRdec/src/hbe.h10
-rw-r--r--libSBRdec/src/sbr_dec.cpp26
-rw-r--r--libSBRdec/src/sbr_dec.h11
-rw-r--r--libSBRdec/src/sbr_ram.cpp5
-rw-r--r--libSBRdec/src/sbr_ram.h5
-rw-r--r--libSBRdec/src/sbrdecoder.cpp32
59 files changed, 1111 insertions, 904 deletions
diff --git a/documentation/aacDecoder.pdf b/documentation/aacDecoder.pdf
index d04a7d6..cc7cf41 100644
--- a/documentation/aacDecoder.pdf
+++ b/documentation/aacDecoder.pdf
Binary files differ
diff --git a/documentation/aacEncoder.pdf b/documentation/aacEncoder.pdf
index d9300a0..77b8f4c 100644
--- a/documentation/aacEncoder.pdf
+++ b/documentation/aacEncoder.pdf
Binary files differ
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..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;
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp
index f747b2d..6a0254d 100644
--- a/libAACdec/src/aacdecoder.cpp
+++ b/libAACdec/src/aacdecoder.cpp
@@ -1281,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;
@@ -1456,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);
@@ -1493,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)
@@ -2394,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;
@@ -3170,10 +3177,8 @@ 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);
+ /* Turn off DRC modules level normalization in digital domain. */
+ aacDecoder_drcSetParam(self->hDrcInfo, APPLY_NORMALIZATION, 0);
/* deactivate legacy DRC in case uniDrc is active, i.e. uniDrc payload is
* present and one of DRC or Loudness Normalization is switched on */
@@ -3325,9 +3330,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,
@@ -3343,7 +3350,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:
@@ -3355,7 +3362,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;
@@ -3376,7 +3383,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;
@@ -3388,7 +3395,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 */
@@ -3409,27 +3417,18 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
* LR) */
if ((aacChannels == 2) && bsPseudoLr) {
int i, offset2;
- const FIXP_SGL invSqrt2 =
- FL2FXCONST_SGL(0.353553390593273f); /* scaled by -1 */
- FIXP_PCM *pTD = pTimeData;
+ const FIXP_SGL invSqrt2 = FL2FXCONST_SGL(0.707106781186547f);
+ 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] = (FIXP_SGL)SATURATE_RIGHT_SHIFT(L + R + (FIXP_DBL)(1 << 14),
- 15, FRACT_BITS);
- pTD[offset2] = (FIXP_SGL)SATURATE_RIGHT_SHIFT(
- L - R + (FIXP_DBL)(1 << 14), 15, FRACT_BITS);
-#else
- pTD[0] = SATURATE_LEFT_SHIFT(FX_DBL2FX_PCM(L + R), 1, DFRACT_BITS);
- pTD[offset2] =
- SATURATE_LEFT_SHIFT(FX_DBL2FX_PCM(L - R), 1, DFRACT_BITS);
-#endif
+ pTD[0] = L + R;
+ pTD[offset2] = L - R;
pTD++;
}
}
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 2ba0e86..f5ce7e0 100644
--- a/libAACdec/src/aacdecoder_lib.cpp
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -119,8 +119,8 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */
#define AACDECODER_LIB_VL0 3
-#define AACDECODER_LIB_VL1 1
-#define AACDECODER_LIB_VL2 3
+#define AACDECODER_LIB_VL1 2
+#define AACDECODER_LIB_VL2 0
#define AACDECODER_LIB_TITLE "AAC Decoder Lib"
#ifdef __ANDROID__
#define AACDECODER_LIB_BUILD_DATE ""
@@ -1131,35 +1131,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;
}
@@ -1315,19 +1311,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 */
@@ -1352,7 +1352,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;
@@ -1366,10 +1366,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
@@ -1416,8 +1416,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:
@@ -1474,18 +1472,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
@@ -1564,10 +1562,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) {
@@ -1590,8 +1589,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;
@@ -1612,11 +1611,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
@@ -1644,17 +1643,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);
+ }
}
}
@@ -1709,22 +1706,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 */
@@ -1759,7 +1755,7 @@ 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);
}
}
@@ -1799,6 +1795,9 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
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) && (accessUnit == 0)) {
/* delete data from the past (e.g. mixdown coeficients) */
@@ -1811,17 +1810,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;
@@ -1833,13 +1827,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;
@@ -1848,44 +1864,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,
@@ -1981,20 +2025,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 379e63a..0939bb5 100644
--- a/libAACdec/src/conceal.cpp
+++ b/libAACdec/src/conceal.cpp
@@ -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;
@@ -1844,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
*/
@@ -1957,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;
@@ -1969,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;
@@ -1987,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));
}
}
@@ -2050,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;
@@ -2070,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 1898557..13e61a5 100644
--- a/libAACdec/src/ldfiltbank.cpp
+++ b/libAACdec/src/ldfiltbank.cpp
@@ -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
@@ -141,16 +144,16 @@ static void multE2_DinvF_fdk(FIXP_PCM *output, FIXP_DBL *x, const FIXP_WTB *fb,
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;
@@ -173,22 +176,22 @@ static void multE2_DinvF_fdk(FIXP_PCM *output, FIXP_DBL *x, const FIXP_WTB *fb,
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;
@@ -198,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/usacdec_lpd.cpp b/libAACdec/src/usacdec_lpd.cpp
index de0c2de..fbf6fab 100644
--- a/libAACdec/src/usacdec_lpd.cpp
+++ b/libAACdec/src/usacdec_lpd.cpp
@@ -122,18 +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 += fMult((noise[i - j] >> 1) + (noise[i + j] >> 1), filt[j]);
}
- syn_out[i] = (FIXP_PCM)(SATURATE_SHIFT(
- (syn[i] >> 1) - (tmp >> 1), (MDCT_OUTPUT_SCALE - 1), PCM_OUT_BITS));
+ syn_out[i] = (PCM_DEC)(
+ IMDCT_SCALE((syn[i] >> 1) - (tmp >> 1), aacOutDataHeadroom - 1));
}
}
@@ -143,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;
@@ -370,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);
}
}
@@ -383,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;
@@ -1552,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;
@@ -2017,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
diff --git a/libAACenc/include/aacenc_lib.h b/libAACenc/include/aacenc_lib.h
index 01a9d36..71f7556 100644
--- a/libAACenc/include/aacenc_lib.h
+++ b/libAACenc/include/aacenc_lib.h
@@ -436,31 +436,32 @@ audio quality.
\subsection vbrmode Variable Bitrate Mode
-The encoder provides various Variable Bitrate Modes that differ in audio quality
-and average overall bitrate. The given values are averages over time, different
-encoder settings and strongly depend on the type of audio signal. The VBR
-configurations can be adjusted via ::AACENC_BITRATEMODE encoder parameter.
+The variable bitrate (VBR) mode coding adapts the bit consumption to the
+psychoacoustic requirements of the signal. The encoder ignores the user-defined
+bit rate and selects a suitable pre-defined configuration based on the provided
+AOT. The VBR mode 1 is tuned for HE-AACv2, for VBR mode 2, HE-AACv1 should be
+used. VBR modes 3-5 should be used with Low-Complexity AAC. When encoding
+AAC-ELD, the best mode is selected automatically.
+
+The bitrates given in the table are averages over time and different encoder
+settings. They strongly depend on the type of audio signal. The VBR
+configurations can be adjusted with the ::AACENC_BITRATEMODE encoder parameter.
\verbatim
---------------------------------------------
- VBR_MODE | Approx. Bitrate in kbps/channel
- | AAC-LC | AAC-LD/AC_ELD
-----------+---------------+-----------------
- VBR_1 | 32 - 48 | 32 - 56
- VBR_2 | 40 - 56 | 40 - 64
- VBR_3 | 48 - 64 | 48 - 72
- VBR_4 | 64 - 80 | 64 - 88
- VBR_5 | 96 - 120 | 112 - 144
+-----------------------------------------------
+ VBR_MODE | Approx. Bitrate in kbps for stereo
+ | AAC-LC | AAC-ELD
+----------+---------------+--------------------
+ VBR_1 | 32 (HE-AACv2) | 48
+ VBR_2 | 72 (HE-AACv1) | 56
+ VBR_3 | 112 | 72
+ VBR_4 | 148 | 148
+ VBR_5 | 228 | 224
--------------------------------------------
\endverbatim
-The bitrate ranges apply for individual audio channels. In case of multichannel
-configurations the average bitrate might be estimated by multiplying with the
-number of effective channels. This corresponds to all audio input channels
-exclusively the low frequency channel. At configurations which are making use of
-downmix modules the AAC core channels respectively downmix channels shall be
-considered. For ::AACENC_AOT which are using SBR, the average bitrate can be
-estimated by using the ratio of 0.5 for dualrate SBR and 0.75 for downsampled
-SBR configurations.
-
+Note that these figures are valid for stereo encoding only. VBR modes 2-5 will
+yield much lower bit rates when encoding single-channel input. For
+configurations which are making use of downmix modules the AAC core channels
+respectively downmix channels shall be considered.
\subsection encQual Audio Quality Considerations
The default encoder configuration is suggested to be used. Encoder tools such as
diff --git a/libAACenc/src/aacEnc_ram.cpp b/libAACenc/src/aacEnc_ram.cpp
index 77b1131..25e2aec 100644
--- a/libAACenc/src/aacEnc_ram.cpp
+++ b/libAACenc/src/aacEnc_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
@@ -204,5 +204,5 @@ QC_OUT_CHANNEL *GetRam_aacEnc_QCchannel(int n, UCHAR *dynamic_RAM) {
* (dynamic_RAM + P_BUF_0 + n*sizeof(QC_OUT_CHANNEL)) is sufficiently aligned,
* so the cast is safe */
return reinterpret_cast<QC_OUT_CHANNEL *>(reinterpret_cast<void *>(
- dynamic_RAM + P_BUF_0 + n * sizeof(QC_OUT_CHANNEL)));
+ dynamic_RAM + P_BUF_0 + n * ALIGN_SIZE(sizeof(QC_OUT_CHANNEL))));
}
diff --git a/libAACenc/src/aacEnc_ram.h b/libAACenc/src/aacEnc_ram.h
index 0775aae..f24eef1 100644
--- a/libAACenc/src/aacEnc_ram.h
+++ b/libAACenc/src/aacEnc_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
@@ -198,7 +198,7 @@ struct AAC_ENC {
+++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
-#define BUF_SIZE_0 (ALIGN_SIZE(sizeof(QC_OUT_CHANNEL) * (8)))
+#define BUF_SIZE_0 (ALIGN_SIZE(sizeof(QC_OUT_CHANNEL)) * (8))
#define BUF_SIZE_1 \
(ALIGN_SIZE(maxSize(maxSize(sizeof(PSY_DYNAMIC), \
(BIT_LOOK_UP_SIZE + MERGE_GAIN_LOOK_UP_SIZE)), \
diff --git a/libAACenc/src/aacenc.cpp b/libAACenc/src/aacenc.cpp
index 8b8a1ad..b6f733d 100644
--- a/libAACenc/src/aacenc.cpp
+++ b/libAACenc/src/aacenc.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
@@ -114,6 +114,8 @@ amm-info@iis.fraunhofer.de
#include "genericStds.h"
+#define BITRES_MIN \
+ 300 /* default threshold for using reduced/disabled bitres mode */
#define BITRES_MAX_LD 4000
#define BITRES_MIN_LD 500
#define BITRATE_MAX_LD 70000 /* Max assumed bitrate for bitres calculation */
@@ -550,7 +552,8 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize(
(config->minBitsPerFrame != -1) ? config->minBitsPerFrame : 0;
qcInit.minBits = fixMin(qcInit.minBits, averageBitsPerFrame & ~7);
} else {
- INT bitreservoir = -1; /* default bitrservoir size*/
+ INT bitreservoir = -1; /* default bitreservoir size*/
+ bitresMin = BITRES_MIN;
if (isLowDelay(config->audioObjectType)) {
INT brPerChannel = config->bitRate / config->nChannels;
brPerChannel = fMin(BITRATE_MAX_LD, fMax(BITRATE_MIN_LD, brPerChannel));
@@ -601,9 +604,9 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize(
qcInit.nSubFrames = config->nSubFrames;
qcInit.padding.paddingRest = config->sampleRate;
- if (qcInit.bitRes >= bitresMin * config->nChannels) {
+ if (qcInit.maxBits - qcInit.averageBits >= bitresMin * config->nChannels) {
qcInit.bitResMode = AACENC_BR_MODE_FULL; /* full bitreservoir */
- } else if (qcInit.bitRes > 0) {
+ } else if (qcInit.maxBits > qcInit.averageBits) {
qcInit.bitResMode = AACENC_BR_MODE_REDUCED; /* reduced bitreservoir */
} else {
qcInit.bitResMode = AACENC_BR_MODE_DISABLED; /* disabled bitreservoir */
diff --git a/libAACenc/src/aacenc_lib.cpp b/libAACenc/src/aacenc_lib.cpp
index 0f0094f..2c2010f 100644
--- a/libAACenc/src/aacenc_lib.cpp
+++ b/libAACenc/src/aacenc_lib.cpp
@@ -110,7 +110,7 @@ amm-info@iis.fraunhofer.de
/* Encoder library info */
#define AACENCODER_LIB_VL0 4
#define AACENCODER_LIB_VL1 0
-#define AACENCODER_LIB_VL2 0
+#define AACENCODER_LIB_VL2 1
#define AACENCODER_LIB_TITLE "AAC Encoder"
#ifdef __ANDROID__
#define AACENCODER_LIB_BUILD_DATE ""
@@ -446,6 +446,24 @@ static SBR_PS_SIGNALING getSbrSignalingMode(
return sbrSignaling;
}
+static inline INT getAssociatedChElement(SBR_ELEMENT_INFO *elInfoSbr,
+ CHANNEL_MAPPING *channelMapping) {
+ ELEMENT_INFO *elInfo = channelMapping->elInfo;
+ INT nElements = channelMapping->nElements;
+ INT associatedChElement = -1;
+ int i;
+
+ for (i = 0; i < nElements; i++) {
+ if (elInfoSbr->elType == elInfo[i].elType &&
+ elInfoSbr->instanceTag == elInfo[i].instanceTag) {
+ associatedChElement = i;
+ break;
+ }
+ }
+
+ return associatedChElement;
+}
+
/****************************************************************************
Allocate Encoder
****************************************************************************/
@@ -1921,7 +1939,15 @@ AACENC_ERROR aacEncEncode(const HANDLE_AACENCODER hAacEncoder,
{
hAacEncoder->extPayload[nExtensions].dataSize =
hAacEncoder->pSbrPayload->dataSize[nPayload][i];
- hAacEncoder->extPayload[nExtensions].associatedChElement = i;
+ hAacEncoder->extPayload[nExtensions].associatedChElement =
+ getAssociatedChElement(
+ &hAacEncoder->hEnvEnc->sbrElement[i]->elInfo,
+ &hAacEncoder->hAacEnc->channelMapping);
+ if (hAacEncoder->extPayload[nExtensions].associatedChElement ==
+ -1) {
+ err = AACENC_ENCODE_ERROR;
+ goto bail;
+ }
}
hAacEncoder->extPayload[nExtensions].dataType =
EXT_SBR_DATA; /* Once SBR Encoder supports SBR CRC set
diff --git a/libAACenc/src/adj_thr.cpp b/libAACenc/src/adj_thr.cpp
index 226d003..239abd0 100644
--- a/libAACenc/src/adj_thr.cpp
+++ b/libAACenc/src/adj_thr.cpp
@@ -1302,14 +1302,6 @@ static void FDKaacEnc_reduceThresholdsVBR(
if (sfbThrReducedLdData < FL2FXCONST_DBL(-0.5f))
sfbThrReducedLdData = FL2FXCONST_DBL(-1.f);
- /* minimum of 29 dB Ratio for Thresholds */
- if ((sfbEnLdData + FL2FXCONST_DBL(1.0f)) >
- FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING)) {
- sfbThrReducedLdData = fixMax(
- sfbThrReducedLdData,
- sfbEnLdData - FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING));
- }
-
sfbThrReducedLdData = fixMax(MIN_LDTHRESH, sfbThrReducedLdData);
qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData;
diff --git a/libAACenc/src/bandwidth.cpp b/libAACenc/src/bandwidth.cpp
index 36cd64d..e814f05 100644
--- a/libAACenc/src/bandwidth.cpp
+++ b/libAACenc/src/bandwidth.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
@@ -151,11 +151,11 @@ typedef struct {
static const BANDWIDTH_TAB_VBR bandWidthTableVBR[] = {
{AACENC_BR_MODE_CBR, 0, 0},
- {AACENC_BR_MODE_VBR_1, 13050, 13050},
- {AACENC_BR_MODE_VBR_2, 13050, 13050},
- {AACENC_BR_MODE_VBR_3, 14260, 14260},
- {AACENC_BR_MODE_VBR_4, 15500, 15500},
- {AACENC_BR_MODE_VBR_5, 48000, 48000},
+ {AACENC_BR_MODE_VBR_1, 13000, 13000},
+ {AACENC_BR_MODE_VBR_2, 13000, 13000},
+ {AACENC_BR_MODE_VBR_3, 15750, 15750},
+ {AACENC_BR_MODE_VBR_4, 16500, 16500},
+ {AACENC_BR_MODE_VBR_5, 19293, 19293},
{AACENC_BR_MODE_SFR, 0, 0},
{AACENC_BR_MODE_FF, 0, 0}
diff --git a/libAACenc/src/qc_main.cpp b/libAACenc/src/qc_main.cpp
index ba3bc7e..bcfaa23 100644
--- a/libAACenc/src/qc_main.cpp
+++ b/libAACenc/src/qc_main.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
@@ -121,20 +121,15 @@ typedef struct {
static const TAB_VBR_QUAL_FACTOR tableVbrQualFactor[] = {
{QCDATA_BR_MODE_VBR_1,
- FL2FXCONST_DBL(0.160f)}, /* Approx. 32 - 48 (AC-LC), 32 - 56
- (AAC-LD/ELD) kbps/channel */
+ FL2FXCONST_DBL(0.150f)}, /* Approx. 32 kbps mono AAC-LC + SBR + PS */
{QCDATA_BR_MODE_VBR_2,
- FL2FXCONST_DBL(0.148f)}, /* Approx. 40 - 56 (AC-LC), 40 - 64
- (AAC-LD/ELD) kbps/channel */
+ FL2FXCONST_DBL(0.162f)}, /* Approx. 64 kbps stereo AAC-LC + SBR */
{QCDATA_BR_MODE_VBR_3,
- FL2FXCONST_DBL(0.135f)}, /* Approx. 48 - 64 (AC-LC), 48 - 72
- (AAC-LD/ELD) kbps/channel */
+ FL2FXCONST_DBL(0.176f)}, /* Approx. 96 kbps stereo AAC-LC */
{QCDATA_BR_MODE_VBR_4,
- FL2FXCONST_DBL(0.111f)}, /* Approx. 64 - 80 (AC-LC), 64 - 88
- (AAC-LD/ELD) kbps/channel */
+ FL2FXCONST_DBL(0.120f)}, /* Approx. 128 kbps stereo AAC-LC */
{QCDATA_BR_MODE_VBR_5,
- FL2FXCONST_DBL(0.070f)} /* Approx. 96 - 120 (AC-LC), 112 - 144
- (AAC-LD/ELD) kbps/channel */
+ FL2FXCONST_DBL(0.070f)} /* Approx. 192 kbps stereo AAC-LC */
};
static INT isConstantBitrateMode(const QCDATA_BR_MODE bitrateMode) {
diff --git a/libFDK/include/FDK_qmf_domain.h b/libFDK/include/FDK_qmf_domain.h
index 5c12682..0e83da3 100644
--- a/libFDK/include/FDK_qmf_domain.h
+++ b/libFDK/include/FDK_qmf_domain.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
@@ -123,11 +123,10 @@ typedef enum {
#define QMF_WB_SECTION_SIZE (1024 * 2)
H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore1, FIXP_DBL)
-H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore2, FIXP_DBL)
H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore3, FIXP_DBL)
H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore4, FIXP_DBL)
-H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore5, FIXP_DBL)
H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore6, FIXP_DBL)
+H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore7, FIXP_DBL)
#define QMF_DOMAIN_MAX_ANALYSIS_QMF_BANDS (64)
#define QMF_DOMAIN_MAX_SYNTHESIS_QMF_BANDS (QMF_MAX_SYNTHESIS_BANDS)
@@ -145,15 +144,15 @@ H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore6, FIXP_DBL)
#define QMF_DOMAIN_OV_TIMESLOTS_16 (3)
#define QMF_DOMAIN_OV_TIMESLOTS_32 (6)
-H_ALLOC_MEM(AnaQmfStates, FIXP_QAS)
+H_ALLOC_MEM(AnaQmfStates, FIXP_DBL)
H_ALLOC_MEM(SynQmfStates, FIXP_QSS)
H_ALLOC_MEM(QmfSlotsReal, FIXP_DBL *)
H_ALLOC_MEM(QmfSlotsImag, FIXP_DBL *)
H_ALLOC_MEM(QmfOverlapBuffer, FIXP_DBL)
-H_ALLOC_MEM(AnaQmfStates16, FIXP_QAS)
-H_ALLOC_MEM(AnaQmfStates24, FIXP_QAS)
-H_ALLOC_MEM(AnaQmfStates32, FIXP_QAS)
+H_ALLOC_MEM(AnaQmfStates16, FIXP_DBL)
+H_ALLOC_MEM(AnaQmfStates24, FIXP_DBL)
+H_ALLOC_MEM(AnaQmfStates32, FIXP_DBL)
H_ALLOC_MEM(QmfSlotsReal16, FIXP_DBL *)
H_ALLOC_MEM(QmfSlotsReal32, FIXP_DBL *)
H_ALLOC_MEM(QmfSlotsImag16, FIXP_DBL *)
@@ -161,8 +160,6 @@ H_ALLOC_MEM(QmfSlotsImag32, FIXP_DBL *)
H_ALLOC_MEM(QmfOverlapBuffer16, FIXP_DBL)
H_ALLOC_MEM(QmfOverlapBuffer32, FIXP_DBL)
-#define QDOM_PCM INT_PCM
-
/**
* Structure to hold the configuration data which is global whithin a QMF domain
* instance.
@@ -182,9 +179,6 @@ typedef struct {
park a channel if only one processing channel is
available. */
UCHAR parkChannel_requested;
- QDOM_PCM
- *TDinput; /*!< Pointer to time domain data used as input for the QMF
- analysis. */
FIXP_DBL *
pWorkBuffer[QMF_MAX_WB_SECTIONS]; /*!< Pointerarray to volatile memory. */
UINT flags; /*!< Flags to be set on all QMF analysis/synthesis filter
@@ -244,7 +238,7 @@ typedef struct {
(workBuf_nTimeSlots * workBuf_nBands * CMPLX_MOD). */
USHORT workBufferOffset; /*!< Offset within work buffer. */
USHORT workBufferSectSize; /*!< Size of work buffer section. */
- FIXP_QAS *
+ FIXP_DBL *
pAnaQmfStates; /*!< Pointer to QMF analysis states (persistent memory). */
FIXP_DBL
*pOverlapBuffer; /*!< Pointer to QMF overlap/delay memory (persistent
diff --git a/libFDK/include/mdct.h b/libFDK/include/mdct.h
index 1382374..e7cf3ad 100644
--- a/libFDK/include/mdct.h
+++ b/libFDK/include/mdct.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
@@ -106,18 +106,16 @@ amm-info@iis.fraunhofer.de
#include "common_fix.h"
#define MDCT_OUT_HEADROOM 2 /* Output additional headroom */
-#define PCM_OUT_BITS SAMPLE_BITS
+
+#define PCM_OUT_BITS DFRACT_BITS
#define PCM_OUT_HEADROOM 8 /* Must have the same values as DMXH_HEADROOM */
-#define MDCT_OUTPUT_SCALE (-MDCT_OUT_HEADROOM + (DFRACT_BITS - SAMPLE_BITS))
+#define MDCT_OUTPUT_SCALE (-MDCT_OUT_HEADROOM + (DFRACT_BITS - PCM_OUT_BITS))
/* Refer to "Output word length" in ISO/IEC 14496-3:2008(E) 23.2.3.6 */
#define MDCT_OUTPUT_GAIN 16
-#if (MDCT_OUTPUT_SCALE >= 0)
-#define IMDCT_SCALE(x) SATURATE_RIGHT_SHIFT(x, MDCT_OUTPUT_SCALE, PCM_OUT_BITS)
-#else
-#define IMDCT_SCALE(x) SATURATE_LEFT_SHIFT(x, -MDCT_OUTPUT_SCALE, PCM_OUT_BITS)
-#endif
+#define IMDCT_SCALE(x, s) \
+ SATURATE_RIGHT_SHIFT((x), ((s) + MDCT_OUTPUT_SCALE), PCM_OUT_BITS)
#define IMDCT_SCALE_DBL(x) (FIXP_DBL)(x)
#define IMDCT_SCALE_DBL_LSH1(x) SATURATE_LEFT_SHIFT_ALT((x), 1, DFRACT_BITS)
diff --git a/libFDK/include/qmf.h b/libFDK/include/qmf.h
index 609c6f1..78770b3 100644
--- a/libFDK/include/qmf.h
+++ b/libFDK/include/qmf.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
@@ -116,6 +116,7 @@ amm-info@iis.fraunhofer.de
#define FIXP_QAS FIXP_PCM
#define QAS_BITS SAMPLE_BITS
+#define INT_PCM_QMFIN INT_PCM
#define FIXP_QSS FIXP_DBL
#define QSS_BITS DFRACT_BITS
@@ -201,66 +202,70 @@ struct QMF_FILTER_BANK {
typedef struct QMF_FILTER_BANK *HANDLE_QMF_FILTER_BANK;
+int qmfInitAnalysisFilterBank(
+ HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */
+ FIXP_QAS *pFilterStates, /*!< Pointer to filter state buffer */
+ int noCols, /*!< Number of time slots */
+ int lsb, /*!< Number of lower bands */
+ int usb, /*!< Number of upper bands */
+ int no_channels, /*!< Number of critically sampled bands */
+ int flags); /*!< Flags */
+#if SAMPLE_BITS == 16
+
+int qmfInitAnalysisFilterBank(
+ HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */
+ FIXP_DBL *pFilterStates, /*!< Pointer to filter state buffer */
+ int noCols, /*!< Number of time slots */
+ int lsb, /*!< Number of lower bands */
+ int usb, /*!< Number of upper bands */
+ int no_channels, /*!< Number of critically sampled bands */
+ int flags); /*!< Flags */
+#endif
+
void qmfAnalysisFiltering(
HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */
FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */
FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */
QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */
- const LONG *timeIn, /*!< Time signal */
+ const INT_PCM *timeIn, /*!< Time signal */
const int timeIn_e, /*!< Exponent of audio data */
const int stride, /*!< Stride factor of audio data */
- FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */
+ FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */
);
+#if SAMPLE_BITS == 16
void qmfAnalysisFiltering(
HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */
FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */
FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */
QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */
- const INT_PCM *timeIn, /*!< Time signal */
+ const LONG *timeIn, /*!< Time signal */
const int timeIn_e, /*!< Exponent of audio data */
const int stride, /*!< Stride factor of audio data */
- FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */
-);
-
-void qmfSynthesisFiltering(
- HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */
- FIXP_DBL **QmfBufferReal, /*!< Pointer to real subband slots */
- FIXP_DBL **QmfBufferImag, /*!< Pointer to imag subband slots */
- const QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */
- const int ov_len, /*!< Length of band overlap */
- INT_PCM *timeOut, /*!< Time signal */
- const INT stride, /*!< Stride factor of audio data */
- FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer. It must be
- aligned */
+ FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */
);
-
-int qmfInitAnalysisFilterBank(
- HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */
- FIXP_QAS *pFilterStates, /*!< Pointer to filter state buffer */
- int noCols, /*!< Number of time slots */
- int lsb, /*!< Number of lower bands */
- int usb, /*!< Number of upper bands */
- int no_channels, /*!< Number of critically sampled bands */
- int flags); /*!< Flags */
+#endif
void qmfAnalysisFilteringSlot(
HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */
FIXP_DBL *qmfReal, /*!< Low and High band, real */
FIXP_DBL *qmfImag, /*!< Low and High band, imag */
- const LONG *timeIn, /*!< Pointer to input */
+ const INT_PCM *timeIn, /*!< Pointer to input */
const int stride, /*!< stride factor of input */
- FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */
+ FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */
);
+#if SAMPLE_BITS == 16
void qmfAnalysisFilteringSlot(
HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */
FIXP_DBL *qmfReal, /*!< Low and High band, real */
FIXP_DBL *qmfImag, /*!< Low and High band, imag */
- const INT_PCM *timeIn, /*!< Pointer to input */
+ const LONG *timeIn, /*!< Pointer to input */
const int stride, /*!< stride factor of input */
- FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */
+ FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */
);
+#endif
+
int qmfInitSynthesisFilterBank(
HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */
FIXP_QSS *pFilterStates, /*!< Pointer to filter state buffer */
@@ -270,12 +275,46 @@ int qmfInitSynthesisFilterBank(
int no_channels, /*!< Number of critically sampled bands */
int flags); /*!< Flags */
+void qmfSynthesisFiltering(
+ HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */
+ FIXP_DBL **QmfBufferReal, /*!< Pointer to real subband slots */
+ FIXP_DBL **QmfBufferImag, /*!< Pointer to imag subband slots */
+ const QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */
+ const int ov_len, /*!< Length of band overlap */
+ INT_PCM *timeOut, /*!< Time signal */
+ const INT stride, /*!< Stride factor of audio data */
+ FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer. It must be
+ aligned */
+);
+#if SAMPLE_BITS == 16
+
+void qmfSynthesisFiltering(
+ HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */
+ FIXP_DBL **QmfBufferReal, /*!< Pointer to real subband slots */
+ FIXP_DBL **QmfBufferImag, /*!< Pointer to imag subband slots */
+ const QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */
+ const int ov_len, /*!< Length of band overlap */
+ LONG *timeOut, /*!< Time signal */
+ const int timeOut_e, /*!< Target exponent for timeOut */
+ FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */
+);
+#endif
+
void qmfSynthesisFilteringSlot(HANDLE_QMF_FILTER_BANK synQmf,
const FIXP_DBL *realSlot,
const FIXP_DBL *imagSlot,
const int scaleFactorLowBand,
const int scaleFactorHighBand, INT_PCM *timeOut,
const int timeOut_e, FIXP_DBL *pWorkBuffer);
+#if SAMPLE_BITS == 16
+
+void qmfSynthesisFilteringSlot(HANDLE_QMF_FILTER_BANK synQmf,
+ const FIXP_DBL *realSlot,
+ const FIXP_DBL *imagSlot,
+ const int scaleFactorLowBand,
+ const int scaleFactorHighBand, LONG *timeOut,
+ const int timeOut_e, FIXP_DBL *pWorkBuffer);
+#endif
void qmfChangeOutScalefactor(
HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */
@@ -291,11 +330,5 @@ void qmfChangeOutGain(
FIXP_DBL outputGain, /*!< New gain for output data (mantissa) */
int outputGainScale /*!< New gain for output data (exponent) */
);
-void qmfSynPrototypeFirSlot(
- HANDLE_QMF_FILTER_BANK qmf,
- FIXP_DBL *RESTRICT realSlot, /*!< Input: Pointer to real Slot */
- FIXP_DBL *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */
- INT_PCM *RESTRICT timeOut, /*!< Time domain data */
- const int timeOut_e);
#endif /*ifndef QMF_H */
diff --git a/libFDK/include/qmf_pcm.h b/libFDK/include/qmf_pcm.h
index f24e0cd..5da53db 100644
--- a/libFDK/include/qmf_pcm.h
+++ b/libFDK/include/qmf_pcm.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
@@ -402,4 +402,220 @@ void qmfSynthesisFiltering(
timeOut + (i * L * stride), stride, pWorkBuffer);
} /* no_col loop i */
}
+
+/*!
+ *
+ * \brief Create QMF filter bank instance
+ *
+ *
+ * \return 0 if successful
+ *
+ */
+int qmfInitAnalysisFilterBank(
+ HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */
+ FIXP_QAS *pFilterStates, /*!< Handle to filter states */
+ int noCols, /*!< Number of timeslots per frame */
+ int lsb, /*!< lower end of QMF */
+ int usb, /*!< upper end of QMF */
+ int no_channels, /*!< Number of channels (bands) */
+ int flags) /*!< Low Power flag */
+{
+ int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb,
+ no_channels, flags, 0);
+ if (!(flags & QMF_FLAG_KEEP_STATES) && (h_Qmf->FilterStates != NULL)) {
+ FDKmemclear(h_Qmf->FilterStates,
+ (2 * QMF_NO_POLY - 1) * h_Qmf->no_channels * sizeof(FIXP_QAS));
+ }
+
+ FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->lsb);
+
+ return err;
+}
+
+#ifndef FUNCTION_qmfAnaPrototypeFirSlot
+/*!
+ \brief Perform Analysis Prototype Filtering on a single slot of input data.
+*/
+static void qmfAnaPrototypeFirSlot(
+ FIXP_DBL *analysisBuffer,
+ INT no_channels, /*!< Number channels of analysis filter */
+ const FIXP_PFT *p_filter, INT p_stride, /*!< Stride of analysis filter */
+ FIXP_QAS *RESTRICT pFilterStates) {
+ INT k;
+
+ FIXP_DBL accu;
+ const FIXP_PFT *RESTRICT p_flt = p_filter;
+ FIXP_DBL *RESTRICT pData_0 = analysisBuffer + 2 * no_channels - 1;
+ FIXP_DBL *RESTRICT pData_1 = analysisBuffer;
+
+ FIXP_QAS *RESTRICT sta_0 = (FIXP_QAS *)pFilterStates;
+ FIXP_QAS *RESTRICT sta_1 =
+ (FIXP_QAS *)pFilterStates + (2 * QMF_NO_POLY * no_channels) - 1;
+ INT pfltStep = QMF_NO_POLY * (p_stride);
+ INT staStep1 = no_channels << 1;
+ INT staStep2 = (no_channels << 3) - 1; /* Rewind one less */
+
+ /* FIR filters 127..64 0..63 */
+ for (k = 0; k < no_channels; k++) {
+ accu = fMultDiv2(p_flt[0], *sta_1);
+ sta_1 -= staStep1;
+ accu += fMultDiv2(p_flt[1], *sta_1);
+ sta_1 -= staStep1;
+ accu += fMultDiv2(p_flt[2], *sta_1);
+ sta_1 -= staStep1;
+ accu += fMultDiv2(p_flt[3], *sta_1);
+ sta_1 -= staStep1;
+ accu += fMultDiv2(p_flt[4], *sta_1);
+ *pData_1++ = (accu << 1);
+ sta_1 += staStep2;
+
+ p_flt += pfltStep;
+ accu = fMultDiv2(p_flt[0], *sta_0);
+ sta_0 += staStep1;
+ accu += fMultDiv2(p_flt[1], *sta_0);
+ sta_0 += staStep1;
+ accu += fMultDiv2(p_flt[2], *sta_0);
+ sta_0 += staStep1;
+ accu += fMultDiv2(p_flt[3], *sta_0);
+ sta_0 += staStep1;
+ accu += fMultDiv2(p_flt[4], *sta_0);
+ *pData_0-- = (accu << 1);
+ sta_0 -= staStep2;
+ }
+}
+#endif /* !defined(FUNCTION_qmfAnaPrototypeFirSlot) */
+
+#ifndef FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric
+/*!
+ \brief Perform Analysis Prototype Filtering on a single slot of input data.
+*/
+static void qmfAnaPrototypeFirSlot_NonSymmetric(
+ FIXP_DBL *analysisBuffer,
+ int no_channels, /*!< Number channels of analysis filter */
+ const FIXP_PFT *p_filter, int p_stride, /*!< Stride of analysis filter */
+ FIXP_QAS *RESTRICT pFilterStates) {
+ const FIXP_PFT *RESTRICT p_flt = p_filter;
+ int p, k;
+
+ for (k = 0; k < 2 * no_channels; k++) {
+ FIXP_DBL accu = (FIXP_DBL)0;
+
+ p_flt += QMF_NO_POLY * (p_stride - 1);
+
+ /*
+ Perform FIR-Filter
+ */
+ for (p = 0; p < QMF_NO_POLY; p++) {
+ accu += fMultDiv2(*p_flt++, pFilterStates[2 * no_channels * p]);
+ }
+ analysisBuffer[2 * no_channels - 1 - k] = (accu << 1);
+ pFilterStates++;
+ }
+}
+#endif /* FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric */
+
+/*
+ * \brief Perform one QMF slot analysis of the time domain data of timeIn
+ * with specified stride and stores the real part of the subband
+ * samples in rSubband, and the imaginary part in iSubband
+ *
+ * Note: anaQmf->lsb can be greater than anaQmf->no_channels in case
+ * of implicit resampling (USAC with reduced 3/4 core frame length).
+ */
+void qmfAnalysisFilteringSlot(
+ HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */
+ FIXP_DBL *qmfReal, /*!< Low and High band, real */
+ FIXP_DBL *qmfImag, /*!< Low and High band, imag */
+ const INT_PCM_QMFIN *RESTRICT timeIn, /*!< Pointer to input */
+ const int stride, /*!< stride factor of input */
+ FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */
+) {
+ int offset = anaQmf->no_channels * (QMF_NO_POLY * 2 - 1);
+ /*
+ Feed time signal into oldest anaQmf->no_channels states
+ */
+ {
+ FIXP_QAS *FilterStatesAnaTmp = ((FIXP_QAS *)anaQmf->FilterStates) + offset;
+
+ /* Feed and scale actual time in slot */
+ for (int i = anaQmf->no_channels >> 1; i != 0; i--) {
+ /* Place INT_PCM value left aligned in scaledTimeIn */
+ *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn;
+ timeIn += stride;
+ *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn;
+ timeIn += stride;
+ }
+ }
+
+ if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) {
+ qmfAnaPrototypeFirSlot_NonSymmetric(pWorkBuffer, anaQmf->no_channels,
+ anaQmf->p_filter, anaQmf->p_stride,
+ (FIXP_QAS *)anaQmf->FilterStates);
+ } else {
+ qmfAnaPrototypeFirSlot(pWorkBuffer, anaQmf->no_channels, anaQmf->p_filter,
+ anaQmf->p_stride, (FIXP_QAS *)anaQmf->FilterStates);
+ }
+
+ if (anaQmf->flags & QMF_FLAG_LP) {
+ if (anaQmf->flags & QMF_FLAG_CLDFB)
+ qmfForwardModulationLP_odd(anaQmf, pWorkBuffer, qmfReal);
+ else
+ qmfForwardModulationLP_even(anaQmf, pWorkBuffer, qmfReal);
+
+ } else {
+ qmfForwardModulationHQ(anaQmf, pWorkBuffer, qmfReal, qmfImag);
+ }
+ /*
+ Shift filter states
+
+ Should be realized with modulo addressing on a DSP instead of a true buffer
+ shift
+ */
+ FDKmemmove(anaQmf->FilterStates,
+ (FIXP_QAS *)anaQmf->FilterStates + anaQmf->no_channels,
+ offset * sizeof(FIXP_QAS));
+}
+
+/*!
+ *
+ * \brief Perform complex-valued subband filtering of the time domain
+ * data of timeIn and stores the real part of the subband
+ * samples in rAnalysis, and the imaginary part in iAnalysis
+ * The qmf coefficient table is symmetric. The symmetry is expoited by
+ * shrinking the coefficient table to half the size. The addressing mode
+ * takes care of the symmetries.
+ *
+ *
+ * \sa PolyphaseFiltering
+ */
+void qmfAnalysisFiltering(
+ HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */
+ FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */
+ FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */
+ QMF_SCALE_FACTOR *scaleFactor,
+ const INT_PCM_QMFIN *timeIn, /*!< Time signal */
+ const int timeIn_e, const int stride,
+ FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */
+) {
+ int i;
+ int no_channels = anaQmf->no_channels;
+
+ scaleFactor->lb_scale =
+ -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - timeIn_e;
+ scaleFactor->lb_scale -= anaQmf->filterScale;
+
+ for (i = 0; i < anaQmf->no_col; i++) {
+ FIXP_DBL *qmfImagSlot = NULL;
+
+ if (!(anaQmf->flags & QMF_FLAG_LP)) {
+ qmfImagSlot = qmfImag[i];
+ }
+
+ qmfAnalysisFilteringSlot(anaQmf, qmfReal[i], qmfImagSlot, timeIn, stride,
+ pWorkBuffer);
+
+ timeIn += no_channels * stride;
+
+ } /* no_col loop i */
+}
#endif /* QMF_PCM_H */
diff --git a/libFDK/src/FDK_core.cpp b/libFDK/src/FDK_core.cpp
index 75ea8a2..2f77179 100644
--- a/libFDK/src/FDK_core.cpp
+++ b/libFDK/src/FDK_core.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
@@ -104,7 +104,7 @@ amm-info@iis.fraunhofer.de
/* FDK tools library info */
#define FDK_TOOLS_LIB_VL0 3
-#define FDK_TOOLS_LIB_VL1 0
+#define FDK_TOOLS_LIB_VL1 1
#define FDK_TOOLS_LIB_VL2 0
#define FDK_TOOLS_LIB_TITLE "FDK Tools"
#ifdef __ANDROID__
diff --git a/libFDK/src/FDK_qmf_domain.cpp b/libFDK/src/FDK_qmf_domain.cpp
index 3245deb..77c5ca2 100644
--- a/libFDK/src/FDK_qmf_domain.cpp
+++ b/libFDK/src/FDK_qmf_domain.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
@@ -106,35 +106,31 @@ amm-info@iis.fraunhofer.de
#include "common_fix.h"
#define WORKBUFFER1_TAG 0
-#define WORKBUFFER2_TAG 1
-
#define WORKBUFFER3_TAG 4
#define WORKBUFFER4_TAG 5
-#define WORKBUFFER5_TAG 6
#define WORKBUFFER6_TAG 7
+#define WORKBUFFER7_TAG 8
C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore1, FIXP_DBL, QMF_WB_SECTION_SIZE,
SECT_DATA_L1, WORKBUFFER1_TAG)
-C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore2, FIXP_DBL, QMF_WB_SECTION_SIZE,
- SECT_DATA_L2, WORKBUFFER2_TAG)
C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore3, FIXP_DBL, QMF_WB_SECTION_SIZE,
SECT_DATA_L2, WORKBUFFER3_TAG)
C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore4, FIXP_DBL, QMF_WB_SECTION_SIZE,
SECT_DATA_L2, WORKBUFFER4_TAG)
-C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore5, FIXP_DBL, QMF_WB_SECTION_SIZE,
- SECT_DATA_L2, WORKBUFFER5_TAG)
C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore6, FIXP_DBL, QMF_WB_SECTION_SIZE,
SECT_DATA_L2, WORKBUFFER6_TAG)
+C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore7, FIXP_DBL, QMF_WB_SECTION_SIZE,
+ SECT_DATA_L2, WORKBUFFER7_TAG)
/*! Analysis states buffer. <br>
Dimension: #((8) + (1)) */
-C_ALLOC_MEM2(AnaQmfStates, FIXP_QAS, 10 * QMF_DOMAIN_MAX_ANALYSIS_QMF_BANDS,
- ((8) + (1)))
+C_AALLOC_MEM2(AnaQmfStates, FIXP_DBL, 10 * QMF_DOMAIN_MAX_ANALYSIS_QMF_BANDS,
+ ((8) + (1)))
/*! Synthesis states buffer. <br>
Dimension: #((8) + (1)) */
-C_ALLOC_MEM2(SynQmfStates, FIXP_QSS, 9 * QMF_DOMAIN_MAX_SYNTHESIS_QMF_BANDS,
- ((8) + (1)))
+C_AALLOC_MEM2(SynQmfStates, FIXP_QSS, 9 * QMF_DOMAIN_MAX_SYNTHESIS_QMF_BANDS,
+ ((8) + (1)))
/*! Pointer to real qmf data for each time slot. <br>
Dimension: #((8) + (1)) */
@@ -156,18 +152,17 @@ C_AALLOC_MEM2(QmfOverlapBuffer, FIXP_DBL,
/*! Analysis states buffer. <br>
Dimension: #((8) + (1)) */
-C_ALLOC_MEM2(AnaQmfStates16, FIXP_QAS, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_16,
- ((8) + (1)))
-
+C_AALLOC_MEM2(AnaQmfStates16, FIXP_DBL, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_16,
+ ((8) + (1)))
/*! Analysis states buffer. <br>
Dimension: #((8) + (1)) */
-C_ALLOC_MEM2(AnaQmfStates24, FIXP_QAS, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_24,
- ((8) + (1)))
+C_AALLOC_MEM2(AnaQmfStates24, FIXP_DBL, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_24,
+ ((8) + (1)))
/*! Analysis states buffer. <br>
Dimension: #((8) + (1)) */
-C_ALLOC_MEM2(AnaQmfStates32, FIXP_QAS, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_32,
- ((8) + (1)))
+C_AALLOC_MEM2(AnaQmfStates32, FIXP_DBL, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_32,
+ ((8) + (1)))
/*! Pointer to real qmf data for each time slot. <br>
Dimension: #((8) + (1)) */
@@ -642,10 +637,10 @@ void FDK_QmfDomain_GetSlot(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, const int ts,
if (pQmfOutImag == NULL) {
for (; b < fMin(lsb, stop_band); b++) {
- pQmfOutReal[b] = scaleValue(real[b], lb_sf);
+ pQmfOutReal[b] = scaleValueSaturate(real[b], lb_sf);
}
for (; b < fMin(usb, stop_band); b++) {
- pQmfOutReal[b] = scaleValue(real[b], hb_sf);
+ pQmfOutReal[b] = scaleValueSaturate(real[b], hb_sf);
}
for (; b < stop_band; b++) {
pQmfOutReal[b] = (FIXP_DBL)0;
@@ -653,12 +648,12 @@ void FDK_QmfDomain_GetSlot(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, const int ts,
} else {
FDK_ASSERT(imag != NULL);
for (; b < fMin(lsb, stop_band); b++) {
- pQmfOutReal[b] = scaleValue(real[b], lb_sf);
- pQmfOutImag[b] = scaleValue(imag[b], lb_sf);
+ pQmfOutReal[b] = scaleValueSaturate(real[b], lb_sf);
+ pQmfOutImag[b] = scaleValueSaturate(imag[b], lb_sf);
}
for (; b < fMin(usb, stop_band); b++) {
- pQmfOutReal[b] = scaleValue(real[b], hb_sf);
- pQmfOutImag[b] = scaleValue(imag[b], hb_sf);
+ pQmfOutReal[b] = scaleValueSaturate(real[b], hb_sf);
+ pQmfOutImag[b] = scaleValueSaturate(imag[b], hb_sf);
}
for (; b < stop_band; b++) {
pQmfOutReal[b] = (FIXP_DBL)0;
@@ -950,7 +945,7 @@ QMF_DOMAIN_ERROR FDK_QmfDomain_Configure(HANDLE_FDK_QMF_DOMAIN hqd) {
if ((size > 4 * QMF_WB_SECTION_SIZE) && (pWorkBuffer[4] == NULL)) {
/* get work buffer of size QMF_WB_SECTION_SIZE */
- pWorkBuffer[4] = GetQmfWorkBufferCore5();
+ pWorkBuffer[4] = GetQmfWorkBufferCore7();
}
/* 8. distribute workbuffer over processing channels */
@@ -996,7 +991,7 @@ static void FDK_QmfDomain_FreeWorkBuffer(HANDLE_FDK_QMF_DOMAIN hqd) {
if (pWorkBuffer[1]) FreeQmfWorkBufferCore1(&pWorkBuffer[1]);
if (pWorkBuffer[2]) FreeQmfWorkBufferCore3(&pWorkBuffer[2]);
if (pWorkBuffer[3]) FreeQmfWorkBufferCore4(&pWorkBuffer[3]);
- if (pWorkBuffer[4]) FreeQmfWorkBufferCore5(&pWorkBuffer[4]);
+ if (pWorkBuffer[4]) FreeQmfWorkBufferCore7(&pWorkBuffer[4]);
}
void FDK_QmfDomain_FreeMem(HANDLE_FDK_QMF_DOMAIN hqd) {
diff --git a/libFDK/src/qmf.cpp b/libFDK/src/qmf.cpp
index 19f1ea1..440bec2 100644
--- a/libFDK/src/qmf.cpp
+++ b/libFDK/src/qmf.cpp
@@ -147,88 +147,6 @@ amm-info@iis.fraunhofer.de
/* moved to qmf_pcm.h: -> qmfSynPrototypeFirSlot_NonSymmetric */
/* moved to qmf_pcm.h: -> qmfSynthesisFilteringSlot */
-#ifndef FUNCTION_qmfAnaPrototypeFirSlot
-/*!
- \brief Perform Analysis Prototype Filtering on a single slot of input data.
-*/
-static void qmfAnaPrototypeFirSlot(
- FIXP_DBL *analysisBuffer,
- INT no_channels, /*!< Number channels of analysis filter */
- const FIXP_PFT *p_filter, INT p_stride, /*!< Stride of analysis filter */
- FIXP_QAS *RESTRICT pFilterStates) {
- INT k;
-
- FIXP_DBL accu;
- const FIXP_PFT *RESTRICT p_flt = p_filter;
- FIXP_DBL *RESTRICT pData_0 = analysisBuffer + 2 * no_channels - 1;
- FIXP_DBL *RESTRICT pData_1 = analysisBuffer;
-
- FIXP_QAS *RESTRICT sta_0 = (FIXP_QAS *)pFilterStates;
- FIXP_QAS *RESTRICT sta_1 =
- (FIXP_QAS *)pFilterStates + (2 * QMF_NO_POLY * no_channels) - 1;
- INT pfltStep = QMF_NO_POLY * (p_stride);
- INT staStep1 = no_channels << 1;
- INT staStep2 = (no_channels << 3) - 1; /* Rewind one less */
-
- /* FIR filters 127..64 0..63 */
- for (k = 0; k < no_channels; k++) {
- accu = fMultDiv2(p_flt[0], *sta_1);
- sta_1 -= staStep1;
- accu += fMultDiv2(p_flt[1], *sta_1);
- sta_1 -= staStep1;
- accu += fMultDiv2(p_flt[2], *sta_1);
- sta_1 -= staStep1;
- accu += fMultDiv2(p_flt[3], *sta_1);
- sta_1 -= staStep1;
- accu += fMultDiv2(p_flt[4], *sta_1);
- *pData_1++ = (accu << 1);
- sta_1 += staStep2;
-
- p_flt += pfltStep;
- accu = fMultDiv2(p_flt[0], *sta_0);
- sta_0 += staStep1;
- accu += fMultDiv2(p_flt[1], *sta_0);
- sta_0 += staStep1;
- accu += fMultDiv2(p_flt[2], *sta_0);
- sta_0 += staStep1;
- accu += fMultDiv2(p_flt[3], *sta_0);
- sta_0 += staStep1;
- accu += fMultDiv2(p_flt[4], *sta_0);
- *pData_0-- = (accu << 1);
- sta_0 -= staStep2;
- }
-}
-#endif /* !defined(FUNCTION_qmfAnaPrototypeFirSlot) */
-
-#ifndef FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric
-/*!
- \brief Perform Analysis Prototype Filtering on a single slot of input data.
-*/
-static void qmfAnaPrototypeFirSlot_NonSymmetric(
- FIXP_DBL *analysisBuffer,
- int no_channels, /*!< Number channels of analysis filter */
- const FIXP_PFT *p_filter, int p_stride, /*!< Stride of analysis filter */
- FIXP_QAS *RESTRICT pFilterStates) {
- const FIXP_PFT *RESTRICT p_flt = p_filter;
- int p, k;
-
- for (k = 0; k < 2 * no_channels; k++) {
- FIXP_DBL accu = (FIXP_DBL)0;
-
- p_flt += QMF_NO_POLY * (p_stride - 1);
-
- /*
- Perform FIR-Filter
- */
- for (p = 0; p < QMF_NO_POLY; p++) {
- accu += fMultDiv2(*p_flt++, pFilterStates[2 * no_channels * p]);
- }
- analysisBuffer[2 * no_channels - 1 - k] = (accu << 1);
- pFilterStates++;
- }
-}
-#endif /* FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric */
-
/*!
*
* \brief Perform real-valued forward modulation of the time domain
@@ -381,211 +299,6 @@ static void qmfForwardModulationHQ(
}
#endif /* FUNCTION_qmfForwardModulationHQ */
-/*
- * \brief Perform one QMF slot analysis of the time domain data of timeIn
- * with specified stride and stores the real part of the subband
- * samples in rSubband, and the imaginary part in iSubband
- *
- * Note: anaQmf->lsb can be greater than anaQmf->no_channels in case
- * of implicit resampling (USAC with reduced 3/4 core frame length).
- */
-#if (SAMPLE_BITS != DFRACT_BITS) && (QAS_BITS == DFRACT_BITS)
-void qmfAnalysisFilteringSlot(
- HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */
- FIXP_DBL *qmfReal, /*!< Low and High band, real */
- FIXP_DBL *qmfImag, /*!< Low and High band, imag */
- const LONG *RESTRICT timeIn, /*!< Pointer to input */
- const int stride, /*!< stride factor of input */
- FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */
-) {
- int offset = anaQmf->no_channels * (QMF_NO_POLY * 2 - 1);
- /*
- Feed time signal into oldest anaQmf->no_channels states
- */
- {
- FIXP_DBL *FilterStatesAnaTmp = ((FIXP_DBL *)anaQmf->FilterStates) + offset;
-
- /* Feed and scale actual time in slot */
- for (int i = anaQmf->no_channels >> 1; i != 0; i--) {
- /* Place INT_PCM value left aligned in scaledTimeIn */
-
- *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn;
- timeIn += stride;
- *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn;
- timeIn += stride;
- }
- }
-
- if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) {
- qmfAnaPrototypeFirSlot_NonSymmetric(pWorkBuffer, anaQmf->no_channels,
- anaQmf->p_filter, anaQmf->p_stride,
- (FIXP_QAS *)anaQmf->FilterStates);
- } else {
- qmfAnaPrototypeFirSlot(pWorkBuffer, anaQmf->no_channels, anaQmf->p_filter,
- anaQmf->p_stride, (FIXP_QAS *)anaQmf->FilterStates);
- }
-
- if (anaQmf->flags & QMF_FLAG_LP) {
- if (anaQmf->flags & QMF_FLAG_CLDFB)
- qmfForwardModulationLP_odd(anaQmf, pWorkBuffer, qmfReal);
- else
- qmfForwardModulationLP_even(anaQmf, pWorkBuffer, qmfReal);
-
- } else {
- qmfForwardModulationHQ(anaQmf, pWorkBuffer, qmfReal, qmfImag);
- }
- /*
- Shift filter states
-
- Should be realized with modulo adressing on a DSP instead of a true buffer
- shift
- */
- FDKmemmove(anaQmf->FilterStates,
- (FIXP_QAS *)anaQmf->FilterStates + anaQmf->no_channels,
- offset * sizeof(FIXP_QAS));
-}
-#endif
-
-void qmfAnalysisFilteringSlot(
- HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */
- FIXP_DBL *qmfReal, /*!< Low and High band, real */
- FIXP_DBL *qmfImag, /*!< Low and High band, imag */
- const INT_PCM *RESTRICT timeIn, /*!< Pointer to input */
- const int stride, /*!< stride factor of input */
- FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */
-) {
- int offset = anaQmf->no_channels * (QMF_NO_POLY * 2 - 1);
- /*
- Feed time signal into oldest anaQmf->no_channels states
- */
- {
- FIXP_QAS *FilterStatesAnaTmp = ((FIXP_QAS *)anaQmf->FilterStates) + offset;
-
- /* Feed and scale actual time in slot */
- for (int i = anaQmf->no_channels >> 1; i != 0; i--) {
- /* Place INT_PCM value left aligned in scaledTimeIn */
-#if (QAS_BITS == SAMPLE_BITS)
- *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn;
- timeIn += stride;
- *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn;
- timeIn += stride;
-#elif (QAS_BITS > SAMPLE_BITS)
- *FilterStatesAnaTmp++ = ((FIXP_QAS)*timeIn) << (QAS_BITS - SAMPLE_BITS);
- timeIn += stride;
- *FilterStatesAnaTmp++ = ((FIXP_QAS)*timeIn) << (QAS_BITS - SAMPLE_BITS);
- timeIn += stride;
-#else
- *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn) >> (SAMPLE_BITS - QAS_BITS));
- timeIn += stride;
- *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn) >> (SAMPLE_BITS - QAS_BITS));
- timeIn += stride;
-#endif
- }
- }
-
- if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) {
- qmfAnaPrototypeFirSlot_NonSymmetric(pWorkBuffer, anaQmf->no_channels,
- anaQmf->p_filter, anaQmf->p_stride,
- (FIXP_QAS *)anaQmf->FilterStates);
- } else {
- qmfAnaPrototypeFirSlot(pWorkBuffer, anaQmf->no_channels, anaQmf->p_filter,
- anaQmf->p_stride, (FIXP_QAS *)anaQmf->FilterStates);
- }
-
- if (anaQmf->flags & QMF_FLAG_LP) {
- if (anaQmf->flags & QMF_FLAG_CLDFB)
- qmfForwardModulationLP_odd(anaQmf, pWorkBuffer, qmfReal);
- else
- qmfForwardModulationLP_even(anaQmf, pWorkBuffer, qmfReal);
-
- } else {
- qmfForwardModulationHQ(anaQmf, pWorkBuffer, qmfReal, qmfImag);
- }
- /*
- Shift filter states
-
- Should be realized with modulo adressing on a DSP instead of a true buffer
- shift
- */
- FDKmemmove(anaQmf->FilterStates,
- (FIXP_QAS *)anaQmf->FilterStates + anaQmf->no_channels,
- offset * sizeof(FIXP_QAS));
-}
-
-/*!
- *
- * \brief Perform complex-valued subband filtering of the time domain
- * data of timeIn and stores the real part of the subband
- * samples in rAnalysis, and the imaginary part in iAnalysis
- * The qmf coefficient table is symmetric. The symmetry is expoited by
- * shrinking the coefficient table to half the size. The addressing mode
- * takes care of the symmetries.
- *
- *
- * \sa PolyphaseFiltering
- */
-#if (SAMPLE_BITS != DFRACT_BITS) && (QAS_BITS == DFRACT_BITS)
-void qmfAnalysisFiltering(
- HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */
- FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */
- FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */
- QMF_SCALE_FACTOR *scaleFactor, const LONG *timeIn, /*!< Time signal */
- const int timeIn_e, const int stride,
- FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */
-) {
- int i;
- int no_channels = anaQmf->no_channels;
-
- scaleFactor->lb_scale =
- -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - timeIn_e;
- scaleFactor->lb_scale -= anaQmf->filterScale;
-
- for (i = 0; i < anaQmf->no_col; i++) {
- FIXP_DBL *qmfImagSlot = NULL;
-
- if (!(anaQmf->flags & QMF_FLAG_LP)) {
- qmfImagSlot = qmfImag[i];
- }
-
- qmfAnalysisFilteringSlot(anaQmf, qmfReal[i], qmfImagSlot, timeIn, stride,
- pWorkBuffer);
-
- timeIn += no_channels * stride;
-
- } /* no_col loop i */
-}
-#endif
-
-void qmfAnalysisFiltering(
- HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */
- FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */
- FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */
- QMF_SCALE_FACTOR *scaleFactor, const INT_PCM *timeIn, /*!< Time signal */
- const int timeIn_e, const int stride,
- FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */
-) {
- int i;
- int no_channels = anaQmf->no_channels;
-
- scaleFactor->lb_scale =
- -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - timeIn_e;
- scaleFactor->lb_scale -= anaQmf->filterScale;
-
- for (i = 0; i < anaQmf->no_col; i++) {
- FIXP_DBL *qmfImagSlot = NULL;
-
- if (!(anaQmf->flags & QMF_FLAG_LP)) {
- qmfImagSlot = qmfImag[i];
- }
-
- qmfAnalysisFilteringSlot(anaQmf, qmfReal[i], qmfImagSlot, timeIn, stride,
- pWorkBuffer);
-
- timeIn += no_channels * stride;
-
- } /* no_col loop i */
-}
-
/*!
*
* \brief Perform low power inverse modulation of the subband
@@ -1005,35 +718,6 @@ static inline void qmfAdaptFilterStates(
* \return 0 if succesful
*
*/
-int qmfInitAnalysisFilterBank(
- HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */
- FIXP_QAS *pFilterStates, /*!< Handle to filter states */
- int noCols, /*!< Number of timeslots per frame */
- int lsb, /*!< lower end of QMF */
- int usb, /*!< upper end of QMF */
- int no_channels, /*!< Number of channels (bands) */
- int flags) /*!< Low Power flag */
-{
- int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb,
- no_channels, flags, 0);
- if (!(flags & QMF_FLAG_KEEP_STATES) && (h_Qmf->FilterStates != NULL)) {
- FDKmemclear(h_Qmf->FilterStates,
- (2 * QMF_NO_POLY - 1) * h_Qmf->no_channels * sizeof(FIXP_QAS));
- }
-
- FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->lsb);
-
- return err;
-}
-
-/*!
- *
- * \brief Create QMF filter bank instance
- *
- *
- * \return 0 if succesful
- *
- */
int qmfInitSynthesisFilterBank(
HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */
FIXP_QSS *pFilterStates, /*!< Handle to filter states */
@@ -1129,8 +813,21 @@ void qmfChangeOutGain(
synQmf->outGain_e = outputGainScale;
}
-/* When QMF_16IN_32OUT is set, synthesis functions for 16 and 32 bit parallel
- * output is compiled */
#define INT_PCM_QMFOUT INT_PCM
#define SAMPLE_BITS_QMFOUT SAMPLE_BITS
#include "qmf_pcm.h"
+#if SAMPLE_BITS == 16
+ /* also create a 32 bit output version */
+#undef INT_PCM_QMFOUT
+#undef SAMPLE_BITS_QMFOUT
+#undef QMF_PCM_H
+#undef FIXP_QAS
+#undef QAS_BITS
+#undef INT_PCM_QMFIN
+#define INT_PCM_QMFOUT LONG
+#define SAMPLE_BITS_QMFOUT 32
+#define FIXP_QAS FIXP_DBL
+#define QAS_BITS 32
+#define INT_PCM_QMFIN LONG
+#include "qmf_pcm.h"
+#endif
diff --git a/libPCMutils/include/limiter.h b/libPCMutils/include/limiter.h
index fab7226..419e891 100644
--- a/libPCMutils/include/limiter.h
+++ b/libPCMutils/include/limiter.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,8 +109,6 @@ amm-info@iis.fraunhofer.de
#define TDL_ATTACK_DEFAULT_MS (15) /* default attack time in ms */
#define TDL_RELEASE_DEFAULT_MS (50) /* default release time in ms */
-#define TDL_GAIN_SCALING (15) /* scaling of gain value. */
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -128,10 +126,7 @@ struct TDLimiter {
unsigned int maxBufIdx, delayBufIdx;
FIXP_DBL smoothState0;
FIXP_DBL minGain;
-
- FIXP_DBL additionalGainPrev;
- FIXP_DBL additionalGainFilterState;
- FIXP_DBL additionalGainFilterState1;
+ INT scaling;
};
typedef enum {
@@ -255,27 +250,16 @@ TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter,
/******************************************************************************
* pcmLimiter_Apply *
- * limiter: limiter handle *
- * pGain : pointer to gains to be applied to the signal before limiting, *
- * which are downscaled by TDL_GAIN_SCALING bit. *
- * These gains are delayed by gain_delay, and smoothed. *
- * Smoothing is done by a butterworth lowpass filter with a cutoff *
- * frequency which is fixed with respect to the sampling rate. *
- * It is a substitute for the smoothing due to windowing and *
- * overlap/add, if a gain is applied in frequency domain. *
- * gain_scale: pointer to scaling exponents to be applied to the signal before *
- * limiting, without delay and without smoothing *
- * gain_size: number of elements in pGain, currently restricted to 1 *
- * gain_delay: delay [samples] with which the gains in pGain shall be applied *
- * gain_delay <= nSamples *
- * samples: input/output buffer containing interleaved samples *
- * precision of output will be DFRACT_BITS-TDL_GAIN_SCALING bits *
- * nSamples: number of samples per channel *
+ * limiter: limiter handle *
+ * samplesIn: pointer to input buffer containing interleaved samples *
+ * samplesOut: pointer to output buffer containing interleaved samples *
+ * pGainPerSample: pointer to gains for each sample *
+ * scaling: scaling of output samples *
+ * nSamples: number of samples per channel *
* returns: error code *
******************************************************************************/
TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
- INT_PCM* samplesOut, FIXP_DBL* pGain,
- const INT* gain_scale, const UINT gain_size,
- const UINT gain_delay, const UINT nSamples);
+ INT_PCM* samplesOut, FIXP_DBL* pGainPerSample,
+ const INT scaling, const UINT nSamples);
#endif /* #ifndef LIMITER_H */
diff --git a/libPCMutils/src/limiter.cpp b/libPCMutils/src/limiter.cpp
index 60e3e3b..598dc0c 100644
--- a/libPCMutils/src/limiter.cpp
+++ b/libPCMutils/src/limiter.cpp
@@ -152,7 +152,7 @@ TDLimiterPtr pcmLimiter_Create(unsigned int maxAttackMs, unsigned int releaseMs,
limiter->attack = attack;
limiter->attackConst = attackConst;
limiter->releaseConst = releaseConst;
- limiter->threshold = threshold >> TDL_GAIN_SCALING;
+ limiter->threshold = threshold;
limiter->channels = maxChannels;
limiter->maxChannels = maxChannels;
limiter->sampleRate = maxSampleRate;
@@ -165,18 +165,13 @@ TDLimiterPtr pcmLimiter_Create(unsigned int maxAttackMs, unsigned int releaseMs,
/* apply limiter */
TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
- INT_PCM* samplesOut, FIXP_DBL* RESTRICT pGain,
- const INT* RESTRICT gain_scale,
- const UINT gain_size, const UINT gain_delay,
- const UINT nSamples) {
+ INT_PCM* samplesOut, FIXP_DBL* pGainPerSample,
+ const INT scaling, const UINT nSamples) {
unsigned int i, j;
- FIXP_DBL tmp1;
FIXP_DBL tmp2;
- FIXP_DBL tmp, old, gain, additionalGain = 0, additionalGainUnfiltered;
+ FIXP_DBL tmp, old, gain, additionalGain = 0;
FIXP_DBL minGain = FL2FXCONST_DBL(1.0f / (1 << 1));
-
- FDK_ASSERT(gain_size == 1);
- FDK_ASSERT(gain_delay <= nSamples);
+ UINT additionalGainAvailable = 1;
if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
@@ -185,7 +180,7 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
unsigned int attack = limiter->attack;
FIXP_DBL attackConst = limiter->attackConst;
FIXP_DBL releaseConst = limiter->releaseConst;
- FIXP_DBL threshold = limiter->threshold;
+ FIXP_DBL threshold = limiter->threshold >> scaling;
FIXP_DBL max = limiter->max;
FIXP_DBL* maxBuf = limiter->maxBuf;
@@ -195,55 +190,34 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
unsigned int delayBufIdx = limiter->delayBufIdx;
FIXP_DBL smoothState0 = limiter->smoothState0;
- FIXP_DBL additionalGainSmoothState = limiter->additionalGainFilterState;
- FIXP_DBL additionalGainSmoothState1 = limiter->additionalGainFilterState1;
- if (!gain_delay) {
- additionalGain = pGain[0];
- if (gain_scale[0] > 0) {
- additionalGain <<= gain_scale[0];
- } else {
- additionalGain >>= -gain_scale[0];
- }
+ if (limiter->scaling != scaling) {
+ scaleValuesSaturate(delayBuf, attack * channels,
+ limiter->scaling - scaling);
+ scaleValuesSaturate(maxBuf, attack + 1, limiter->scaling - scaling);
+ max = scaleValueSaturate(max, limiter->scaling - scaling);
+ limiter->scaling = scaling;
}
- for (i = 0; i < nSamples; i++) {
- if (gain_delay) {
- if (i < gain_delay) {
- additionalGainUnfiltered = limiter->additionalGainPrev;
- } else {
- additionalGainUnfiltered = pGain[0];
- }
+ if (pGainPerSample == NULL) {
+ additionalGainAvailable = 0;
+ }
- /* Smooth additionalGain */
- /* [b,a] = butter(1, 0.01) */
- static const FIXP_SGL b[] = {FL2FXCONST_SGL(0.015466 * 2.0),
- FL2FXCONST_SGL(0.015466 * 2.0)};
- static const FIXP_SGL a[] = {(FIXP_SGL)MAXVAL_SGL,
- FL2FXCONST_SGL(-0.96907)};
- additionalGain = -fMult(additionalGainSmoothState, a[1]) +
- fMultDiv2(additionalGainUnfiltered, b[0]) +
- fMultDiv2(additionalGainSmoothState1, b[1]);
- additionalGainSmoothState1 = additionalGainUnfiltered;
- additionalGainSmoothState = additionalGain;
-
- /* Apply the additional scaling that has no delay and no smoothing */
- if (gain_scale[0] > 0) {
- additionalGain <<= gain_scale[0];
- } else {
- additionalGain >>= -gain_scale[0];
- }
- }
+ for (i = 0; i < nSamples; i++) {
/* get maximum absolute sample value of all channels, including the
* additional gain. */
- tmp1 = (FIXP_DBL)0;
+ tmp = (FIXP_DBL)0;
for (j = 0; j < channels; j++) {
tmp2 = PCM_LIM2FIXP_DBL(samplesIn[j]);
tmp2 =
(tmp2 == (FIXP_DBL)MINVAL_DBL) ? (FIXP_DBL)MAXVAL_DBL : fAbs(tmp2);
- tmp1 = fMax(tmp1, tmp2);
+ tmp = fMax(tmp, tmp2);
+ }
+
+ if (additionalGainAvailable) {
+ additionalGain = pGainPerSample[i];
+ tmp = fMult(tmp, additionalGain);
}
- tmp = fMult(tmp1, additionalGain);
/* set threshold as lower border to save calculations in running maximum
* algorithm */
@@ -314,22 +288,42 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
/* lookahead delay, apply gain */
for (j = 0; j < channels; j++) {
tmp = p_delayBuf[j];
- p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain);
+
+ if (additionalGainAvailable) {
+ p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain);
+ } else {
+ p_delayBuf[j] = PCM_LIM2FIXP_DBL(samplesIn[j]);
+ }
/* Apply gain to delayed signal */
tmp = fMultDiv2(tmp, gain);
-
+#if (SAMPLE_BITS == DFRACT_BITS)
+ samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM(
+ (FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling + 1, DFRACT_BITS));
+#else
samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT(
- tmp, TDL_GAIN_SCALING + 1, DFRACT_BITS));
+ tmp + ((FIXP_DBL)0x8000 >> (scaling + 1)), scaling + 1,
+ DFRACT_BITS));
+#endif
}
gain >>= 1;
} else {
/* lookahead delay, apply gain=1.0f */
for (j = 0; j < channels; j++) {
tmp = p_delayBuf[j];
- p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain);
+ if (additionalGainAvailable) {
+ p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain);
+ } else {
+ p_delayBuf[j] = PCM_LIM2FIXP_DBL(samplesIn[j]);
+ }
+
+#if (SAMPLE_BITS == DFRACT_BITS)
+ samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM(
+ (FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling, DFRACT_BITS));
+#else
samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT(
- tmp, TDL_GAIN_SCALING, DFRACT_BITS));
+ tmp + ((FIXP_DBL)0x8000 >> scaling), scaling, DFRACT_BITS));
+#endif
}
}
@@ -354,13 +348,9 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
limiter->delayBufIdx = delayBufIdx;
limiter->smoothState0 = smoothState0;
- limiter->additionalGainFilterState = additionalGainSmoothState;
- limiter->additionalGainFilterState1 = additionalGainSmoothState1;
limiter->minGain = minGain;
- limiter->additionalGainPrev = pGain[0];
-
return TDLIMIT_OK;
}
}
@@ -370,7 +360,7 @@ TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter,
FIXP_DBL threshold) {
if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
- limiter->threshold = threshold >> TDL_GAIN_SCALING;
+ limiter->threshold = threshold;
return TDLIMIT_OK;
}
@@ -384,13 +374,7 @@ TDLIMITER_ERROR pcmLimiter_Reset(TDLimiterPtr limiter) {
limiter->cor = FL2FXCONST_DBL(1.0f / (1 << 1));
limiter->smoothState0 = FL2FXCONST_DBL(1.0f / (1 << 1));
limiter->minGain = FL2FXCONST_DBL(1.0f / (1 << 1));
-
- limiter->additionalGainPrev =
- FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING));
- limiter->additionalGainFilterState =
- FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING));
- limiter->additionalGainFilterState1 =
- FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING));
+ limiter->scaling = 0;
FDKmemset(limiter->maxBuf, 0, (limiter->attack + 1) * sizeof(FIXP_DBL));
FDKmemset(limiter->delayBuf, 0,
diff --git a/libPCMutils/src/version.h b/libPCMutils/src/version.h
index fa31af1..05371f8 100644
--- a/libPCMutils/src/version.h
+++ b/libPCMutils/src/version.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
@@ -105,7 +105,7 @@ amm-info@iis.fraunhofer.de
/* library info */
#define PCMUTIL_LIB_VL0 3
-#define PCMUTIL_LIB_VL1 0
+#define PCMUTIL_LIB_VL1 1
#define PCMUTIL_LIB_VL2 0
#define PCMUTIL_LIB_TITLE "PCM Utility Lib"
#ifdef __ANDROID__
diff --git a/libSACdec/include/sac_dec_lib.h b/libSACdec/include/sac_dec_lib.h
index 9913279..1827504 100644
--- a/libSACdec/include/sac_dec_lib.h
+++ b/libSACdec/include/sac_dec_lib.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
@@ -252,7 +252,7 @@ typedef enum {
scenario. Default parameter value is 3 frames. */
} SACDEC_PARAM;
-#define PCM_MPS INT_PCM
+#define PCM_MPS LONG
/**
* \brief MPEG Surround decoder handle.
@@ -401,17 +401,22 @@ int mpegSurroundDecoder_Parse(CMpegSurroundDecoder *pMpegSurroundDecoder,
* for each output audio channel is stored into.
* \param mapDescr Channep map descriptor for output channel mapping
* to be used (From MPEG PCE ordering to whatever is required).
+ * \param inDataHeadroom Headroom of SAC input time signal to prevent
+ * clipping.
+ * \param outDataHeadroom Pointer to headroom of SAC output time signal to
+ * prevent clipping.
*
* \return Error code.
*/
int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder,
- INT_PCM *input, PCM_MPS *pTimeData,
+ PCM_MPS *input, PCM_MPS *pTimeData,
const int timeDataSize, int timeDataFrameSize,
int *nChannels, int *frameSize, int sampleRate,
AUDIO_OBJECT_TYPE coreCodec,
AUDIO_CHANNEL_TYPE channelType[],
UCHAR channelIndices[],
- const FDK_channelMapDescr *const mapDescr);
+ const FDK_channelMapDescr *const mapDescr,
+ const INT inDataHeadroom, INT *outDataHeadroom);
/**
* \brief Deallocate a MPEG Surround decoder instance.
diff --git a/libSACdec/src/sac_dec.cpp b/libSACdec/src/sac_dec.cpp
index c1832f1..a7b50df 100644
--- a/libSACdec/src/sac_dec.cpp
+++ b/libSACdec/src/sac_dec.cpp
@@ -766,7 +766,7 @@ SACDEC_ERROR FDK_SpatialDecInit(spatialDec *self, SPATIAL_BS_FRAME *frame,
/* output scaling */
for (nCh = 0; nCh < self->numOutputChannelsAT; nCh++) {
- int outputScale = 0, outputGain_e = 0, scale = 0;
+ int outputScale = 0, outputGain_e = 0, scale = -(8) + (1);
FIXP_DBL outputGain_m = getChGain(self, nCh, &outputGain_e);
if (!isTwoChMode(self->upmixType) && !bypassMode) {
@@ -775,7 +775,7 @@ SACDEC_ERROR FDK_SpatialDecInit(spatialDec *self, SPATIAL_BS_FRAME *frame,
synthesis qmf */
}
- scale = outputScale;
+ scale += outputScale;
qmfChangeOutScalefactor(&self->pQmfDomain->QmfDomainOut[nCh].fb, scale);
qmfChangeOutGain(&self->pQmfDomain->QmfDomainOut[nCh].fb, outputGain_m,
@@ -1223,18 +1223,24 @@ static SACDEC_ERROR SpatialDecApplyParameterSets(
!(self->stereoConfigIndex == 3)) {
for (i = 0; i < self->qmfBands; i++) {
self_qmfResidualReal__FDK_0_0[i] =
- fMult(self_qmfResidualReal__FDK_0_0[i] << 1,
+ fMult(scaleValueSaturate(self_qmfResidualReal__FDK_0_0[i],
+ 1 + self->sacInDataHeadroom - (1)),
self->clipProtectGain__FDK);
self_qmfResidualImag__FDK_0_0[i] =
- fMult(self_qmfResidualImag__FDK_0_0[i] << 1,
+ fMult(scaleValueSaturate(self_qmfResidualImag__FDK_0_0[i],
+ 1 + self->sacInDataHeadroom - (1)),
self->clipProtectGain__FDK);
}
} else {
for (i = 0; i < self->qmfBands; i++) {
- self_qmfResidualReal__FDK_0_0[i] = fMult(
- self_qmfResidualReal__FDK_0_0[i], self->clipProtectGain__FDK);
- self_qmfResidualImag__FDK_0_0[i] = fMult(
- self_qmfResidualImag__FDK_0_0[i], self->clipProtectGain__FDK);
+ self_qmfResidualReal__FDK_0_0[i] =
+ fMult(scaleValueSaturate(self_qmfResidualReal__FDK_0_0[i],
+ self->sacInDataHeadroom - (1)),
+ self->clipProtectGain__FDK);
+ self_qmfResidualImag__FDK_0_0[i] =
+ fMult(scaleValueSaturate(self_qmfResidualImag__FDK_0_0[i],
+ self->sacInDataHeadroom - (1)),
+ self->clipProtectGain__FDK);
}
}
}
@@ -1416,6 +1422,7 @@ SACDEC_ERROR SpatialDecApplyFrame(
FDK_ASSERT(self != NULL);
FDK_ASSERT(pControlFlags != NULL);
FDK_ASSERT(pcmOutBuf != NULL);
+ FDK_ASSERT(self->sacInDataHeadroom >= (1));
self->errInt = err; /* Init internal error */
diff --git a/libSACdec/src/sac_dec.h b/libSACdec/src/sac_dec.h
index 992acad..1c3df71 100644
--- a/libSACdec/src/sac_dec.h
+++ b/libSACdec/src/sac_dec.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
@@ -523,6 +523,9 @@ struct spatialDec_struct {
new frame after SSC change (aka
decodeAfterConfigHasChangedFlag). */
SpatialDecConcealmentInfo concealInfo;
+
+ INT sacInDataHeadroom; /* Headroom of the SAC input time signal to prevent
+ clipping */
};
#define SACDEC_SYNTAX_MPS 1
diff --git a/libSACdec/src/sac_dec_interface.h b/libSACdec/src/sac_dec_interface.h
index a2eea92..05a9a75 100644
--- a/libSACdec/src/sac_dec_interface.h
+++ b/libSACdec/src/sac_dec_interface.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
@@ -249,10 +249,10 @@ typedef struct {
} MEM_REQUIREMENTS;
-#define PCM_MPS INT_PCM
-#define PCM_MPSF FIXP_PCM
+#define PCM_MPS LONG
+#define PCM_MPSF FIXP_DBL
-#define FIXP_DBL2PCM_MPS(x) ((INT_PCM)FX_DBL2FX_PCM(x))
+#define FIXP_DBL2PCM_MPS(x) ((LONG)(x))
/* exposed functions (library interface) */
diff --git a/libSACdec/src/sac_dec_lib.cpp b/libSACdec/src/sac_dec_lib.cpp
index bf6dedf..856a923 100644
--- a/libSACdec/src/sac_dec_lib.cpp
+++ b/libSACdec/src/sac_dec_lib.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
@@ -1507,15 +1507,17 @@ bail:
}
int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder,
- INT_PCM *input, PCM_MPS *pTimeData,
+ PCM_MPS *input, PCM_MPS *pTimeData,
const int timeDataSize, int timeDataFrameSize,
int *nChannels, int *frameSize, int sampleRate,
AUDIO_OBJECT_TYPE coreCodec,
AUDIO_CHANNEL_TYPE channelType[],
UCHAR channelIndices[],
- const FDK_channelMapDescr *const mapDescr) {
+ const FDK_channelMapDescr *const mapDescr,
+ const INT inDataHeadroom, INT *outDataHeadroom) {
SACDEC_ERROR err = MPS_OK;
PCM_MPS *pTimeOut = pTimeData;
+ PCM_MPS *TDinput = NULL;
UINT initControlFlags = 0, controlFlags = 0;
int timeDataRequiredSize = 0;
int newData;
@@ -1534,6 +1536,9 @@ int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder,
return MPS_NOTOK;
}
+ pMpegSurroundDecoder->pSpatialDec->sacInDataHeadroom = inDataHeadroom;
+ *outDataHeadroom = (INT)(8);
+
pMpegSurroundDecoder->pSpatialDec->pConfigCurrent =
&pMpegSurroundDecoder
->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode];
@@ -1682,8 +1687,7 @@ int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder,
(timeDataFrameSize *
pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsSynthesis) /
pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis;
- pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput =
- pTimeData + timeDataFrameSizeOut - timeDataFrameSize;
+ TDinput = pTimeData + timeDataFrameSizeOut - timeDataFrameSize;
for (int i = *nChannels - 1; i >= 0; i--) {
FDKmemmove(pTimeData + (i + 1) * timeDataFrameSizeOut - timeDataFrameSize,
pTimeData + timeDataFrameSize * i,
@@ -1694,8 +1698,8 @@ int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder,
} else {
if (pMpegSurroundDecoder->mpegSurroundUseTimeInterface) {
FDKmemcpy(input, pTimeData,
- sizeof(INT_PCM) * (*nChannels) * (*frameSize));
- pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput = input;
+ sizeof(PCM_MPS) * (*nChannels) * (*frameSize));
+ TDinput = input;
}
}
@@ -1707,8 +1711,8 @@ int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder,
&pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode],
pMpegSurroundDecoder->mpegSurroundUseTimeInterface ? INPUTMODE_TIME
: INPUTMODE_QMF_SBR,
- pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput, NULL, NULL,
- pTimeOut, *frameSize, &controlFlags, *nChannels, mapDescr);
+ TDinput, NULL, NULL, pTimeOut, *frameSize, &controlFlags, *nChannels,
+ mapDescr);
*nChannels = pMpegSurroundDecoder->pSpatialDec->numOutputChannelsAT;
if (err !=
@@ -1781,7 +1785,7 @@ void mpegSurroundDecoder_Close(CMpegSurroundDecoder *pMpegSurroundDecoder) {
}
#define SACDEC_VL0 2
-#define SACDEC_VL1 0
+#define SACDEC_VL1 1
#define SACDEC_VL2 0
int mpegSurroundDecoder_GetLibInfo(LIB_INFO *info) {
diff --git a/libSACdec/src/sac_process.cpp b/libSACdec/src/sac_process.cpp
index 95128f3..22091a9 100644
--- a/libSACdec/src/sac_process.cpp
+++ b/libSACdec/src/sac_process.cpp
@@ -187,8 +187,12 @@ SACDEC_ERROR SpatialDecQMFAnalysis(spatialDec *self, const PCM_MPS *inData,
if (!isTwoChMode(self->upmixType) && !bypassMode) {
int i;
for (i = 0; i < self->qmfBands; i++) {
- qmfReal[ch][i] = fMult(qmfReal[ch][i], self->clipProtectGain__FDK);
- qmfImag[ch][i] = fMult(qmfImag[ch][i], self->clipProtectGain__FDK);
+ qmfReal[ch][i] = fMult(
+ scaleValueSaturate(qmfReal[ch][i], self->sacInDataHeadroom - (1)),
+ self->clipProtectGain__FDK);
+ qmfImag[ch][i] = fMult(
+ scaleValueSaturate(qmfImag[ch][i], self->sacInDataHeadroom - (1)),
+ self->clipProtectGain__FDK);
}
}
}
@@ -216,16 +220,17 @@ SACDEC_ERROR SpatialDecFeedQMF(spatialDec *self, FIXP_DBL **qmfInDataReal,
/* Write Input data to pQmfRealAnalysis. */
if (self->bShareDelayWithSBR) {
- FDK_QmfDomain_GetSlot(
- &self->pQmfDomain->QmfDomainIn[ch], ts + HYBRID_FILTER_DELAY, 0,
- MAX_QMF_BANDS_TO_HYBRID, pQmfRealAnalysis, pQmfImagAnalysis, 15);
+ FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch],
+ ts + HYBRID_FILTER_DELAY, 0,
+ MAX_QMF_BANDS_TO_HYBRID, pQmfRealAnalysis,
+ pQmfImagAnalysis, 15 + (1));
FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts,
MAX_QMF_BANDS_TO_HYBRID, self->qmfBands,
- pQmfRealAnalysis, pQmfImagAnalysis, 15);
+ pQmfRealAnalysis, pQmfImagAnalysis, 15 + (1));
} else {
FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, 0,
self->qmfBands, pQmfRealAnalysis,
- pQmfImagAnalysis, 15);
+ pQmfImagAnalysis, 15 + (1));
}
if (ts == self->pQmfDomain->globalConf.nQmfTimeSlots - 1) {
/* Is currently also needed in case we dont have any overlap. We need to
@@ -501,8 +506,8 @@ SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding(
for (pb = 0, qs = 3; pb < 2; pb++) {
INT s;
FIXP_DBL maxVal;
- FIXP_SGL mReal1;
- FIXP_SGL mReal0, mImag0;
+ FIXP_DBL mReal1;
+ FIXP_DBL mReal0, mImag0;
FIXP_DBL iReal0, iImag0, iReal1;
iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]);
@@ -515,9 +520,9 @@ SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding(
s = fMax(CntLeadingZeros(maxVal) - 1, 0);
s = fMin(s, scale_param_m2);
- mReal0 = FX_DBL2FX_SGL(iReal0 << s);
- mImag0 = FX_DBL2FX_SGL(iImag0 << s);
- mReal1 = FX_DBL2FX_SGL(iReal1 << s);
+ mReal0 = iReal0 << s;
+ mImag0 = iImag0 << s;
+ mReal1 = iReal1 << s;
s = scale_param_m2 - s;
@@ -934,6 +939,7 @@ SACDEC_ERROR SpatialDecSynthesis(spatialDec *self, const INT ts,
self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -=
self->clipProtectGainSF__FDK;
+ self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= (1);
} else {
/* Call the QMF synthesis for dry. */
err = CalculateSpaceSynthesisQmf(&self->pQmfDomain->QmfDomainOut[outCh],
diff --git a/libSACdec/src/sac_qmf.cpp b/libSACdec/src/sac_qmf.cpp
index a075490..fd7599d 100644
--- a/libSACdec/src/sac_qmf.cpp
+++ b/libSACdec/src/sac_qmf.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
@@ -110,7 +110,7 @@ amm-info@iis.fraunhofer.de
SACDEC_ERROR CalculateSpaceSynthesisQmf(
const HANDLE_FDK_QMF_DOMAIN_OUT hQmfDomainOutCh, const FIXP_DBL *Sr,
- const FIXP_DBL *Si, const INT stride, INT_PCM *timeSig) {
+ const FIXP_DBL *Si, const INT stride, PCM_MPS *timeSig) {
SACDEC_ERROR err = MPS_OK;
if (hQmfDomainOutCh == NULL) {
diff --git a/libSACdec/src/sac_qmf.h b/libSACdec/src/sac_qmf.h
index d1dc837..5cd573e 100644
--- a/libSACdec/src/sac_qmf.h
+++ b/libSACdec/src/sac_qmf.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
@@ -124,7 +124,7 @@ amm-info@iis.fraunhofer.de
*/
SACDEC_ERROR CalculateSpaceSynthesisQmf(
const HANDLE_FDK_QMF_DOMAIN_OUT hQmfDomainOutCh, const FIXP_DBL *Sr,
- const FIXP_DBL *Si, const INT stride, INT_PCM *timeSig);
+ const FIXP_DBL *Si, const INT stride, PCM_MPS *timeSig);
/**
* \brief Convert audio input data to qmf representation.
diff --git a/libSACdec/src/sac_reshapeBBEnv.cpp b/libSACdec/src/sac_reshapeBBEnv.cpp
index b44ce4e..272d009 100644
--- a/libSACdec/src/sac_reshapeBBEnv.cpp
+++ b/libSACdec/src/sac_reshapeBBEnv.cpp
@@ -253,17 +253,17 @@ static inline void slotAmp(FIXP_DBL *RESTRICT slotAmp_dry,
dry = wet = FL2FXCONST_DBL(0.0f);
for (qs = 0; qs < cplxBands; qs++) {
- dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs]) +
- fPow2Div2(pHybOutputImagDry[qs]));
- wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs]) +
- fPow2Div2(pHybOutputImagWet[qs]));
+ dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs] << (1)) +
+ fPow2Div2(pHybOutputImagDry[qs] << (1)));
+ wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs] << (1)) +
+ fPow2Div2(pHybOutputImagWet[qs] << (1)));
}
for (; qs < hybBands; qs++) {
- dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs]));
- wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs]));
+ dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs] << (1)));
+ wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs] << (1)));
}
- *slotAmp_dry = dry;
- *slotAmp_wet = wet;
+ *slotAmp_dry = dry >> (2 * (1));
+ *slotAmp_wet = wet >> (2 * (1));
}
#if defined(__aarch64__)
@@ -327,7 +327,7 @@ static void extractBBEnv(spatialDec *self, INT inp, INT start, INT channels,
INT shapeActiv = 1;
INT hybBands = fixMin(42, self->hybridBands);
- INT staticScale = self->staticDecScale;
+ INT staticScale = self->staticDecScale + (1);
INT cplxBands;
cplxBands = fixMin(42, self->hybridBands);
diff --git a/libSACdec/src/sac_rom.h b/libSACdec/src/sac_rom.h
index 38f17f2..d317856 100644
--- a/libSACdec/src/sac_rom.h
+++ b/libSACdec/src/sac_rom.h
@@ -111,21 +111,12 @@ amm-info@iis.fraunhofer.de
#include "machine_type.h"
/* Global ROM table data type: */
-#ifndef ARCH_PREFER_MULT_32x32
-#define FIXP_CFG FIXP_SGL
-#define FX_CFG2FX_DBL FX_SGL2FX_DBL
-#define FX_CFG2FX_SGL
-#define CFG(a) (FX_DBL2FXCONST_SGL(a))
-#define FL2FXCONST_CFG FL2FXCONST_SGL
-#define FX_DBL2FX_CFG(x) FX_DBL2FX_SGL((FIXP_DBL)(x))
-#else
#define FIXP_CFG FIXP_DBL
#define FX_CFG2FX_DBL
#define FX_CFG2FX_SGL FX_DBL2FX_SGL
#define CFG(a) FIXP_DBL(a)
#define FL2FXCONST_CFG FL2FXCONST_DBL
#define FX_DBL2FX_CFG(x) ((FIXP_DBL)(x))
-#endif
/* others */
#define SCALE_INV_ICC (2)
@@ -133,15 +124,9 @@ amm-info@iis.fraunhofer.de
#define QCC_SCALE 1
#define M1M2_DATA FIXP_DBL
-#ifndef ARCH_PREFER_MULT_32x32
-#define M1M2_CDATA FIXP_SGL
-#define M1M2_CDATA2FX_DBL(a) FX_SGL2FX_DBL(a)
-#define FX_DBL2M1M2_CDATA(a) FX_DBL2FX_SGL(a)
-#else
#define M1M2_CDATA FIXP_DBL
#define M1M2_CDATA2FX_DBL(a) (a)
#define FX_DBL2M1M2_CDATA(a) (a)
-#endif
#define CLIP_PROTECT_GAIN_0(x) FL2FXCONST_CFG(((x) / (float)(1 << 0)))
#define CLIP_PROTECT_GAIN_1(x) FL2FXCONST_CFG(((x) / (float)(1 << 1)))
diff --git a/libSBRdec/include/sbrdecoder.h b/libSBRdec/include/sbrdecoder.h
index cc55572..c09c985 100644
--- a/libSBRdec/include/sbrdecoder.h
+++ b/libSBRdec/include/sbrdecoder.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
@@ -361,15 +361,20 @@ SBR_ERROR sbrDecoder_Parse(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs,
* error (0: core decoder found errors, 1: no errors).
* \param psDecoded Pointer to a buffer holding a flag. Input: PS is
* possible, Output: PS has been rendered.
+ * \param inDataHeadroom Headroom of the SBR input time signal to prevent
+ * clipping.
+ * \param outDataHeadroom Pointer to headroom of the SBR output time signal to
+ * prevent clipping.
*
* \return Error code.
*/
-SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, INT_PCM *input,
- INT_PCM *timeData, const int timeDataSize,
- int *numChannels, int *sampleRate,
+SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, LONG *input, LONG *timeData,
+ const int timeDataSize, int *numChannels,
+ int *sampleRate,
const FDK_channelMapDescr *const mapDescr,
const int mapIdx, const int coreDecodedOk,
- UCHAR *psDecoded);
+ UCHAR *psDecoded, const INT inDataHeadroom,
+ INT *outDataHeadroom);
/**
* \brief Close SBR decoder instance and free memory.
diff --git a/libSBRdec/src/HFgen_preFlat.cpp b/libSBRdec/src/HFgen_preFlat.cpp
index 268011e..ad4caba 100644
--- a/libSBRdec/src/HFgen_preFlat.cpp
+++ b/libSBRdec/src/HFgen_preFlat.cpp
@@ -897,10 +897,10 @@ void sbrDecoder_calculateGainVec(FIXP_DBL **sourceBufferReal,
for (i = startSample; i < stopSample; i++) {
maxVal |=
(FIXP_DBL)((LONG)(sourceBufferReal[i][loBand]) ^
- ((LONG)sourceBufferReal[i][loBand] >> (SAMPLE_BITS - 1)));
+ ((LONG)sourceBufferReal[i][loBand] >> (DFRACT_BITS - 1)));
maxVal |=
(FIXP_DBL)((LONG)(sourceBufferImag[i][loBand]) ^
- ((LONG)sourceBufferImag[i][loBand] >> (SAMPLE_BITS - 1)));
+ ((LONG)sourceBufferImag[i][loBand] >> (DFRACT_BITS - 1)));
}
if (maxVal != FL2FX_DBL(0.0f)) {
diff --git a/libSBRdec/src/hbe.cpp b/libSBRdec/src/hbe.cpp
index 2284c42..d210bb6 100644
--- a/libSBRdec/src/hbe.cpp
+++ b/libSBRdec/src/hbe.cpp
@@ -957,7 +957,7 @@ QmfTransposerCreate(HANDLE_HBE_TRANSPOSER* hQmfTransposer, const int frameSize,
hQmfTran->qmfOutBufSize = 2 * (hQmfTran->noCols / 2 + QMF_WIN_LEN - 1);
hQmfTran->inBuf_F =
- (INT_PCM*)FDKcalloc(QMF_SYNTH_CHANNELS + 20 + 1, sizeof(INT_PCM));
+ (LONG*)FDKcalloc(QMF_SYNTH_CHANNELS + 20 + 1, sizeof(LONG));
/* buffered time signal needs to be delayed by synthesis_size; max
* synthesis_size = 20; */
if (hQmfTran->inBuf_F == NULL) {
diff --git a/libSBRdec/src/hbe.h b/libSBRdec/src/hbe.h
index fdffe1e..3556783 100644
--- a/libSBRdec/src/hbe.h
+++ b/libSBRdec/src/hbe.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
@@ -132,6 +132,9 @@ typedef enum {
} KEEP_STATES_SYNCED_MODE;
struct hbeTransposer {
+ FIXP_DBL anaQmfStates[HBE_QMF_FILTER_STATE_ANA_SIZE];
+ FIXP_QSS synQmfStates[HBE_QMF_FILTER_STATE_SYN_SIZE];
+
int xOverQmf[MAX_NUM_PATCHES_HBE];
int maxStretch;
@@ -144,7 +147,7 @@ struct hbeTransposer {
int stopBand;
int bSbr41;
- INT_PCM *inBuf_F;
+ LONG *inBuf_F;
FIXP_DBL **qmfInBufReal_F;
FIXP_DBL **qmfInBufImag_F;
@@ -156,9 +159,6 @@ struct hbeTransposer {
FIXP_DBL const *synthesisQmfPreModCos_F;
FIXP_DBL const *synthesisQmfPreModSin_F;
- FIXP_QAS anaQmfStates[HBE_QMF_FILTER_STATE_ANA_SIZE];
- FIXP_QSS synQmfStates[HBE_QMF_FILTER_STATE_SYN_SIZE];
-
FIXP_DBL **qmfHBEBufReal_F;
FIXP_DBL **qmfHBEBufImag_F;
diff --git a/libSBRdec/src/sbr_dec.cpp b/libSBRdec/src/sbr_dec.cpp
index 30611e7..b1fb0da 100644
--- a/libSBRdec/src/sbr_dec.cpp
+++ b/libSBRdec/src/sbr_dec.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
@@ -259,17 +259,18 @@ static void copyHarmonicSpectrum(int *xOverQmf, FIXP_DBL **qmfReal,
void sbr_dec(
HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
- INT_PCM *timeIn, /*!< pointer to input time signal */
- INT_PCM *timeOut, /*!< pointer to output time signal */
+ LONG *timeIn, /*!< pointer to input time signal */
+ LONG *timeOut, /*!< pointer to output time signal */
HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */
- INT_PCM *timeOutRight, /*!< pointer to output time signal */
+ LONG *timeOutRight, /*!< pointer to output time signal */
const int strideOut, /*!< Time data traversal strideOut */
HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */
HANDLE_SBR_PREV_FRAME_DATA
hPrevFrameData, /*!< Some control data of last frame */
const int applyProcessing, /*!< Flag for SBR operation */
- HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize) {
+ HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize,
+ const INT sbrInDataHeadroom) {
int i, slot, reserve;
int saveLbScale;
int lastSlotOffs;
@@ -278,7 +279,7 @@ void sbr_dec(
/* temporary pointer / variable for QMF;
required as we want to use temporary buffer
creating one frame delay for HBE in LP mode */
- INT_PCM *pTimeInQmf = timeIn;
+ LONG *pTimeInQmf = timeIn;
/* Number of QMF timeslots in the overlap buffer: */
int ov_len = hSbrDec->LppTrans.pSettings->overlap;
@@ -341,8 +342,8 @@ void sbr_dec(
} else {
C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2 * (64));
qmfAnalysisFiltering(&hSbrDec->qmfDomainInCh->fb, pReal, pImag,
- &hSbrDec->qmfDomainInCh->scaling, pTimeInQmf, 0, 1,
- qmfTemp);
+ &hSbrDec->qmfDomainInCh->scaling, pTimeInQmf,
+ 0 + sbrInDataHeadroom, 1, qmfTemp);
C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2 * (64));
}
@@ -658,7 +659,7 @@ void sbr_dec(
if (!(flags & SBRDEC_PS_DECODED)) {
if (!(flags & SBRDEC_SKIP_QMF_SYN)) {
- int outScalefactor = 0;
+ int outScalefactor = -(8);
if (h_ps_d != NULL) {
h_ps_d->procFrameBased = 1; /* we here do frame based processing */
@@ -743,6 +744,7 @@ void sbr_dec(
*/
FDK_ASSERT(hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis <=
QMF_MAX_SYNTHESIS_BANDS);
+ qmfChangeOutScalefactor(synQmfRight, -(8));
FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates,
9 * hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis *
sizeof(FIXP_QSS));
@@ -814,7 +816,8 @@ void sbr_dec(
: scaleFactorLowBand_no_ov,
scaleFactorHighBand, synQmf->lsb, synQmf->usb);
- outScalefactorL = outScalefactorR = 1; /* psDiffScale! (MPEG-PS) */
+ outScalefactorL = outScalefactorR =
+ 1 + sbrInDataHeadroom; /* psDiffScale! (MPEG-PS) */
}
sbrDecoder_drcApplySlot(/* right channel */
@@ -831,6 +834,9 @@ void sbr_dec(
outScalefactorL += maxShift;
if (!(flags & SBRDEC_SKIP_QMF_SYN)) {
+ qmfChangeOutScalefactor(synQmf, -(8));
+ qmfChangeOutScalefactor(synQmfRight, -(8));
+
qmfSynthesisFilteringSlot(
synQmfRight, rQmfReal, /* QMF real buffer */
rQmfImag, /* QMF imag buffer */
diff --git a/libSBRdec/src/sbr_dec.h b/libSBRdec/src/sbr_dec.h
index 156da03..eb9c394 100644
--- a/libSBRdec/src/sbr_dec.h
+++ b/libSBRdec/src/sbr_dec.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
@@ -176,17 +176,18 @@ typedef SBR_CHANNEL *HANDLE_SBR_CHANNEL;
void sbr_dec(
HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
- INT_PCM *timeIn, /*!< pointer to input time signal */
- INT_PCM *timeOut, /*!< pointer to output time signal */
+ LONG *timeIn, /*!< pointer to input time signal */
+ LONG *timeOut, /*!< pointer to output time signal */
HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */
- INT_PCM *timeOutRight, /*!< pointer to output time signal */
+ LONG *timeOutRight, /*!< pointer to output time signal */
INT strideOut, /*!< Time data traversal strideOut */
HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */
HANDLE_SBR_PREV_FRAME_DATA
hPrevFrameData, /*!< Some control data of last frame */
const int applyProcessing, /*!< Flag for SBR operation */
- HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize);
+ HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize,
+ const INT sbrInDataHeadroom);
SBR_ERROR
createSbrDec(SBR_CHANNEL *hSbrChannel, HANDLE_SBR_HEADER_DATA hHeaderData,
diff --git a/libSBRdec/src/sbr_ram.cpp b/libSBRdec/src/sbr_ram.cpp
index 8b35fd2..a759d71 100644
--- a/libSBRdec/src/sbr_ram.cpp
+++ b/libSBRdec/src/sbr_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
@@ -109,9 +109,6 @@ amm-info@iis.fraunhofer.de
#include "sbr_ram.h"
-#define WORKBUFFER1_TAG 2
-#define WORKBUFFER2_TAG 3
-
/*!
\name StaticSbrData
diff --git a/libSBRdec/src/sbr_ram.h b/libSBRdec/src/sbr_ram.h
index e00f8b5..452f835 100644
--- a/libSBRdec/src/sbr_ram.h
+++ b/libSBRdec/src/sbr_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
@@ -170,6 +170,9 @@ struct SBR_DECODER_INSTANCE {
flushed consecutively. */
UINT flags;
+
+ INT sbrInDataHeadroom; /* Headroom of the SBR input time signal to prevent
+ clipping */
};
H_ALLOC_MEM(Ram_SbrDecElement, SBR_DECODER_ELEMENT)
diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp
index 52403f6..6e4aad4 100644
--- a/libSBRdec/src/sbrdecoder.cpp
+++ b/libSBRdec/src/sbrdecoder.cpp
@@ -155,7 +155,7 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */
#define SBRDECODER_LIB_VL0 3
-#define SBRDECODER_LIB_VL1 0
+#define SBRDECODER_LIB_VL1 1
#define SBRDECODER_LIB_VL2 0
#define SBRDECODER_LIB_TITLE "SBR Decoder"
#ifdef __ANDROID__
@@ -1570,10 +1570,10 @@ bail:
* \return SBRDEC_OK if successfull, else error code
*/
static SBR_ERROR sbrDecoder_DecodeElement(
- HANDLE_SBRDECODER self, QDOM_PCM *input, INT_PCM *timeData,
- const int timeDataSize, const FDK_channelMapDescr *const mapDescr,
- const int mapIdx, int channelIndex, const int elementIndex,
- const int numInChannels, int *numOutChannels, const int psPossible) {
+ HANDLE_SBRDECODER self, LONG *input, LONG *timeData, const int timeDataSize,
+ const FDK_channelMapDescr *const mapDescr, const int mapIdx,
+ int channelIndex, const int elementIndex, const int numInChannels,
+ int *numOutChannels, const int psPossible) {
SBR_DECODER_ELEMENT *hSbrElement = self->pSbrElement[elementIndex];
HANDLE_SBR_CHANNEL *pSbrChannel =
self->pSbrElement[elementIndex]->pSbrChannel;
@@ -1743,7 +1743,7 @@ static SBR_ERROR sbrDecoder_DecodeElement(
timeData + offset1, strideOut, hSbrHeader, hFrameDataLeft,
&pSbrChannel[0]->prevFrameData,
(hSbrHeader->syncState == SBR_ACTIVE), h_ps_d, self->flags,
- codecFrameSize);
+ codecFrameSize, self->sbrInDataHeadroom);
if (stereo) {
/* Process right channel */
@@ -1751,7 +1751,7 @@ static SBR_ERROR sbrDecoder_DecodeElement(
timeData + offset1, NULL, NULL, strideOut, hSbrHeader,
hFrameDataRight, &pSbrChannel[1]->prevFrameData,
(hSbrHeader->syncState == SBR_ACTIVE), NULL, self->flags,
- codecFrameSize);
+ codecFrameSize, self->sbrInDataHeadroom);
}
C_ALLOC_SCRATCH_END(pPsScratch, struct PS_DEC_COEFFICIENTS, 1)
@@ -1771,14 +1771,14 @@ static SBR_ERROR sbrDecoder_DecodeElement(
int copyFrameSize =
codecFrameSize * self->pQmfDomain->QmfDomainOut->fb.no_channels;
copyFrameSize /= self->pQmfDomain->QmfDomainIn->fb.no_channels;
- INT_PCM *ptr;
+ LONG *ptr;
INT i;
FDK_ASSERT(strideOut == 2);
ptr = timeData;
for (i = copyFrameSize >> 1; i--;) {
- INT_PCM tmp; /* This temporal variable is required because some
- compilers can't do *ptr++ = *ptr++ correctly. */
+ LONG tmp; /* This temporal variable is required because some compilers
+ can't do *ptr++ = *ptr++ correctly. */
tmp = *ptr++;
*ptr++ = tmp;
tmp = *ptr++;
@@ -1791,12 +1791,13 @@ static SBR_ERROR sbrDecoder_DecodeElement(
return errorStatus;
}
-SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, INT_PCM *input,
- INT_PCM *timeData, const int timeDataSize,
- int *numChannels, int *sampleRate,
+SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, LONG *input, LONG *timeData,
+ const int timeDataSize, int *numChannels,
+ int *sampleRate,
const FDK_channelMapDescr *const mapDescr,
const int mapIdx, const int coreDecodedOk,
- UCHAR *psDecoded) {
+ UCHAR *psDecoded, const INT inDataHeadroom,
+ INT *outDataHeadroom) {
SBR_ERROR errorStatus = SBRDEC_OK;
int psPossible;
@@ -1833,6 +1834,9 @@ SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, INT_PCM *input,
psPossible = 0;
}
+ self->sbrInDataHeadroom = inDataHeadroom;
+ *outDataHeadroom = (INT)(8);
+
/* Make sure that even if no SBR data was found/parsed *psDecoded is returned
* 1 if psPossible was 0. */
if (psPossible == 0) {