diff --git a/documentation/aacDecoder.pdf b/documentation/aacDecoder.pdf index d04a7d6..cc7cf41 100644 Binary files a/documentation/aacDecoder.pdf and b/documentation/aacDecoder.pdf 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_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/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/libFDK/include/FDK_qmf_domain.h b/libFDK/include/FDK_qmf_domain.h index aa247e9..0e83da3 100644 --- a/libFDK/include/FDK_qmf_domain.h +++ b/libFDK/include/FDK_qmf_domain.h @@ -160,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. @@ -181,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 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/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 71e2ef5..77c5ca2 100644 --- a/libFDK/src/FDK_qmf_domain.cpp +++ b/libFDK/src/FDK_qmf_domain.cpp @@ -637,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; @@ -648,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; 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; + } + + if (pGainPerSample == NULL) { + additionalGainAvailable = 0; } for (i = 0; i < nSamples; i++) { - if (gain_delay) { - if (i < gain_delay) { - additionalGainUnfiltered = limiter->additionalGainPrev; - } else { - additionalGainUnfiltered = pGain[0]; - } - - /* Smooth additionalGain */ - /* [b,a] = butter(1, 0.01) */ - static const FIXP_SGL b[] = {FL2FXCONST_SGL(0.015466 * 2.0), - FL2FXCONST_SGL(0.015466 * 2.0)}; - static const FIXP_SGL a[] = {(FIXP_SGL)MAXVAL_SGL, - FL2FXCONST_SGL(-0.96907)}; - additionalGain = -fMult(additionalGainSmoothState, a[1]) + - fMultDiv2(additionalGainUnfiltered, b[0]) + - fMultDiv2(additionalGainSmoothState1, b[1]); - additionalGainSmoothState1 = additionalGainUnfiltered; - additionalGainSmoothState = additionalGain; - - /* Apply the additional scaling that has no delay and no smoothing */ - if (gain_scale[0] > 0) { - additionalGain <<= gain_scale[0]; - } else { - additionalGain >>= -gain_scale[0]; - } - } /* get maximum absolute sample value of all channels, including the * additional gain. */ - tmp1 = (FIXP_DBL)0; + tmp = (FIXP_DBL)0; for (j = 0; j < channels; j++) { tmp2 = PCM_LIM2FIXP_DBL(samplesIn[j]); tmp2 = (tmp2 == (FIXP_DBL)MINVAL_DBL) ? (FIXP_DBL)MAXVAL_DBL : fAbs(tmp2); - tmp1 = fMax(tmp1, tmp2); + tmp = fMax(tmp, tmp2); + } + + if (additionalGainAvailable) { + additionalGain = pGainPerSample[i]; + tmp = fMult(tmp, additionalGain); } - tmp = fMult(tmp1, additionalGain); /* set threshold as lower border to save calculations in running maximum * algorithm */ @@ -314,22 +288,42 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn, /* lookahead delay, apply gain */ for (j = 0; j < channels; j++) { tmp = p_delayBuf[j]; - p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain); + + if (additionalGainAvailable) { + p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain); + } else { + p_delayBuf[j] = PCM_LIM2FIXP_DBL(samplesIn[j]); + } /* Apply gain to delayed signal */ tmp = fMultDiv2(tmp, gain); - +#if (SAMPLE_BITS == DFRACT_BITS) + samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM( + (FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling + 1, DFRACT_BITS)); +#else samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT( - tmp, TDL_GAIN_SCALING + 1, DFRACT_BITS)); + tmp + ((FIXP_DBL)0x8000 >> (scaling + 1)), scaling + 1, + DFRACT_BITS)); +#endif } gain >>= 1; } else { /* lookahead delay, apply gain=1.0f */ for (j = 0; j < channels; j++) { tmp = p_delayBuf[j]; - p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain); + if (additionalGainAvailable) { + p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain); + } else { + p_delayBuf[j] = PCM_LIM2FIXP_DBL(samplesIn[j]); + } + +#if (SAMPLE_BITS == DFRACT_BITS) + samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM( + (FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling, DFRACT_BITS)); +#else samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT( - tmp, TDL_GAIN_SCALING, DFRACT_BITS)); + tmp + ((FIXP_DBL)0x8000 >> scaling), scaling, DFRACT_BITS)); +#endif } } @@ -354,13 +348,9 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn, limiter->delayBufIdx = delayBufIdx; limiter->smoothState0 = smoothState0; - limiter->additionalGainFilterState = additionalGainSmoothState; - limiter->additionalGainFilterState1 = additionalGainSmoothState1; limiter->minGain = minGain; - limiter->additionalGainPrev = pGain[0]; - return TDLIMIT_OK; } } @@ -370,7 +360,7 @@ TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter, FIXP_DBL threshold) { if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; - limiter->threshold = threshold >> TDL_GAIN_SCALING; + limiter->threshold = threshold; return TDLIMIT_OK; } @@ -384,13 +374,7 @@ TDLIMITER_ERROR pcmLimiter_Reset(TDLimiterPtr limiter) { limiter->cor = FL2FXCONST_DBL(1.0f / (1 << 1)); limiter->smoothState0 = FL2FXCONST_DBL(1.0f / (1 << 1)); limiter->minGain = FL2FXCONST_DBL(1.0f / (1 << 1)); - - limiter->additionalGainPrev = - FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING)); - limiter->additionalGainFilterState = - FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING)); - limiter->additionalGainFilterState1 = - FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING)); + limiter->scaling = 0; FDKmemset(limiter->maxBuf, 0, (limiter->attack + 1) * sizeof(FIXP_DBL)); FDKmemset(limiter->delayBuf, 0, 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.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) {