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