Avoid decoder internal clipping by converting the whole audio sample data path from 16 to 32 bit data width (FDKdec v3.2.0).

Bug: 149514474
Test: atest DecoderTestXheAac DecoderTestAacDrc
Change-Id: I8a504ab709e42e27a61fe29840212953742283a5
This commit is contained in:
Fraunhofer IIS FDK 2019-12-19 17:28:15 +01:00 committed by Jean-Michel Trivi
parent 57c9355de0
commit e016635f0d
41 changed files with 488 additions and 442 deletions

Binary file not shown.

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -113,7 +113,7 @@ INT FDK_Delay_Create(FDK_SignalDelay* data, const USHORT delay,
if (delay > 0) { if (delay > 0) {
data->delay_line = 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) { if (data->delay_line == NULL) {
return -1; return -1;
} }
@ -126,36 +126,36 @@ INT FDK_Delay_Create(FDK_SignalDelay* data, const USHORT delay,
return 0; 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) { const UINT frame_length, const UCHAR channel) {
FDK_ASSERT(data != NULL); FDK_ASSERT(data != NULL);
if (data->delay > 0) { 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(frame_length <= MAX_FRAME_LENGTH);
FDK_ASSERT(channel < data->num_channels); FDK_ASSERT(channel < data->num_channels);
FDK_ASSERT(time_buffer != NULL); FDK_ASSERT(time_buffer != NULL);
if (frame_length >= data->delay) { if (frame_length >= data->delay) {
FDKmemcpy(tmp, &time_buffer[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], 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], 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, FDKmemcpy(&data->delay_line[channel * data->delay], tmp,
data->delay * sizeof(FIXP_PCM)); data->delay * sizeof(PCM_DEC));
} else { } 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], 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], FDKmemcpy(&data->delay_line[channel * data->delay],
&data->delay_line[channel * data->delay + frame_length], &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 + FDKmemcpy(&data->delay_line[channel * data->delay +
(data->delay - frame_length)], (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; return;

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -109,7 +109,7 @@ amm-info@iis.fraunhofer.de
* Structure representing one delay element for multiple channels. * Structure representing one delay element for multiple channels.
*/ */
typedef struct { 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). */ USHORT delay; /*!< Delay required in samples (per channel). */
UCHAR num_channels; /*!< Number of channels to delay. */ UCHAR num_channels; /*!< Number of channels to delay. */
} FDK_SignalDelay; } FDK_SignalDelay;
@ -137,7 +137,7 @@ INT FDK_Delay_Create(FDK_SignalDelay* data, const USHORT delay,
* *
* \return void * \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); const UINT frame_length, const UCHAR channel);
/** /**

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -108,6 +108,7 @@ amm-info@iis.fraunhofer.de
#include "aacdec_hcr_types.h" #include "aacdec_hcr_types.h"
#include "aacdec_hcrs.h" #include "aacdec_hcrs.h"
#define PCM_AAC LONG
#define PCM_DEC FIXP_DBL #define PCM_DEC FIXP_DBL
#define MAXVAL_PCM_DEC MAXVAL_DBL #define MAXVAL_PCM_DEC MAXVAL_DBL
#define MINVAL_PCM_DEC MINVAL_DBL #define MINVAL_PCM_DEC MINVAL_DBL

View File

@ -1281,6 +1281,7 @@ LINKSPEC_CPP HANDLE_AACDECODER CAacDecoder_Open(
/* Set default frame delay */ /* Set default frame delay */
aacDecoder_drcSetParam(self->hDrcInfo, DRC_BS_DELAY, aacDecoder_drcSetParam(self->hDrcInfo, DRC_BS_DELAY,
CConcealment_GetDelay(&self->concealCommonData)); CConcealment_GetDelay(&self->concealCommonData));
self->workBufferCore1 = (FIXP_DBL *)GetWorkBufferCore1();
self->workBufferCore2 = GetWorkBufferCore2(); self->workBufferCore2 = GetWorkBufferCore2();
if (self->workBufferCore2 == NULL) goto bail; if (self->workBufferCore2 == NULL) goto bail;
@ -1456,6 +1457,10 @@ LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self) {
FreeDrcInfo(&self->hDrcInfo); FreeDrcInfo(&self->hDrcInfo);
} }
if (self->workBufferCore1 != NULL) {
FreeWorkBufferCore1((CWorkBufferCore1 **)&self->workBufferCore1);
}
/* Free WorkBufferCore2 */ /* Free WorkBufferCore2 */
if (self->workBufferCore2 != NULL) { if (self->workBufferCore2 != NULL) {
FreeWorkBufferCore2(&self->workBufferCore2); FreeWorkBufferCore2(&self->workBufferCore2);
@ -1493,6 +1498,8 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
UCHAR downscaleFactor = self->downscaleFactor; UCHAR downscaleFactor = self->downscaleFactor;
UCHAR downscaleFactorInBS = self->downscaleFactorInBS; UCHAR downscaleFactorInBS = self->downscaleFactorInBS;
self->aacOutDataHeadroom = (3);
// set profile and check for supported aot // set profile and check for supported aot
// leave profile on default (=-1) for all other supported MPEG-4 aot's except // leave profile on default (=-1) for all other supported MPEG-4 aot's except
// aot=2 (=AAC-LC) // aot=2 (=AAC-LC)
@ -2394,7 +2401,7 @@ bail:
} }
LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( 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) { const INT timeDataSize, const int timeDataChannelOffset) {
AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; 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)); FDKmemcpy(drcChMap, self->chMapping, (8) * sizeof(UCHAR));
} }
/* Turn on/off DRC modules level normalization in digital domain depending /* Turn off DRC modules level normalization in digital domain. */
* on the limiter status. */ aacDecoder_drcSetParam(self->hDrcInfo, APPLY_NORMALIZATION, 0);
aacDecoder_drcSetParam(self->hDrcInfo, APPLY_NORMALIZATION,
(self->limiterEnableCurr) ? 0 : 1);
/* deactivate legacy DRC in case uniDrc is active, i.e. uniDrc payload is /* deactivate legacy DRC in case uniDrc is active, i.e. uniDrc payload is
* present and one of DRC or Loudness Normalization is switched on */ * present and one of DRC or Loudness Normalization is switched on */
@ -3325,9 +3330,11 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
&pAacDecoderStaticChannelInfo->drcData); &pAacDecoderStaticChannelInfo->drcData);
} }
} }
/* The DRC module demands to be called with the gain field holding the /* The DRC module demands to be called with the gain field holding the
* gain scale. */ * gain scale. */
self->extGain[0] = (FIXP_DBL)TDL_GAIN_SCALING; self->extGain[0] = (FIXP_DBL)AACDEC_DRC_GAIN_SCALING;
/* DRC processing */ /* DRC processing */
aacDecoder_drcApply( aacDecoder_drcApply(
self->hDrcInfo, self->hSbrDecoder, pAacDecoderChannelInfo, self->hDrcInfo, self->hSbrDecoder, pAacDecoderChannelInfo,
@ -3343,7 +3350,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
if (self->flushStatus && (self->flushCnt > 0) && if (self->flushStatus && (self->flushCnt > 0) &&
!(flags & AACDEC_CONCEAL)) { !(flags & AACDEC_CONCEAL)) {
FDKmemclear(pTimeData + offset, FDKmemclear(pTimeData + offset,
sizeof(FIXP_PCM) * self->streamInfo.aacSamplesPerFrame); sizeof(PCM_DEC) * self->streamInfo.aacSamplesPerFrame);
} else } else
switch (pAacDecoderChannelInfo->renderMode) { switch (pAacDecoderChannelInfo->renderMode) {
case AACDEC_RENDER_IMDCT: case AACDEC_RENDER_IMDCT:
@ -3355,7 +3362,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
!frameOk_butConceal), !frameOk_butConceal),
pAacDecoderChannelInfo->pComStaticData->pWorkBufferCore1 pAacDecoderChannelInfo->pComStaticData->pWorkBufferCore1
->mdctOutTemp, ->mdctOutTemp,
self->elFlags[el], elCh); self->aacOutDataHeadroom, self->elFlags[el], elCh);
self->extGainDelay = self->streamInfo.aacSamplesPerFrame; self->extGainDelay = self->streamInfo.aacSamplesPerFrame;
break; break;
@ -3376,7 +3383,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
&self->samplingRateInfo[streamIndex], &self->samplingRateInfo[streamIndex],
(self->frameOK && !(flags & AACDEC_CONCEAL) && (self->frameOK && !(flags & AACDEC_CONCEAL) &&
!frameOk_butConceal), !frameOk_butConceal),
flags, self->flags[streamIndex]); self->aacOutDataHeadroom, flags, self->flags[streamIndex]);
self->extGainDelay = self->streamInfo.aacSamplesPerFrame; self->extGainDelay = self->streamInfo.aacSamplesPerFrame;
break; break;
@ -3388,7 +3395,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
if (!CConceal_TDFading_Applied[c]) { if (!CConceal_TDFading_Applied[c]) {
CConceal_TDFading_Applied[c] = CConcealment_TDFading( CConceal_TDFading_Applied[c] = CConcealment_TDFading(
self->streamInfo.aacSamplesPerFrame, self->streamInfo.aacSamplesPerFrame,
&self->pAacDecoderStaticChannelInfo[c], pTimeData + offset, 0); &self->pAacDecoderStaticChannelInfo[c], self->aacOutDataHeadroom,
pTimeData + offset, 0);
if (c + 1 < (8) && c < aacChannels - 1) { if (c + 1 < (8) && c < aacChannels - 1) {
/* update next TDNoise Seed to avoid muting in case of Parametric /* update next TDNoise Seed to avoid muting in case of Parametric
* Stereo */ * Stereo */
@ -3409,27 +3417,18 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
* LR) */ * LR) */
if ((aacChannels == 2) && bsPseudoLr) { if ((aacChannels == 2) && bsPseudoLr) {
int i, offset2; int i, offset2;
const FIXP_SGL invSqrt2 = const FIXP_SGL invSqrt2 = FL2FXCONST_SGL(0.707106781186547f);
FL2FXCONST_SGL(0.353553390593273f); /* scaled by -1 */ PCM_DEC *pTD = pTimeData;
FIXP_PCM *pTD = pTimeData;
offset2 = timeDataChannelOffset; offset2 = timeDataChannelOffset;
for (i = 0; i < self->streamInfo.aacSamplesPerFrame; i++) { for (i = 0; i < self->streamInfo.aacSamplesPerFrame; i++) {
FIXP_DBL L = FX_PCM2FX_DBL(pTD[0]); FIXP_DBL L = PCM_DEC2FIXP_DBL(pTD[0]);
FIXP_DBL R = FX_PCM2FX_DBL(pTD[offset2]); FIXP_DBL R = PCM_DEC2FIXP_DBL(pTD[offset2]);
L = fMult(L, invSqrt2); L = fMult(L, invSqrt2);
R = fMult(R, invSqrt2); R = fMult(R, invSqrt2);
#if (SAMPLE_BITS == 16) pTD[0] = L + R;
pTD[0] = (FIXP_SGL)SATURATE_RIGHT_SHIFT(L + R + (FIXP_DBL)(1 << 14), pTD[offset2] = L - R;
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++; pTD++;
} }
} }

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -191,6 +191,9 @@ struct AAC_DECODER_INSTANCE {
INT outputInterleaved; /*!< PCM output format (interleaved/none interleaved). 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. */ HANDLE_TRANSPORTDEC hInput; /*!< Transport layer handle. */
SamplingRateInfo SamplingRateInfo
@ -235,6 +238,7 @@ struct AAC_DECODER_INSTANCE {
CAacDecoderStaticChannelInfo CAacDecoderStaticChannelInfo
*pAacDecoderStaticChannelInfo[(8)]; /*!< Persistent channel memory */ *pAacDecoderStaticChannelInfo[(8)]; /*!< Persistent channel memory */
FIXP_DBL *workBufferCore1;
FIXP_DBL *workBufferCore2; FIXP_DBL *workBufferCore2;
PCM_DEC *pTimeData2; PCM_DEC *pTimeData2;
INT timeData2Size; INT timeData2Size;
@ -311,11 +315,10 @@ This structure is allocated once for each CPE. */
UCHAR limiterEnableUser; /*!< The limiter configuration requested by the UCHAR limiterEnableUser; /*!< The limiter configuration requested by the
library user */ library user */
UCHAR limiterEnableCurr; /*!< The current limiter configuration. */ UCHAR limiterEnableCurr; /*!< The current limiter configuration. */
FIXP_DBL extGain[1]; /*!< Gain that must be applied to the output signal. */ FIXP_DBL extGain[1]; /*!< Gain that must be applied to the output signal. */
UINT extGainDelay; /*!< Delay that must be accounted for extGain. */ UINT extGainDelay; /*!< Delay that must be accounted for extGain. */
INT_PCM pcmOutputBuffer[(8) * (1024 * 2)];
HANDLE_DRC_DECODER hUniDrcDecoder; HANDLE_DRC_DECODER hUniDrcDecoder;
UCHAR multibandDrcPresent; UCHAR multibandDrcPresent;
UCHAR numTimeSlots; UCHAR numTimeSlots;
@ -427,7 +430,7 @@ LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self,
\return error status \return error status
*/ */
LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_DecodeFrame( 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); const INT timeDataSize, const int timeDataChannelOffset);
/* Free config dependent AAC memory */ /* Free config dependent AAC memory */

View File

@ -119,8 +119,8 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */ /* Decoder library info */
#define AACDECODER_LIB_VL0 3 #define AACDECODER_LIB_VL0 3
#define AACDECODER_LIB_VL1 1 #define AACDECODER_LIB_VL1 2
#define AACDECODER_LIB_VL2 3 #define AACDECODER_LIB_VL2 0
#define AACDECODER_LIB_TITLE "AAC Decoder Lib" #define AACDECODER_LIB_TITLE "AAC Decoder Lib"
#ifdef __ANDROID__ #ifdef __ANDROID__
#define AACDECODER_LIB_BUILD_DATE "" #define AACDECODER_LIB_BUILD_DATE ""
@ -1131,35 +1131,31 @@ static INT aacDecoder_EstimateNumberOfLostFrames(HANDLE_AACDECODER self) {
return n; return n;
} }
LINKSPEC_CPP AAC_DECODER_ERROR LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, INT_PCM *pTimeData,
const INT timeDataSize_extern, const UINT flags) { const INT timeDataSize,
const UINT flags) {
AAC_DECODER_ERROR ErrorStatus; AAC_DECODER_ERROR ErrorStatus;
INT layer; INT layer;
INT nBits; INT nBits;
INT timeData2Size;
INT timeData3Size;
INT timeDataHeadroom;
HANDLE_FDK_BITSTREAM hBs; HANDLE_FDK_BITSTREAM hBs;
int fTpInterruption = 0; /* Transport originated interruption detection. */ int fTpInterruption = 0; /* Transport originated interruption detection. */
int fTpConceal = 0; /* Transport originated concealment. */ int fTpConceal = 0; /* Transport originated concealment. */
INT_PCM *pTimeData = NULL;
INT timeDataSize = 0;
UINT accessUnit = 0; UINT accessUnit = 0;
UINT numAccessUnits = 1; UINT numAccessUnits = 1;
UINT numPrerollAU = 0; UINT numPrerollAU = 0;
int fEndAuNotAdjusted = 0; /* The end of the access unit was not adjusted */ int fEndAuNotAdjusted = 0; /* The end of the access unit was not adjusted */
int applyCrossfade = 1; /* flag indicates if flushing was possible */ int applyCrossfade = 1; /* flag indicates if flushing was possible */
FIXP_PCM *pTimeDataFixpPcm; /* Signal buffer for decoding process before PCM PCM_DEC *pTimeData2;
processing */ PCM_AAC *pTimeData3;
INT timeDataFixpPcmSize;
PCM_DEC *pTimeDataPcmPost; /* Signal buffer for PCM post-processing */
INT timeDataPcmPostSize;
if (self == NULL) { if (self == NULL) {
return AAC_DEC_INVALID_HANDLE; return AAC_DEC_INVALID_HANDLE;
} }
pTimeData = self->pcmOutputBuffer;
timeDataSize = sizeof(self->pcmOutputBuffer) / sizeof(*self->pcmOutputBuffer);
if (flags & AACDEC_INTR) { if (flags & AACDEC_INTR) {
self->streamInfo.numLostAccessUnits = 0; self->streamInfo.numLostAccessUnits = 0;
} }
@ -1315,19 +1311,23 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
/* Use limiter configuration as requested. */ /* Use limiter configuration as requested. */
self->limiterEnableCurr = self->limiterEnableUser; 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; /* reset DRC level normalization gain on a per frame basis */
timeDataFixpPcmSize = timeDataSize; 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( ErrorStatus = CAacDecoder_DecodeFrame(
self, self,
flags | (fTpConceal ? AACDEC_CONCEAL : 0) | flags | (fTpConceal ? AACDEC_CONCEAL : 0) |
((self->flushStatus && !(flags & AACDEC_CONCEAL)) ? AACDEC_FLUSH ((self->flushStatus && !(flags & AACDEC_CONCEAL)) ? AACDEC_FLUSH
: 0), : 0),
pTimeDataFixpPcm + 0, timeDataFixpPcmSize, pTimeData2 + 0, timeData2Size, self->streamInfo.aacSamplesPerFrame + 0);
self->streamInfo.aacSamplesPerFrame + 0);
timeDataHeadroom = self->aacOutDataHeadroom;
/* if flushing for USAC DASH IPF was not possible go on with decoding /* if flushing for USAC DASH IPF was not possible go on with decoding
* preroll */ * 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. */ * nothing else we can do, so bail. */
if (!IS_OUTPUT_VALID(ErrorStatus)) { if (!IS_OUTPUT_VALID(ErrorStatus)) {
goto bail; goto bail;
@ -1366,10 +1366,10 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
self->streamInfo.numChannels = self->streamInfo.aacNumChannels; self->streamInfo.numChannels = self->streamInfo.aacNumChannels;
{ {
FDK_Delay_Apply(&self->usacResidualDelay, FDK_Delay_Apply(
pTimeDataFixpPcm + &self->usacResidualDelay,
1 * (self->streamInfo.aacSamplesPerFrame + 0) + 0, pTimeData2 + 1 * (self->streamInfo.aacSamplesPerFrame + 0) + 0,
self->streamInfo.frameSize, 0); self->streamInfo.frameSize, 0);
} }
/* Setting of internal MPS state; may be reset in CAacDecoder_SyncQmfMode /* 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)) { switch (FDK_QmfDomain_Configure(&self->qmfDomain)) {
default: default:
case QMF_DOMAIN_INIT_ERROR: 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, sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF,
(self->mpsEnableCurr) ? 2 : 0); (self->mpsEnableCurr) ? 2 : 0);
INT_PCM *input; PCM_AAC *input;
input = (INT_PCM *)self->workBufferCore2; input = (PCM_AAC *)self->workBufferCore2;
FDKmemcpy(input, pTimeData, FDKmemcpy(input, pTimeData3,
sizeof(INT_PCM) * (self->streamInfo.numChannels) * sizeof(PCM_AAC) * (self->streamInfo.numChannels) *
(self->streamInfo.frameSize)); (self->streamInfo.frameSize));
/* apply SBR processing */ /* apply SBR processing */
sbrError = sbrDecoder_Apply(self->hSbrDecoder, input, pTimeData, sbrError = sbrDecoder_Apply(
timeDataSize, &self->streamInfo.numChannels, self->hSbrDecoder, input, pTimeData3, timeData3Size,
&self->streamInfo.sampleRate, &self->streamInfo.numChannels, &self->streamInfo.sampleRate,
&self->mapDescr, self->chMapIndex, &self->mapDescr, self->chMapIndex, self->frameOK, &self->psPossible,
self->frameOK, &self->psPossible); self->aacOutDataHeadroom, &timeDataHeadroom);
if (sbrError == SBRDEC_OK) { if (sbrError == SBRDEC_OK) {
/* Update data in streaminfo structure. Assume that the SBR upsampling /* 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) { if (err == 0) {
err = mpegSurroundDecoder_Apply( err = mpegSurroundDecoder_Apply(
(CMpegSurroundDecoder *)self->pMpegSurroundDecoder, (CMpegSurroundDecoder *)self->pMpegSurroundDecoder,
(INT_PCM *)self->workBufferCore2, pTimeData, timeDataSize, (PCM_AAC *)self->workBufferCore2, pTimeData3, timeData3Size,
self->streamInfo.aacSamplesPerFrame, &nChannels, &frameSize, self->streamInfo.aacSamplesPerFrame, &nChannels, &frameSize,
self->streamInfo.sampleRate, self->streamInfo.aot, 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) { 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; self->streamInfo.frameSize = self->mpsFrameSizeLast;
/* ... and clear output buffer so that potentially corrupted data does /* ... and clear output buffer so that potentially corrupted data does
* not reach the framework. */ * not reach the framework. */
FDKmemclear(pTimeData, self->mpsOutChannelsLast * FDKmemclear(pTimeData3, self->mpsOutChannelsLast *
self->mpsFrameSizeLast * sizeof(INT_PCM)); self->mpsFrameSizeLast * sizeof(PCM_AAC));
/* Additionally proclaim that this frame had errors during decoding. /* Additionally proclaim that this frame had errors during decoding.
*/ */
ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; 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); sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF, 1);
/* apply SBR processing */ /* apply SBR processing */
sbrError = sbrDecoder_Apply(self->hSbrDecoder, pTimeData, pTimeData, sbrError = sbrDecoder_Apply(
timeDataSize, &self->streamInfo.numChannels, self->hSbrDecoder, pTimeData3, pTimeData3, timeData3Size,
&self->streamInfo.sampleRate, &self->streamInfo.numChannels, &self->streamInfo.sampleRate,
&self->mapDescr, self->chMapIndex, &self->mapDescr, self->chMapIndex, self->frameOK, &self->psPossible,
self->frameOK, &self->psPossible); self->aacOutDataHeadroom, &timeDataHeadroom);
if (sbrError == SBRDEC_OK) { if (sbrError == SBRDEC_OK) {
/* Update data in streaminfo structure. Assume that the SBR upsampling /* 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 = if ((INT)PCM_OUT_HEADROOM != timeDataHeadroom) {
self->streamInfo.frameSize * self->streamInfo.numChannels; for (int i = ((self->streamInfo.frameSize *
FDK_ASSERT(timeDataPcmPostSize >= size); self->streamInfo.numChannels) -
for (int i = 0; i < size; i++) { 1);
pTimeDataPcmPost[i] = i >= 0; i--) {
(PCM_DEC)FX_PCM2PCM_DEC(pTimeData[i]) >> PCM_OUT_HEADROOM; 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) && if ((self->streamInfo.numChannels > 1) &&
(0 || (self->sbrEnabled) || (self->mpsEnableCurr))) { (0 || (self->sbrEnabled) || (self->mpsEnableCurr))) {
/* interleaving/deinterleaving is performed on upper part of /* interleaving/deinterleaving is performed on upper part of
* pTimeDataPcmPost. Check if this buffer is large enough. */ * pTimeData2. Check if this buffer is large enough. */
if (timeDataPcmPostSize < if (timeData2Size < (INT)(2 * self->streamInfo.numChannels *
(INT)(2 * self->streamInfo.numChannels * self->streamInfo.frameSize)) {
self->streamInfo.frameSize * sizeof(PCM_DEC))) {
ErrorStatus = AAC_DEC_UNKNOWN; ErrorStatus = AAC_DEC_UNKNOWN;
goto bail; goto bail;
} }
needsDeinterleaving = 1; needsDeinterleaving = 1;
drcWorkBuffer = drcWorkBuffer =
(FIXP_DBL *)pTimeDataPcmPost + (FIXP_DBL *)pTimeData2 +
self->streamInfo.numChannels * self->streamInfo.frameSize; self->streamInfo.numChannels * self->streamInfo.frameSize;
FDK_deinterleave( FDK_deinterleave(
pTimeDataPcmPost, drcWorkBuffer, self->streamInfo.numChannels, pTimeData2, drcWorkBuffer, self->streamInfo.numChannels,
self->streamInfo.frameSize, self->streamInfo.frameSize); self->streamInfo.frameSize, self->streamInfo.frameSize);
} else { } else {
drcWorkBuffer = (FIXP_DBL *)pTimeDataPcmPost; drcWorkBuffer = pTimeData2;
} }
/* prepare Loudness Normalisation gain */ /* prepare Loudness Normalisation gain */
@ -1759,7 +1755,7 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
if (needsDeinterleaving) { if (needsDeinterleaving) {
FDK_interleave( FDK_interleave(
drcWorkBuffer, pTimeDataPcmPost, self->streamInfo.numChannels, drcWorkBuffer, pTimeData2, self->streamInfo.numChannels,
self->streamInfo.frameSize, self->streamInfo.frameSize); 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) { if (self->streamInfo.extAot != AOT_AAC_SLS) {
INT pcmLimiterScale = 0; INT pcmLimiterScale = 0;
INT interleaved = 0;
interleaved |= (self->sbrEnabled) ? 1 : 0;
interleaved |= (self->mpsEnableCurr) ? 1 : 0;
PCMDMX_ERROR dmxErr = PCMDMX_OK; PCMDMX_ERROR dmxErr = PCMDMX_OK;
if ((flags & AACDEC_INTR) && (accessUnit == 0)) { if ((flags & AACDEC_INTR) && (accessUnit == 0)) {
/* delete data from the past (e.g. mixdown coeficients) */ /* 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 */ /* do PCM post processing */
dmxErr = pcmDmx_ApplyFrame( dmxErr = pcmDmx_ApplyFrame(self->hPcmUtils, pTimeData2, timeData2Size,
self->hPcmUtils, pTimeDataPcmPost, timeDataFixpPcmSize, self->streamInfo.frameSize,
self->streamInfo.frameSize, &self->streamInfo.numChannels, &self->streamInfo.numChannels, interleaved,
interleaved, self->channelType, self->channelIndices, self->channelType, self->channelIndices,
&self->mapDescr, &self->mapDescr, &pcmLimiterScale);
(self->limiterEnableCurr) ? &pcmLimiterScale : NULL);
if (dmxErr == PCMDMX_OUTPUT_BUFFER_TOO_SMALL) { if (dmxErr == PCMDMX_OUTPUT_BUFFER_TOO_SMALL) {
ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL;
goto bail; goto bail;
@ -1833,13 +1827,35 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
} }
pcmLimiterScale += PCM_OUT_HEADROOM;
if (flags & AACDEC_CLRHIST) { if (flags & AACDEC_CLRHIST) {
if (!(self->flags[0] & AC_USAC)) { if (!(self->flags[0] & AC_USAC)) {
/* Reset DRC data */
aacDecoder_drcReset(self->hDrcInfo);
/* Delete the delayed signal. */ /* Delete the delayed signal. */
pcmLimiter_Reset(self->hLimiter); 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) { if (self->limiterEnableCurr) {
/* use workBufferCore2 buffer for interleaving */ /* use workBufferCore2 buffer for interleaving */
PCM_LIM *pInterleaveBuffer; PCM_LIM *pInterleaveBuffer;
@ -1848,44 +1864,72 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern,
/* Set actual signal parameters */ /* Set actual signal parameters */
pcmLimiter_SetNChannels(self->hLimiter, self->streamInfo.numChannels); pcmLimiter_SetNChannels(self->hLimiter, self->streamInfo.numChannels);
pcmLimiter_SetSampleRate(self->hLimiter, self->streamInfo.sampleRate); pcmLimiter_SetSampleRate(self->hLimiter, self->streamInfo.sampleRate);
pcmLimiterScale += PCM_OUT_HEADROOM;
if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) || if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
(self->mpsEnableCurr)) { (self->mpsEnableCurr)) {
pInterleaveBuffer = (PCM_LIM *)pTimeDataPcmPost; pInterleaveBuffer = (PCM_LIM *)pTimeData2;
} else { } else {
pInterleaveBuffer = (PCM_LIM *)pTimeData; pInterleaveBuffer = (PCM_LIM *)self->workBufferCore2;
/* applyLimiter requests for interleaved data */ /* applyLimiter requests for interleaved data */
/* Interleave ouput buffer */ /* Interleave ouput buffer */
FDK_interleave(pTimeDataPcmPost, pInterleaveBuffer, FDK_interleave(pTimeData2, pInterleaveBuffer,
self->streamInfo.numChannels, blockLength, self->streamInfo.numChannels, blockLength,
self->streamInfo.frameSize); 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, pcmLimiter_Apply(self->hLimiter, pInterleaveBuffer, pTimeData,
self->extGain, &pcmLimiterScale, 1, pGainPerSample, pcmLimiterScale,
self->extGainDelay, self->streamInfo.frameSize); self->streamInfo.frameSize);
{ {
/* Announce the additional limiter output delay */ /* Announce the additional limiter output delay */
self->streamInfo.outputDelay += pcmLimiter_GetDelay(self->hLimiter); self->streamInfo.outputDelay += pcmLimiter_GetDelay(self->hLimiter);
} }
} else { } 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 /* If numChannels = 1 we do not need interleaving. The same applies if
SBR or MPS are used, since their output is interleaved already SBR or MPS are used, since their output is interleaved already
(resampled or not) */ (resampled or not) */
if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) || if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
(self->mpsEnableCurr)) { (self->mpsEnableCurr)) {
scaleValuesSaturate( scaleValuesSaturate(
pTimeData, pTimeDataPcmPost, pTimeData, pTimeData2,
self->streamInfo.frameSize * self->streamInfo.numChannels, self->streamInfo.frameSize * self->streamInfo.numChannels,
PCM_OUT_HEADROOM); pcmLimiterScale);
} else { } else {
scaleValuesSaturate( scaleValuesSaturate(
(INT_PCM *)self->workBufferCore2, pTimeDataPcmPost, (INT_PCM *)self->workBufferCore2, pTimeData2,
self->streamInfo.frameSize * self->streamInfo.numChannels, self->streamInfo.frameSize * self->streamInfo.numChannels,
PCM_OUT_HEADROOM); pcmLimiterScale);
/* Interleave ouput buffer */ /* Interleave ouput buffer */
FDK_interleave((INT_PCM *)self->workBufferCore2, pTimeData, FDK_interleave((INT_PCM *)self->workBufferCore2, pTimeData,
self->streamInfo.numChannels, self->streamInfo.numChannels,
@ -1981,20 +2025,8 @@ bail:
ErrorStatus = AAC_DEC_UNKNOWN; ErrorStatus = AAC_DEC_UNKNOWN;
} }
/* Check whether external output buffer is large enough. */ if (!IS_OUTPUT_VALID(ErrorStatus)) {
if (timeDataSize_extern < FDKmemclear(pTimeData, timeDataSize * sizeof(*pTimeData));
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));
} }
return ErrorStatus; return ErrorStatus;

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -1015,9 +1015,9 @@ FIXP_DBL get_gain(const FIXP_DBL *x, const FIXP_DBL *y, int n) {
void CBlock_FrequencyToTime( void CBlock_FrequencyToTime(
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[], CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[],
const SHORT frameLen, const int frameOk, FIXP_DBL *pWorkBuffer1, 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; int fr, fl, tl, nSpec;
#if defined(FDK_ASSERT_ENABLE) #if defined(FDK_ASSERT_ENABLE)
@ -1213,6 +1213,7 @@ void CBlock_FrequencyToTime(
bass_pf_1sf_delay(p2_synth, pitch, pit_gain, frameLen, bass_pf_1sf_delay(p2_synth, pitch, pit_gain, frameLen,
(LpdSfd + 2) * L_SUBFR + BPF_SFD * L_SUBFR, (LpdSfd + 2) * L_SUBFR + BPF_SFD * L_SUBFR,
frameLen - (LpdSfd + 4) * L_SUBFR, outSamples, frameLen - (LpdSfd + 4) * L_SUBFR, outSamples,
aacOutDataHeadroom,
pAacDecoderStaticChannelInfo->mem_bpf); pAacDecoderStaticChannelInfo->mem_bpf);
} }
@ -1236,7 +1237,8 @@ void CBlock_FrequencyToTime(
? MLT_FLAG_CURR_ALIAS_SYMMETRY ? MLT_FLAG_CURR_ALIAS_SYMMETRY
: 0); : 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" #include "ldfiltbank.h"
void CBlock_FrequencyToTimeLowDelay( void CBlock_FrequencyToTimeLowDelay(
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[], CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[],
const short frameLen) { const short frameLen) {
InvMdctTransformLowDelay_fdk( InvMdctTransformLowDelay_fdk(
SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient), SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient),

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -218,16 +218,16 @@ void ApplyTools(CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
*/ */
void CBlock_FrequencyToTime( void CBlock_FrequencyToTime(
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[], CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[],
const SHORT frameLen, const int frameOk, FIXP_DBL *pWorkBuffer1, 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. * \brief Transform double lapped MDCT (AAC-ELD) spectral data into time domain.
*/ */
void CBlock_FrequencyToTimeLowDelay( void CBlock_FrequencyToTimeLowDelay(
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[], CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[],
const short frameLen); const short frameLen);
AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData( AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData(

View File

@ -226,7 +226,7 @@ static void CConcealment_ApplyRandomSign(int iRandomPhase, FIXP_DBL *spec,
/* TimeDomainFading */ /* TimeDomainFading */
static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart, 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, static void CConcealment_TDFadeFillFadingStations(FIXP_DBL *fadingStations,
int *fadingSteps, int *fadingSteps,
FIXP_DBL fadeStop, FIXP_DBL fadeStop,
@ -242,7 +242,9 @@ static int CConcealment_ApplyFadeOut(
static int CConcealment_TDNoise_Random(ULONG *seed); static int CConcealment_TDNoise_Random(ULONG *seed);
static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo, 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) { static BLOCK_TYPE CConcealment_GetWinSeq(int prevWinSeq) {
BLOCK_TYPE newWinSeq = BLOCK_LONG; BLOCK_TYPE newWinSeq = BLOCK_LONG;
@ -1844,7 +1846,7 @@ Target fading level is determined by fading index cntFadeFrames.
INT CConcealment_TDFading( INT CConcealment_TDFading(
int len, CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo, 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 Do the fading in Time domain based on concealment states and core mode
*/ */
@ -1957,7 +1959,8 @@ INT CConcealment_TDFading(
start += len; start += len;
} }
} }
CConcealment_TDNoise_Apply(pConcealmentInfo, len, pcmdata); CConcealment_TDNoise_Apply(pConcealmentInfo, len, aacOutDataHeadroom,
pcmdata);
/* Save end-of-frame attenuation and fading type */ /* Save end-of-frame attenuation and fading type */
pConcealmentInfo->lastFadingType = fadingType; pConcealmentInfo->lastFadingType = fadingType;
@ -1969,12 +1972,11 @@ INT CConcealment_TDFading(
/* attenuate pcmdata in Time Domain Fading process */ /* attenuate pcmdata in Time Domain Fading process */
static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart, 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; int i;
FIXP_DBL dStep; FIXP_DBL dStep;
FIXP_DBL dGain; FIXP_DBL dGain;
FIXP_DBL dGain_apply; FIXP_DBL dGain_apply;
int bitshift = (DFRACT_BITS - SAMPLE_BITS);
/* set start energy */ /* set start energy */
dGain = fadeStart; dGain = fadeStart;
@ -1987,7 +1989,7 @@ static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart,
*/ */
dGain_apply = fMax((FIXP_DBL)0, dGain); dGain_apply = fMax((FIXP_DBL)0, dGain);
/* finally, attenuate samples */ /* 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, static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo,
const int len, FIXP_PCM *const pcmdata) { const int len,
FIXP_PCM *states = pConcealmentInfo->TDNoiseStates; const INT aacOutDataHeadroom,
FIXP_PCM noiseVal; PCM_DEC *const pcmdata) {
PCM_DEC *states = pConcealmentInfo->TDNoiseStates;
PCM_DEC noiseVal;
FIXP_DBL noiseValLong; FIXP_DBL noiseValLong;
FIXP_SGL *coef = pConcealmentInfo->TDNoiseCoef; FIXP_SGL *coef = pConcealmentInfo->TDNoiseCoef;
FIXP_DBL TDNoiseAtt; FIXP_DBL TDNoiseAtt;
@ -2070,18 +2074,20 @@ static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo,
/* create filtered noise */ /* create filtered noise */
states[2] = states[1]; states[2] = states[1];
states[1] = states[0]; 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]) + noiseValLong = fMult(states[0], coef[0]) + fMult(states[1], coef[1]) +
fMult(states[2], coef[2]); 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 */ /* add filtered noise - check for clipping, before */
if (noiseVal > (FIXP_PCM)0 && if (noiseVal > (PCM_DEC)0 &&
pcmdata[ii] > (FIXP_PCM)MAXVAL_FIXP_PCM - noiseVal) { pcmdata[ii] > (PCM_DEC)MAXVAL_PCM_DEC - noiseVal) {
noiseVal = noiseVal * (FIXP_PCM)-1; noiseVal = noiseVal * (PCM_DEC)-1;
} else if (noiseVal < (FIXP_PCM)0 && } else if (noiseVal < (PCM_DEC)0 &&
pcmdata[ii] < (FIXP_PCM)MINVAL_FIXP_PCM - noiseVal) { pcmdata[ii] < (PCM_DEC)MINVAL_PCM_DEC - noiseVal) {
noiseVal = noiseVal * (FIXP_PCM)-1; noiseVal = noiseVal * (PCM_DEC)-1;
} }
pcmdata[ii] += noiseVal; pcmdata[ii] += noiseVal;

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -147,6 +147,6 @@ int CConcealment_GetLastFrameOk(CConcealmentInfo *hConcealmentInfo,
INT CConcealment_TDFading( INT CConcealment_TDFading(
int len, CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo, 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 */ #endif /* #ifndef CONCEAL_H */

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -194,7 +194,7 @@ typedef struct {
FIXP_DBL last_tcx_gain; FIXP_DBL last_tcx_gain;
INT last_tcx_gain_e; INT last_tcx_gain_e;
ULONG TDNoiseSeed; ULONG TDNoiseSeed;
FIXP_PCM TDNoiseStates[3]; PCM_DEC TDNoiseStates[3];
FIXP_SGL TDNoiseCoef[3]; FIXP_SGL TDNoiseCoef[3];
FIXP_SGL TDNoiseAtt; FIXP_SGL TDNoiseAtt;

View File

@ -112,17 +112,20 @@ amm-info@iis.fraunhofer.de
#if defined(__arm__) #if defined(__arm__)
#endif #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) { FIXP_DBL *z, const int N) {
int i; int i;
/* scale for FIXP_DBL -> INT_PCM conversion. */ /* scale for FIXP_DBL -> PCM_DEC conversion: */
const int scale = (DFRACT_BITS - SAMPLE_BITS) - LDFB_HEADROOM; const int scale = (DFRACT_BITS - PCM_OUT_BITS) - LDFB_HEADROOM + (3);
#if ((DFRACT_BITS - SAMPLE_BITS - LDFB_HEADROOM) > 0)
#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - 1) > 0)
FIXP_DBL rnd_val_wts0 = (FIXP_DBL)0; FIXP_DBL rnd_val_wts0 = (FIXP_DBL)0;
FIXP_DBL rnd_val_wts1 = (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) if (-WTS0 - 1 + scale)
rnd_val_wts0 = (FIXP_DBL)(1 << (-WTS0 - 1 + scale - 1)); rnd_val_wts0 = (FIXP_DBL)(1 << (-WTS0 - 1 + scale - 1));
#endif
if (-WTS1 - 1 + scale) if (-WTS1 - 1 + scale)
rnd_val_wts1 = (FIXP_DBL)(1 << (-WTS1 - 1 + scale - 1)); rnd_val_wts1 = (FIXP_DBL)(1 << (-WTS1 - 1 + scale - 1));
#endif #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]) + tmp = (fMultDiv2(z[N / 2 + i], fb[N + N / 2 - 1 - i]) +
fMultDiv2(z[i], fb[N + N / 2 + 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((-WTS1 - 1 + scale) >= 0);
FDK_ASSERT(tmp <= ((FIXP_DBL)0x7FFFFFFF - FDK_ASSERT(tmp <= ((FIXP_DBL)0x7FFFFFFF -
rnd_val_wts1)); /* rounding must not cause overflow */ 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); tmp + rnd_val_wts1, -WTS1 - 1 + scale, PCM_OUT_BITS);
#else #else
FDK_ASSERT((WTS1 + 1 - scale) >= 0); FDK_ASSERT((WTS1 + 1 - scale) >= 0);
output[(N * 3 / 4 - 1 - i)] = 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 #endif
z[i] = z0; 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]) + tmp1 = (fMultDiv2(z[N / 2 + i], fb[N + N / 2 - 1 - i]) +
fMultDiv2(z[i], fb[N + N / 2 + 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((-WTS0 - 1 + scale) >= 0);
FDK_ASSERT(tmp0 <= ((FIXP_DBL)0x7FFFFFFF - FDK_ASSERT(tmp0 <= ((FIXP_DBL)0x7FFFFFFF -
rnd_val_wts0)); /* rounding must not cause overflow */ rnd_val_wts0)); /* rounding must not cause overflow */
FDK_ASSERT(tmp1 <= ((FIXP_DBL)0x7FFFFFFF - FDK_ASSERT(tmp1 <= ((FIXP_DBL)0x7FFFFFFF -
rnd_val_wts1)); /* rounding must not cause overflow */ 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); 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); tmp1 + rnd_val_wts1, -WTS1 - 1 + scale, PCM_OUT_BITS);
#else #else
FDK_ASSERT((WTS0 + 1 - scale) >= 0); FDK_ASSERT((WTS0 + 1 - scale) >= 0);
output[(i - N / 4)] = 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)] = 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 #endif
z[i] = z0; z[i] = z0;
z[N + i] = z2; 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++) { for (i = 0; i < N / 4; i++) {
FIXP_DBL tmp0 = fMultDiv2(z[i], fb[N / 2 + 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((-WTS0 - 1 + scale) >= 0);
FDK_ASSERT(tmp0 <= ((FIXP_DBL)0x7FFFFFFF - FDK_ASSERT(tmp0 <= ((FIXP_DBL)0x7FFFFFFF -
rnd_val_wts0)); /* rounding must not cause overflow */ 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); tmp0 + rnd_val_wts0, -WTS0 - 1 + scale, PCM_OUT_BITS);
#else #else
FDK_ASSERT((WTS0 + 1 - scale) >= 0); FDK_ASSERT((WTS0 + 1 - scale) >= 0);
output[(N * 3 / 4 + i)] = 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 #endif
} }
} }
int InvMdctTransformLowDelay_fdk(FIXP_DBL *mdctData, const int mdctData_e, 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 int N) {
const FIXP_WTB *coef; const FIXP_WTB *coef;
FIXP_DBL gain = (FIXP_DBL)0; FIXP_DBL gain = (FIXP_DBL)0;

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -104,9 +104,10 @@ amm-info@iis.fraunhofer.de
#define LDFILTBANK_H #define LDFILTBANK_H
#include "common_fix.h" #include "common_fix.h"
#include "aac_rom.h"
int InvMdctTransformLowDelay_fdk(FIXP_DBL *mdctdata_m, const int mdctdata_e, 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); const int frameLength);
#endif #endif

View File

@ -122,18 +122,21 @@ amm-info@iis.fraunhofer.de
#include "ac_arith_coder.h" #include "ac_arith_coder.h"
void filtLP(const FIXP_DBL *syn, FIXP_PCM *syn_out, FIXP_DBL *noise, void filtLP(const FIXP_DBL *syn, PCM_DEC *syn_out, FIXP_DBL *noise,
const FIXP_SGL *filt, INT stop, int len) { const FIXP_SGL *filt, const INT aacOutDataHeadroom, INT stop,
int len) {
INT i, j; INT i, j;
FIXP_DBL tmp; FIXP_DBL tmp;
FDK_ASSERT((aacOutDataHeadroom - 1) >= -(MDCT_OUTPUT_SCALE));
for (i = 0; i < stop; i++) { for (i = 0; i < stop; i++) {
tmp = fMultDiv2(noise[i], filt[0]); // Filt in Q-1.16 tmp = fMultDiv2(noise[i], filt[0]); // Filt in Q-1.16
for (j = 1; j <= len; j++) { for (j = 1; j <= len; j++) {
tmp += fMult((noise[i - j] >> 1) + (noise[i + j] >> 1), filt[j]); tmp += fMult((noise[i - j] >> 1) + (noise[i + j] >> 1), filt[j]);
} }
syn_out[i] = (FIXP_PCM)(SATURATE_SHIFT( syn_out[i] = (PCM_DEC)(
(syn[i] >> 1) - (tmp >> 1), (MDCT_OUTPUT_SCALE - 1), PCM_OUT_BITS)); IMDCT_SCALE((syn[i] >> 1) - (tmp >> 1), aacOutDataHeadroom - 1));
} }
} }
@ -143,8 +146,10 @@ void bass_pf_1sf_delay(
FIXP_DBL *pit_gain, FIXP_DBL *pit_gain,
const int frame_length, /* (i) : frame length (should be 768|1024) */ const int frame_length, /* (i) : frame length (should be 768|1024) */
const INT l_frame, const INT l_frame,
const INT l_next, /* (i) : look ahead for symmetric filtering */ const INT l_next, /* (i) : look ahead for symmetric filtering */
FIXP_PCM *synth_out, /* (o) : filtered synthesis (with delay of 1 subfr) */ 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] */ FIXP_DBL mem_bpf[]) /* i/o : memory state [L_FILT+L_SUBFR] */
{ {
INT i, sf, i_subfr, T, T2, lg; 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, 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 */ /* Output scaling of the BPF memory */
scaleValues(mem_bpf, (L_FILT + L_SUBFR), -1); scaleValues(mem_bpf, (L_FILT + L_SUBFR), -1);
/* Copy the rest of the signal (after the fac) */ /* Copy the rest of the signal (after the fac) */
scaleValuesSaturate((FIXP_PCM *)&synth_out[l_frame], scaleValuesSaturate(
(FIXP_DBL *)&syn[l_frame - L_SUBFR], (PCM_DEC *)&synth_out[l_frame], (FIXP_DBL *)&syn[l_frame - L_SUBFR],
(frame_length - l_frame), MDCT_OUT_HEADROOM); (frame_length - l_frame), MDCT_OUT_HEADROOM - aacOutDataHeadroom);
} }
return; return;
@ -1552,9 +1557,9 @@ void CLpdChannelStream_Decode(
AAC_DECODER_ERROR CLpd_RenderTimeSignal( AAC_DECODER_ERROR CLpd_RenderTimeSignal(
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM *pTimeData, CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC *pTimeData,
INT lFrame, SamplingRateInfo *pSamplingRateInfo, UINT frameOk, UINT flags, INT lFrame, SamplingRateInfo *pSamplingRateInfo, UINT frameOk,
UINT strmFlags) { const INT aacOutDataHeadroom, UINT flags, UINT strmFlags) {
UCHAR *mod = pAacDecoderChannelInfo->data.usac.mod; UCHAR *mod = pAacDecoderChannelInfo->data.usac.mod;
AAC_DECODER_ERROR error = AAC_DEC_OK; AAC_DECODER_ERROR error = AAC_DEC_OK;
int k, i_offset; 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, bass_pf_1sf_delay(p2_synth, pitch, pit_gain, lFrame, lFrame / facFB,
mod[nbDiv - 1] ? (SynDelay - (lDiv / 2)) : SynDelay, mod[nbDiv - 1] ? (SynDelay - (lDiv / 2)) : SynDelay,
pTimeData, pAacDecoderStaticChannelInfo->mem_bpf); pTimeData, aacOutDataHeadroom,
pAacDecoderStaticChannelInfo->mem_bpf);
} }
} }

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -140,13 +140,14 @@ void CLpdChannelStream_Decode(
* \param pTimeData pointer to output buffer * \param pTimeData pointer to output buffer
* \param samplesPerFrame amount of output samples * \param samplesPerFrame amount of output samples
* \param pSamplingRateInfo holds the sampling rate information * \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( AAC_DECODER_ERROR CLpd_RenderTimeSignal(
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM *pTimeData, CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC *pTimeData,
INT samplesPerFrame, SamplingRateInfo *pSamplingRateInfo, UINT frameOk, 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) { static inline INT CLpd_FAC_getLength(int fNotShortBlock, int fac_length_long) {
if (fNotShortBlock) { 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, void filtLP(const FIXP_DBL *syn, PCM_DEC *syn_out, FIXP_DBL *noise,
const FIXP_SGL *filt, INT stop, int len); const FIXP_SGL *filt, const INT aacOutDataHeadroom, INT stop,
int len);
/** /**
* \brief perform a low-frequency pitch enhancement on time domain signal * \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_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[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[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) * \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, 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 frame_length, const INT l_frame,
const INT l_next, FIXP_PCM *synth_out, const INT l_next, PCM_DEC *synth_out,
FIXP_DBL mem_bpf[]); const INT aacOutDataHeadroom, FIXP_DBL mem_bpf[]);
/** /**
* \brief random sign generator for FD and TCX noise filling * \brief random sign generator for FD and TCX noise filling

View File

@ -160,8 +160,6 @@ H_ALLOC_MEM(QmfSlotsImag32, FIXP_DBL *)
H_ALLOC_MEM(QmfOverlapBuffer16, FIXP_DBL) H_ALLOC_MEM(QmfOverlapBuffer16, FIXP_DBL)
H_ALLOC_MEM(QmfOverlapBuffer32, 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 * Structure to hold the configuration data which is global whithin a QMF domain
* instance. * instance.
@ -181,9 +179,6 @@ typedef struct {
park a channel if only one processing channel is park a channel if only one processing channel is
available. */ available. */
UCHAR parkChannel_requested; UCHAR parkChannel_requested;
QDOM_PCM
*TDinput; /*!< Pointer to time domain data used as input for the QMF
analysis. */
FIXP_DBL * FIXP_DBL *
pWorkBuffer[QMF_MAX_WB_SECTIONS]; /*!< Pointerarray to volatile memory. */ pWorkBuffer[QMF_MAX_WB_SECTIONS]; /*!< Pointerarray to volatile memory. */
UINT flags; /*!< Flags to be set on all QMF analysis/synthesis filter UINT flags; /*!< Flags to be set on all QMF analysis/synthesis filter

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -106,18 +106,16 @@ amm-info@iis.fraunhofer.de
#include "common_fix.h" #include "common_fix.h"
#define MDCT_OUT_HEADROOM 2 /* Output additional headroom */ #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 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 */ /* Refer to "Output word length" in ISO/IEC 14496-3:2008(E) 23.2.3.6 */
#define MDCT_OUTPUT_GAIN 16 #define MDCT_OUTPUT_GAIN 16
#if (MDCT_OUTPUT_SCALE >= 0) #define IMDCT_SCALE(x, s) \
#define IMDCT_SCALE(x) SATURATE_RIGHT_SHIFT(x, MDCT_OUTPUT_SCALE, PCM_OUT_BITS) SATURATE_RIGHT_SHIFT((x), ((s) + 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_DBL(x) (FIXP_DBL)(x) #define IMDCT_SCALE_DBL(x) (FIXP_DBL)(x)
#define IMDCT_SCALE_DBL_LSH1(x) SATURATE_LEFT_SHIFT_ALT((x), 1, DFRACT_BITS) #define IMDCT_SCALE_DBL_LSH1(x) SATURATE_LEFT_SHIFT_ALT((x), 1, DFRACT_BITS)

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -104,7 +104,7 @@ amm-info@iis.fraunhofer.de
/* FDK tools library info */ /* FDK tools library info */
#define FDK_TOOLS_LIB_VL0 3 #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_VL2 0
#define FDK_TOOLS_LIB_TITLE "FDK Tools" #define FDK_TOOLS_LIB_TITLE "FDK Tools"
#ifdef __ANDROID__ #ifdef __ANDROID__

View File

@ -637,10 +637,10 @@ void FDK_QmfDomain_GetSlot(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, const int ts,
if (pQmfOutImag == NULL) { if (pQmfOutImag == NULL) {
for (; b < fMin(lsb, stop_band); b++) { 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++) { 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++) { for (; b < stop_band; b++) {
pQmfOutReal[b] = (FIXP_DBL)0; 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 { } else {
FDK_ASSERT(imag != NULL); FDK_ASSERT(imag != NULL);
for (; b < fMin(lsb, stop_band); b++) { for (; b < fMin(lsb, stop_band); b++) {
pQmfOutReal[b] = scaleValue(real[b], lb_sf); pQmfOutReal[b] = scaleValueSaturate(real[b], lb_sf);
pQmfOutImag[b] = scaleValue(imag[b], lb_sf); pQmfOutImag[b] = scaleValueSaturate(imag[b], lb_sf);
} }
for (; b < fMin(usb, stop_band); b++) { for (; b < fMin(usb, stop_band); b++) {
pQmfOutReal[b] = scaleValue(real[b], hb_sf); pQmfOutReal[b] = scaleValueSaturate(real[b], hb_sf);
pQmfOutImag[b] = scaleValue(imag[b], hb_sf); pQmfOutImag[b] = scaleValueSaturate(imag[b], hb_sf);
} }
for (; b < stop_band; b++) { for (; b < stop_band; b++) {
pQmfOutReal[b] = (FIXP_DBL)0; pQmfOutReal[b] = (FIXP_DBL)0;

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -109,8 +109,6 @@ amm-info@iis.fraunhofer.de
#define TDL_ATTACK_DEFAULT_MS (15) /* default attack time in ms */ #define TDL_ATTACK_DEFAULT_MS (15) /* default attack time in ms */
#define TDL_RELEASE_DEFAULT_MS (50) /* default release 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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -128,10 +126,7 @@ struct TDLimiter {
unsigned int maxBufIdx, delayBufIdx; unsigned int maxBufIdx, delayBufIdx;
FIXP_DBL smoothState0; FIXP_DBL smoothState0;
FIXP_DBL minGain; FIXP_DBL minGain;
INT scaling;
FIXP_DBL additionalGainPrev;
FIXP_DBL additionalGainFilterState;
FIXP_DBL additionalGainFilterState1;
}; };
typedef enum { typedef enum {
@ -255,27 +250,16 @@ TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter,
/****************************************************************************** /******************************************************************************
* pcmLimiter_Apply * * pcmLimiter_Apply *
* limiter: limiter handle * * limiter: limiter handle *
* pGain : pointer to gains to be applied to the signal before limiting, * * samplesIn: pointer to input buffer containing interleaved samples *
* which are downscaled by TDL_GAIN_SCALING bit. * * samplesOut: pointer to output buffer containing interleaved samples *
* These gains are delayed by gain_delay, and smoothed. * * pGainPerSample: pointer to gains for each sample *
* Smoothing is done by a butterworth lowpass filter with a cutoff * * scaling: scaling of output samples *
* frequency which is fixed with respect to the sampling rate. * * nSamples: number of samples per channel *
* 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 *
* returns: error code * * returns: error code *
******************************************************************************/ ******************************************************************************/
TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn, TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
INT_PCM* samplesOut, FIXP_DBL* pGain, INT_PCM* samplesOut, FIXP_DBL* pGainPerSample,
const INT* gain_scale, const UINT gain_size, const INT scaling, const UINT nSamples);
const UINT gain_delay, const UINT nSamples);
#endif /* #ifndef LIMITER_H */ #endif /* #ifndef LIMITER_H */

View File

@ -152,7 +152,7 @@ TDLimiterPtr pcmLimiter_Create(unsigned int maxAttackMs, unsigned int releaseMs,
limiter->attack = attack; limiter->attack = attack;
limiter->attackConst = attackConst; limiter->attackConst = attackConst;
limiter->releaseConst = releaseConst; limiter->releaseConst = releaseConst;
limiter->threshold = threshold >> TDL_GAIN_SCALING; limiter->threshold = threshold;
limiter->channels = maxChannels; limiter->channels = maxChannels;
limiter->maxChannels = maxChannels; limiter->maxChannels = maxChannels;
limiter->sampleRate = maxSampleRate; limiter->sampleRate = maxSampleRate;
@ -165,18 +165,13 @@ TDLimiterPtr pcmLimiter_Create(unsigned int maxAttackMs, unsigned int releaseMs,
/* apply limiter */ /* apply limiter */
TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn, TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
INT_PCM* samplesOut, FIXP_DBL* RESTRICT pGain, INT_PCM* samplesOut, FIXP_DBL* pGainPerSample,
const INT* RESTRICT gain_scale, const INT scaling, const UINT nSamples) {
const UINT gain_size, const UINT gain_delay,
const UINT nSamples) {
unsigned int i, j; unsigned int i, j;
FIXP_DBL tmp1;
FIXP_DBL tmp2; 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)); FIXP_DBL minGain = FL2FXCONST_DBL(1.0f / (1 << 1));
UINT additionalGainAvailable = 1;
FDK_ASSERT(gain_size == 1);
FDK_ASSERT(gain_delay <= nSamples);
if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; 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; unsigned int attack = limiter->attack;
FIXP_DBL attackConst = limiter->attackConst; FIXP_DBL attackConst = limiter->attackConst;
FIXP_DBL releaseConst = limiter->releaseConst; FIXP_DBL releaseConst = limiter->releaseConst;
FIXP_DBL threshold = limiter->threshold; FIXP_DBL threshold = limiter->threshold >> scaling;
FIXP_DBL max = limiter->max; FIXP_DBL max = limiter->max;
FIXP_DBL* maxBuf = limiter->maxBuf; FIXP_DBL* maxBuf = limiter->maxBuf;
@ -195,55 +190,34 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
unsigned int delayBufIdx = limiter->delayBufIdx; unsigned int delayBufIdx = limiter->delayBufIdx;
FIXP_DBL smoothState0 = limiter->smoothState0; FIXP_DBL smoothState0 = limiter->smoothState0;
FIXP_DBL additionalGainSmoothState = limiter->additionalGainFilterState;
FIXP_DBL additionalGainSmoothState1 = limiter->additionalGainFilterState1;
if (!gain_delay) { if (limiter->scaling != scaling) {
additionalGain = pGain[0]; scaleValuesSaturate(delayBuf, attack * channels,
if (gain_scale[0] > 0) { limiter->scaling - scaling);
additionalGain <<= gain_scale[0]; scaleValuesSaturate(maxBuf, attack + 1, limiter->scaling - scaling);
} else { max = scaleValueSaturate(max, limiter->scaling - scaling);
additionalGain >>= -gain_scale[0]; limiter->scaling = scaling;
} }
if (pGainPerSample == NULL) {
additionalGainAvailable = 0;
} }
for (i = 0; i < nSamples; i++) { 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 /* get maximum absolute sample value of all channels, including the
* additional gain. */ * additional gain. */
tmp1 = (FIXP_DBL)0; tmp = (FIXP_DBL)0;
for (j = 0; j < channels; j++) { for (j = 0; j < channels; j++) {
tmp2 = PCM_LIM2FIXP_DBL(samplesIn[j]); tmp2 = PCM_LIM2FIXP_DBL(samplesIn[j]);
tmp2 = tmp2 =
(tmp2 == (FIXP_DBL)MINVAL_DBL) ? (FIXP_DBL)MAXVAL_DBL : fAbs(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 /* set threshold as lower border to save calculations in running maximum
* algorithm */ * algorithm */
@ -314,22 +288,42 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
/* lookahead delay, apply gain */ /* lookahead delay, apply gain */
for (j = 0; j < channels; j++) { for (j = 0; j < channels; j++) {
tmp = p_delayBuf[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 */ /* Apply gain to delayed signal */
tmp = fMultDiv2(tmp, gain); 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( 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; gain >>= 1;
} else { } else {
/* lookahead delay, apply gain=1.0f */ /* lookahead delay, apply gain=1.0f */
for (j = 0; j < channels; j++) { for (j = 0; j < channels; j++) {
tmp = p_delayBuf[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( 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->delayBufIdx = delayBufIdx;
limiter->smoothState0 = smoothState0; limiter->smoothState0 = smoothState0;
limiter->additionalGainFilterState = additionalGainSmoothState;
limiter->additionalGainFilterState1 = additionalGainSmoothState1;
limiter->minGain = minGain; limiter->minGain = minGain;
limiter->additionalGainPrev = pGain[0];
return TDLIMIT_OK; return TDLIMIT_OK;
} }
} }
@ -370,7 +360,7 @@ TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter,
FIXP_DBL threshold) { FIXP_DBL threshold) {
if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; if (limiter == NULL) return TDLIMIT_INVALID_HANDLE;
limiter->threshold = threshold >> TDL_GAIN_SCALING; limiter->threshold = threshold;
return TDLIMIT_OK; return TDLIMIT_OK;
} }
@ -384,13 +374,7 @@ TDLIMITER_ERROR pcmLimiter_Reset(TDLimiterPtr limiter) {
limiter->cor = FL2FXCONST_DBL(1.0f / (1 << 1)); limiter->cor = FL2FXCONST_DBL(1.0f / (1 << 1));
limiter->smoothState0 = FL2FXCONST_DBL(1.0f / (1 << 1)); limiter->smoothState0 = FL2FXCONST_DBL(1.0f / (1 << 1));
limiter->minGain = FL2FXCONST_DBL(1.0f / (1 << 1)); limiter->minGain = FL2FXCONST_DBL(1.0f / (1 << 1));
limiter->scaling = 0;
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));
FDKmemset(limiter->maxBuf, 0, (limiter->attack + 1) * sizeof(FIXP_DBL)); FDKmemset(limiter->maxBuf, 0, (limiter->attack + 1) * sizeof(FIXP_DBL));
FDKmemset(limiter->delayBuf, 0, FDKmemset(limiter->delayBuf, 0,

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -105,7 +105,7 @@ amm-info@iis.fraunhofer.de
/* library info */ /* library info */
#define PCMUTIL_LIB_VL0 3 #define PCMUTIL_LIB_VL0 3
#define PCMUTIL_LIB_VL1 0 #define PCMUTIL_LIB_VL1 1
#define PCMUTIL_LIB_VL2 0 #define PCMUTIL_LIB_VL2 0
#define PCMUTIL_LIB_TITLE "PCM Utility Lib" #define PCMUTIL_LIB_TITLE "PCM Utility Lib"
#ifdef __ANDROID__ #ifdef __ANDROID__

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -252,7 +252,7 @@ typedef enum {
scenario. Default parameter value is 3 frames. */ scenario. Default parameter value is 3 frames. */
} SACDEC_PARAM; } SACDEC_PARAM;
#define PCM_MPS INT_PCM #define PCM_MPS LONG
/** /**
* \brief MPEG Surround decoder handle. * \brief MPEG Surround decoder handle.
@ -401,17 +401,22 @@ int mpegSurroundDecoder_Parse(CMpegSurroundDecoder *pMpegSurroundDecoder,
* for each output audio channel is stored into. * for each output audio channel is stored into.
* \param mapDescr Channep map descriptor for output channel mapping * \param mapDescr Channep map descriptor for output channel mapping
* to be used (From MPEG PCE ordering to whatever is required). * 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. * \return Error code.
*/ */
int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder, int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder,
INT_PCM *input, PCM_MPS *pTimeData, PCM_MPS *input, PCM_MPS *pTimeData,
const int timeDataSize, int timeDataFrameSize, const int timeDataSize, int timeDataFrameSize,
int *nChannels, int *frameSize, int sampleRate, int *nChannels, int *frameSize, int sampleRate,
AUDIO_OBJECT_TYPE coreCodec, AUDIO_OBJECT_TYPE coreCodec,
AUDIO_CHANNEL_TYPE channelType[], AUDIO_CHANNEL_TYPE channelType[],
UCHAR channelIndices[], UCHAR channelIndices[],
const FDK_channelMapDescr *const mapDescr); const FDK_channelMapDescr *const mapDescr,
const INT inDataHeadroom, INT *outDataHeadroom);
/** /**
* \brief Deallocate a MPEG Surround decoder instance. * \brief Deallocate a MPEG Surround decoder instance.

View File

@ -766,7 +766,7 @@ SACDEC_ERROR FDK_SpatialDecInit(spatialDec *self, SPATIAL_BS_FRAME *frame,
/* output scaling */ /* output scaling */
for (nCh = 0; nCh < self->numOutputChannelsAT; nCh++) { 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); FIXP_DBL outputGain_m = getChGain(self, nCh, &outputGain_e);
if (!isTwoChMode(self->upmixType) && !bypassMode) { if (!isTwoChMode(self->upmixType) && !bypassMode) {
@ -775,7 +775,7 @@ SACDEC_ERROR FDK_SpatialDecInit(spatialDec *self, SPATIAL_BS_FRAME *frame,
synthesis qmf */ synthesis qmf */
} }
scale = outputScale; scale += outputScale;
qmfChangeOutScalefactor(&self->pQmfDomain->QmfDomainOut[nCh].fb, scale); qmfChangeOutScalefactor(&self->pQmfDomain->QmfDomainOut[nCh].fb, scale);
qmfChangeOutGain(&self->pQmfDomain->QmfDomainOut[nCh].fb, outputGain_m, qmfChangeOutGain(&self->pQmfDomain->QmfDomainOut[nCh].fb, outputGain_m,
@ -1223,18 +1223,24 @@ static SACDEC_ERROR SpatialDecApplyParameterSets(
!(self->stereoConfigIndex == 3)) { !(self->stereoConfigIndex == 3)) {
for (i = 0; i < self->qmfBands; i++) { for (i = 0; i < self->qmfBands; i++) {
self_qmfResidualReal__FDK_0_0[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->clipProtectGain__FDK);
self_qmfResidualImag__FDK_0_0[i] = 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); self->clipProtectGain__FDK);
} }
} else { } else {
for (i = 0; i < self->qmfBands; i++) { for (i = 0; i < self->qmfBands; i++) {
self_qmfResidualReal__FDK_0_0[i] = fMult( self_qmfResidualReal__FDK_0_0[i] =
self_qmfResidualReal__FDK_0_0[i], self->clipProtectGain__FDK); fMult(scaleValueSaturate(self_qmfResidualReal__FDK_0_0[i],
self_qmfResidualImag__FDK_0_0[i] = fMult( self->sacInDataHeadroom - (1)),
self_qmfResidualImag__FDK_0_0[i], self->clipProtectGain__FDK); 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(self != NULL);
FDK_ASSERT(pControlFlags != NULL); FDK_ASSERT(pControlFlags != NULL);
FDK_ASSERT(pcmOutBuf != NULL); FDK_ASSERT(pcmOutBuf != NULL);
FDK_ASSERT(self->sacInDataHeadroom >= (1));
self->errInt = err; /* Init internal error */ self->errInt = err; /* Init internal error */

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -523,6 +523,9 @@ struct spatialDec_struct {
new frame after SSC change (aka new frame after SSC change (aka
decodeAfterConfigHasChangedFlag). */ decodeAfterConfigHasChangedFlag). */
SpatialDecConcealmentInfo concealInfo; SpatialDecConcealmentInfo concealInfo;
INT sacInDataHeadroom; /* Headroom of the SAC input time signal to prevent
clipping */
}; };
#define SACDEC_SYNTAX_MPS 1 #define SACDEC_SYNTAX_MPS 1

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -249,10 +249,10 @@ typedef struct {
} MEM_REQUIREMENTS; } MEM_REQUIREMENTS;
#define PCM_MPS INT_PCM #define PCM_MPS LONG
#define PCM_MPSF FIXP_PCM #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) */ /* exposed functions (library interface) */

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -1507,15 +1507,17 @@ bail:
} }
int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder, int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder,
INT_PCM *input, PCM_MPS *pTimeData, PCM_MPS *input, PCM_MPS *pTimeData,
const int timeDataSize, int timeDataFrameSize, const int timeDataSize, int timeDataFrameSize,
int *nChannels, int *frameSize, int sampleRate, int *nChannels, int *frameSize, int sampleRate,
AUDIO_OBJECT_TYPE coreCodec, AUDIO_OBJECT_TYPE coreCodec,
AUDIO_CHANNEL_TYPE channelType[], AUDIO_CHANNEL_TYPE channelType[],
UCHAR channelIndices[], UCHAR channelIndices[],
const FDK_channelMapDescr *const mapDescr) { const FDK_channelMapDescr *const mapDescr,
const INT inDataHeadroom, INT *outDataHeadroom) {
SACDEC_ERROR err = MPS_OK; SACDEC_ERROR err = MPS_OK;
PCM_MPS *pTimeOut = pTimeData; PCM_MPS *pTimeOut = pTimeData;
PCM_MPS *TDinput = NULL;
UINT initControlFlags = 0, controlFlags = 0; UINT initControlFlags = 0, controlFlags = 0;
int timeDataRequiredSize = 0; int timeDataRequiredSize = 0;
int newData; int newData;
@ -1534,6 +1536,9 @@ int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder,
return MPS_NOTOK; return MPS_NOTOK;
} }
pMpegSurroundDecoder->pSpatialDec->sacInDataHeadroom = inDataHeadroom;
*outDataHeadroom = (INT)(8);
pMpegSurroundDecoder->pSpatialDec->pConfigCurrent = pMpegSurroundDecoder->pSpatialDec->pConfigCurrent =
&pMpegSurroundDecoder &pMpegSurroundDecoder
->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode]; ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode];
@ -1682,8 +1687,7 @@ int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder,
(timeDataFrameSize * (timeDataFrameSize *
pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsSynthesis) / pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsSynthesis) /
pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis; pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis;
pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput = TDinput = pTimeData + timeDataFrameSizeOut - timeDataFrameSize;
pTimeData + timeDataFrameSizeOut - timeDataFrameSize;
for (int i = *nChannels - 1; i >= 0; i--) { for (int i = *nChannels - 1; i >= 0; i--) {
FDKmemmove(pTimeData + (i + 1) * timeDataFrameSizeOut - timeDataFrameSize, FDKmemmove(pTimeData + (i + 1) * timeDataFrameSizeOut - timeDataFrameSize,
pTimeData + timeDataFrameSize * i, pTimeData + timeDataFrameSize * i,
@ -1694,8 +1698,8 @@ int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder,
} else { } else {
if (pMpegSurroundDecoder->mpegSurroundUseTimeInterface) { if (pMpegSurroundDecoder->mpegSurroundUseTimeInterface) {
FDKmemcpy(input, pTimeData, FDKmemcpy(input, pTimeData,
sizeof(INT_PCM) * (*nChannels) * (*frameSize)); sizeof(PCM_MPS) * (*nChannels) * (*frameSize));
pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput = input; TDinput = input;
} }
} }
@ -1707,8 +1711,8 @@ int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder,
&pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode], &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode],
pMpegSurroundDecoder->mpegSurroundUseTimeInterface ? INPUTMODE_TIME pMpegSurroundDecoder->mpegSurroundUseTimeInterface ? INPUTMODE_TIME
: INPUTMODE_QMF_SBR, : INPUTMODE_QMF_SBR,
pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput, NULL, NULL, TDinput, NULL, NULL, pTimeOut, *frameSize, &controlFlags, *nChannels,
pTimeOut, *frameSize, &controlFlags, *nChannels, mapDescr); mapDescr);
*nChannels = pMpegSurroundDecoder->pSpatialDec->numOutputChannelsAT; *nChannels = pMpegSurroundDecoder->pSpatialDec->numOutputChannelsAT;
if (err != if (err !=
@ -1781,7 +1785,7 @@ void mpegSurroundDecoder_Close(CMpegSurroundDecoder *pMpegSurroundDecoder) {
} }
#define SACDEC_VL0 2 #define SACDEC_VL0 2
#define SACDEC_VL1 0 #define SACDEC_VL1 1
#define SACDEC_VL2 0 #define SACDEC_VL2 0
int mpegSurroundDecoder_GetLibInfo(LIB_INFO *info) { int mpegSurroundDecoder_GetLibInfo(LIB_INFO *info) {

View File

@ -187,8 +187,12 @@ SACDEC_ERROR SpatialDecQMFAnalysis(spatialDec *self, const PCM_MPS *inData,
if (!isTwoChMode(self->upmixType) && !bypassMode) { if (!isTwoChMode(self->upmixType) && !bypassMode) {
int i; int i;
for (i = 0; i < self->qmfBands; i++) { for (i = 0; i < self->qmfBands; i++) {
qmfReal[ch][i] = fMult(qmfReal[ch][i], self->clipProtectGain__FDK); qmfReal[ch][i] = fMult(
qmfImag[ch][i] = fMult(qmfImag[ch][i], self->clipProtectGain__FDK); 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. */ /* Write Input data to pQmfRealAnalysis. */
if (self->bShareDelayWithSBR) { if (self->bShareDelayWithSBR) {
FDK_QmfDomain_GetSlot( FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch],
&self->pQmfDomain->QmfDomainIn[ch], ts + HYBRID_FILTER_DELAY, 0, ts + HYBRID_FILTER_DELAY, 0,
MAX_QMF_BANDS_TO_HYBRID, pQmfRealAnalysis, pQmfImagAnalysis, 15); MAX_QMF_BANDS_TO_HYBRID, pQmfRealAnalysis,
pQmfImagAnalysis, 15 + (1));
FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts,
MAX_QMF_BANDS_TO_HYBRID, self->qmfBands, MAX_QMF_BANDS_TO_HYBRID, self->qmfBands,
pQmfRealAnalysis, pQmfImagAnalysis, 15); pQmfRealAnalysis, pQmfImagAnalysis, 15 + (1));
} else { } else {
FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, 0, FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, 0,
self->qmfBands, pQmfRealAnalysis, self->qmfBands, pQmfRealAnalysis,
pQmfImagAnalysis, 15); pQmfImagAnalysis, 15 + (1));
} }
if (ts == self->pQmfDomain->globalConf.nQmfTimeSlots - 1) { if (ts == self->pQmfDomain->globalConf.nQmfTimeSlots - 1) {
/* Is currently also needed in case we dont have any overlap. We need to /* 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++) { for (pb = 0, qs = 3; pb < 2; pb++) {
INT s; INT s;
FIXP_DBL maxVal; FIXP_DBL maxVal;
FIXP_SGL mReal1; FIXP_DBL mReal1;
FIXP_SGL mReal0, mImag0; FIXP_DBL mReal0, mImag0;
FIXP_DBL iReal0, iImag0, iReal1; FIXP_DBL iReal0, iImag0, iReal1;
iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]); iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]);
@ -515,9 +520,9 @@ SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding(
s = fMax(CntLeadingZeros(maxVal) - 1, 0); s = fMax(CntLeadingZeros(maxVal) - 1, 0);
s = fMin(s, scale_param_m2); s = fMin(s, scale_param_m2);
mReal0 = FX_DBL2FX_SGL(iReal0 << s); mReal0 = iReal0 << s;
mImag0 = FX_DBL2FX_SGL(iImag0 << s); mImag0 = iImag0 << s;
mReal1 = FX_DBL2FX_SGL(iReal1 << s); mReal1 = iReal1 << s;
s = scale_param_m2 - 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->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -=
self->clipProtectGainSF__FDK; self->clipProtectGainSF__FDK;
self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= (1);
} else { } else {
/* Call the QMF synthesis for dry. */ /* Call the QMF synthesis for dry. */
err = CalculateSpaceSynthesisQmf(&self->pQmfDomain->QmfDomainOut[outCh], err = CalculateSpaceSynthesisQmf(&self->pQmfDomain->QmfDomainOut[outCh],

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -110,7 +110,7 @@ amm-info@iis.fraunhofer.de
SACDEC_ERROR CalculateSpaceSynthesisQmf( SACDEC_ERROR CalculateSpaceSynthesisQmf(
const HANDLE_FDK_QMF_DOMAIN_OUT hQmfDomainOutCh, const FIXP_DBL *Sr, 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; SACDEC_ERROR err = MPS_OK;
if (hQmfDomainOutCh == NULL) { if (hQmfDomainOutCh == NULL) {

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -124,7 +124,7 @@ amm-info@iis.fraunhofer.de
*/ */
SACDEC_ERROR CalculateSpaceSynthesisQmf( SACDEC_ERROR CalculateSpaceSynthesisQmf(
const HANDLE_FDK_QMF_DOMAIN_OUT hQmfDomainOutCh, const FIXP_DBL *Sr, 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. * \brief Convert audio input data to qmf representation.

View File

@ -253,17 +253,17 @@ static inline void slotAmp(FIXP_DBL *RESTRICT slotAmp_dry,
dry = wet = FL2FXCONST_DBL(0.0f); dry = wet = FL2FXCONST_DBL(0.0f);
for (qs = 0; qs < cplxBands; qs++) { for (qs = 0; qs < cplxBands; qs++) {
dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs]) + dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs] << (1)) +
fPow2Div2(pHybOutputImagDry[qs])); fPow2Div2(pHybOutputImagDry[qs] << (1)));
wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs]) + wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs] << (1)) +
fPow2Div2(pHybOutputImagWet[qs])); fPow2Div2(pHybOutputImagWet[qs] << (1)));
} }
for (; qs < hybBands; qs++) { for (; qs < hybBands; qs++) {
dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs])); dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs] << (1)));
wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs])); wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs] << (1)));
} }
*slotAmp_dry = dry; *slotAmp_dry = dry >> (2 * (1));
*slotAmp_wet = wet; *slotAmp_wet = wet >> (2 * (1));
} }
#if defined(__aarch64__) #if defined(__aarch64__)
@ -327,7 +327,7 @@ static void extractBBEnv(spatialDec *self, INT inp, INT start, INT channels,
INT shapeActiv = 1; INT shapeActiv = 1;
INT hybBands = fixMin(42, self->hybridBands); INT hybBands = fixMin(42, self->hybridBands);
INT staticScale = self->staticDecScale; INT staticScale = self->staticDecScale + (1);
INT cplxBands; INT cplxBands;
cplxBands = fixMin(42, self->hybridBands); cplxBands = fixMin(42, self->hybridBands);

View File

@ -111,21 +111,12 @@ amm-info@iis.fraunhofer.de
#include "machine_type.h" #include "machine_type.h"
/* Global ROM table data type: */ /* 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 FIXP_CFG FIXP_DBL
#define FX_CFG2FX_DBL #define FX_CFG2FX_DBL
#define FX_CFG2FX_SGL FX_DBL2FX_SGL #define FX_CFG2FX_SGL FX_DBL2FX_SGL
#define CFG(a) FIXP_DBL(a) #define CFG(a) FIXP_DBL(a)
#define FL2FXCONST_CFG FL2FXCONST_DBL #define FL2FXCONST_CFG FL2FXCONST_DBL
#define FX_DBL2FX_CFG(x) ((FIXP_DBL)(x)) #define FX_DBL2FX_CFG(x) ((FIXP_DBL)(x))
#endif
/* others */ /* others */
#define SCALE_INV_ICC (2) #define SCALE_INV_ICC (2)
@ -133,15 +124,9 @@ amm-info@iis.fraunhofer.de
#define QCC_SCALE 1 #define QCC_SCALE 1
#define M1M2_DATA FIXP_DBL #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_CDATA FIXP_DBL
#define M1M2_CDATA2FX_DBL(a) (a) #define M1M2_CDATA2FX_DBL(a) (a)
#define FX_DBL2M1M2_CDATA(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_0(x) FL2FXCONST_CFG(((x) / (float)(1 << 0)))
#define CLIP_PROTECT_GAIN_1(x) FL2FXCONST_CFG(((x) / (float)(1 << 1))) #define CLIP_PROTECT_GAIN_1(x) FL2FXCONST_CFG(((x) / (float)(1 << 1)))

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 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). * error (0: core decoder found errors, 1: no errors).
* \param psDecoded Pointer to a buffer holding a flag. Input: PS is * \param psDecoded Pointer to a buffer holding a flag. Input: PS is
* possible, Output: PS has been rendered. * 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. * \return Error code.
*/ */
SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, INT_PCM *input, SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, LONG *input, LONG *timeData,
INT_PCM *timeData, const int timeDataSize, const int timeDataSize, int *numChannels,
int *numChannels, int *sampleRate, int *sampleRate,
const FDK_channelMapDescr *const mapDescr, const FDK_channelMapDescr *const mapDescr,
const int mapIdx, const int coreDecodedOk, const int mapIdx, const int coreDecodedOk,
UCHAR *psDecoded); UCHAR *psDecoded, const INT inDataHeadroom,
INT *outDataHeadroom);
/** /**
* \brief Close SBR decoder instance and free memory. * \brief Close SBR decoder instance and free memory.

View File

@ -897,10 +897,10 @@ void sbrDecoder_calculateGainVec(FIXP_DBL **sourceBufferReal,
for (i = startSample; i < stopSample; i++) { for (i = startSample; i < stopSample; i++) {
maxVal |= maxVal |=
(FIXP_DBL)((LONG)(sourceBufferReal[i][loBand]) ^ (FIXP_DBL)((LONG)(sourceBufferReal[i][loBand]) ^
((LONG)sourceBufferReal[i][loBand] >> (SAMPLE_BITS - 1))); ((LONG)sourceBufferReal[i][loBand] >> (DFRACT_BITS - 1)));
maxVal |= maxVal |=
(FIXP_DBL)((LONG)(sourceBufferImag[i][loBand]) ^ (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)) { if (maxVal != FL2FX_DBL(0.0f)) {

View File

@ -957,7 +957,7 @@ QmfTransposerCreate(HANDLE_HBE_TRANSPOSER* hQmfTransposer, const int frameSize,
hQmfTran->qmfOutBufSize = 2 * (hQmfTran->noCols / 2 + QMF_WIN_LEN - 1); hQmfTran->qmfOutBufSize = 2 * (hQmfTran->noCols / 2 + QMF_WIN_LEN - 1);
hQmfTran->inBuf_F = 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 /* buffered time signal needs to be delayed by synthesis_size; max
* synthesis_size = 20; */ * synthesis_size = 20; */
if (hQmfTran->inBuf_F == NULL) { if (hQmfTran->inBuf_F == NULL) {

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -132,6 +132,9 @@ typedef enum {
} KEEP_STATES_SYNCED_MODE; } KEEP_STATES_SYNCED_MODE;
struct hbeTransposer { 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 xOverQmf[MAX_NUM_PATCHES_HBE];
int maxStretch; int maxStretch;
@ -144,7 +147,7 @@ struct hbeTransposer {
int stopBand; int stopBand;
int bSbr41; int bSbr41;
INT_PCM *inBuf_F; LONG *inBuf_F;
FIXP_DBL **qmfInBufReal_F; FIXP_DBL **qmfInBufReal_F;
FIXP_DBL **qmfInBufImag_F; FIXP_DBL **qmfInBufImag_F;
@ -156,9 +159,6 @@ struct hbeTransposer {
FIXP_DBL const *synthesisQmfPreModCos_F; FIXP_DBL const *synthesisQmfPreModCos_F;
FIXP_DBL const *synthesisQmfPreModSin_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 **qmfHBEBufReal_F;
FIXP_DBL **qmfHBEBufImag_F; FIXP_DBL **qmfHBEBufImag_F;

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -259,17 +259,18 @@ static void copyHarmonicSpectrum(int *xOverQmf, FIXP_DBL **qmfReal,
void sbr_dec( void sbr_dec(
HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
INT_PCM *timeIn, /*!< pointer to input time signal */ LONG *timeIn, /*!< pointer to input time signal */
INT_PCM *timeOut, /*!< pointer to output time signal */ LONG *timeOut, /*!< pointer to output time signal */
HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ 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 */ const int strideOut, /*!< Time data traversal strideOut */
HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */
HANDLE_SBR_PREV_FRAME_DATA HANDLE_SBR_PREV_FRAME_DATA
hPrevFrameData, /*!< Some control data of last frame */ hPrevFrameData, /*!< Some control data of last frame */
const int applyProcessing, /*!< Flag for SBR operation */ 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 i, slot, reserve;
int saveLbScale; int saveLbScale;
int lastSlotOffs; int lastSlotOffs;
@ -278,7 +279,7 @@ void sbr_dec(
/* temporary pointer / variable for QMF; /* temporary pointer / variable for QMF;
required as we want to use temporary buffer required as we want to use temporary buffer
creating one frame delay for HBE in LP mode */ creating one frame delay for HBE in LP mode */
INT_PCM *pTimeInQmf = timeIn; LONG *pTimeInQmf = timeIn;
/* Number of QMF timeslots in the overlap buffer: */ /* Number of QMF timeslots in the overlap buffer: */
int ov_len = hSbrDec->LppTrans.pSettings->overlap; int ov_len = hSbrDec->LppTrans.pSettings->overlap;
@ -341,8 +342,8 @@ void sbr_dec(
} else { } else {
C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2 * (64)); C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2 * (64));
qmfAnalysisFiltering(&hSbrDec->qmfDomainInCh->fb, pReal, pImag, qmfAnalysisFiltering(&hSbrDec->qmfDomainInCh->fb, pReal, pImag,
&hSbrDec->qmfDomainInCh->scaling, pTimeInQmf, 0, 1, &hSbrDec->qmfDomainInCh->scaling, pTimeInQmf,
qmfTemp); 0 + sbrInDataHeadroom, 1, qmfTemp);
C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2 * (64)); C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2 * (64));
} }
@ -658,7 +659,7 @@ void sbr_dec(
if (!(flags & SBRDEC_PS_DECODED)) { if (!(flags & SBRDEC_PS_DECODED)) {
if (!(flags & SBRDEC_SKIP_QMF_SYN)) { if (!(flags & SBRDEC_SKIP_QMF_SYN)) {
int outScalefactor = 0; int outScalefactor = -(8);
if (h_ps_d != NULL) { if (h_ps_d != NULL) {
h_ps_d->procFrameBased = 1; /* we here do frame based processing */ h_ps_d->procFrameBased = 1; /* we here do frame based processing */
@ -743,6 +744,7 @@ void sbr_dec(
*/ */
FDK_ASSERT(hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis <= FDK_ASSERT(hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis <=
QMF_MAX_SYNTHESIS_BANDS); QMF_MAX_SYNTHESIS_BANDS);
qmfChangeOutScalefactor(synQmfRight, -(8));
FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates, FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates,
9 * hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis * 9 * hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis *
sizeof(FIXP_QSS)); sizeof(FIXP_QSS));
@ -814,7 +816,8 @@ void sbr_dec(
: scaleFactorLowBand_no_ov, : scaleFactorLowBand_no_ov,
scaleFactorHighBand, synQmf->lsb, synQmf->usb); scaleFactorHighBand, synQmf->lsb, synQmf->usb);
outScalefactorL = outScalefactorR = 1; /* psDiffScale! (MPEG-PS) */ outScalefactorL = outScalefactorR =
1 + sbrInDataHeadroom; /* psDiffScale! (MPEG-PS) */
} }
sbrDecoder_drcApplySlot(/* right channel */ sbrDecoder_drcApplySlot(/* right channel */
@ -831,6 +834,9 @@ void sbr_dec(
outScalefactorL += maxShift; outScalefactorL += maxShift;
if (!(flags & SBRDEC_SKIP_QMF_SYN)) { if (!(flags & SBRDEC_SKIP_QMF_SYN)) {
qmfChangeOutScalefactor(synQmf, -(8));
qmfChangeOutScalefactor(synQmfRight, -(8));
qmfSynthesisFilteringSlot( qmfSynthesisFilteringSlot(
synQmfRight, rQmfReal, /* QMF real buffer */ synQmfRight, rQmfReal, /* QMF real buffer */
rQmfImag, /* QMF imag buffer */ rQmfImag, /* QMF imag buffer */

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -176,17 +176,18 @@ typedef SBR_CHANNEL *HANDLE_SBR_CHANNEL;
void sbr_dec( void sbr_dec(
HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
INT_PCM *timeIn, /*!< pointer to input time signal */ LONG *timeIn, /*!< pointer to input time signal */
INT_PCM *timeOut, /*!< pointer to output time signal */ LONG *timeOut, /*!< pointer to output time signal */
HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ 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 */ INT strideOut, /*!< Time data traversal strideOut */
HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */
HANDLE_SBR_PREV_FRAME_DATA HANDLE_SBR_PREV_FRAME_DATA
hPrevFrameData, /*!< Some control data of last frame */ hPrevFrameData, /*!< Some control data of last frame */
const int applyProcessing, /*!< Flag for SBR operation */ 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 SBR_ERROR
createSbrDec(SBR_CHANNEL *hSbrChannel, HANDLE_SBR_HEADER_DATA hHeaderData, createSbrDec(SBR_CHANNEL *hSbrChannel, HANDLE_SBR_HEADER_DATA hHeaderData,

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android 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. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -170,6 +170,9 @@ struct SBR_DECODER_INSTANCE {
flushed consecutively. */ flushed consecutively. */
UINT flags; UINT flags;
INT sbrInDataHeadroom; /* Headroom of the SBR input time signal to prevent
clipping */
}; };
H_ALLOC_MEM(Ram_SbrDecElement, SBR_DECODER_ELEMENT) H_ALLOC_MEM(Ram_SbrDecElement, SBR_DECODER_ELEMENT)

View File

@ -155,7 +155,7 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */ /* Decoder library info */
#define SBRDECODER_LIB_VL0 3 #define SBRDECODER_LIB_VL0 3
#define SBRDECODER_LIB_VL1 0 #define SBRDECODER_LIB_VL1 1
#define SBRDECODER_LIB_VL2 0 #define SBRDECODER_LIB_VL2 0
#define SBRDECODER_LIB_TITLE "SBR Decoder" #define SBRDECODER_LIB_TITLE "SBR Decoder"
#ifdef __ANDROID__ #ifdef __ANDROID__
@ -1570,10 +1570,10 @@ bail:
* \return SBRDEC_OK if successfull, else error code * \return SBRDEC_OK if successfull, else error code
*/ */
static SBR_ERROR sbrDecoder_DecodeElement( static SBR_ERROR sbrDecoder_DecodeElement(
HANDLE_SBRDECODER self, QDOM_PCM *input, INT_PCM *timeData, HANDLE_SBRDECODER self, LONG *input, LONG *timeData, const int timeDataSize,
const int timeDataSize, const FDK_channelMapDescr *const mapDescr, const FDK_channelMapDescr *const mapDescr, const int mapIdx,
const int mapIdx, int channelIndex, const int elementIndex, int channelIndex, const int elementIndex, const int numInChannels,
const int numInChannels, int *numOutChannels, const int psPossible) { int *numOutChannels, const int psPossible) {
SBR_DECODER_ELEMENT *hSbrElement = self->pSbrElement[elementIndex]; SBR_DECODER_ELEMENT *hSbrElement = self->pSbrElement[elementIndex];
HANDLE_SBR_CHANNEL *pSbrChannel = HANDLE_SBR_CHANNEL *pSbrChannel =
self->pSbrElement[elementIndex]->pSbrChannel; self->pSbrElement[elementIndex]->pSbrChannel;
@ -1743,7 +1743,7 @@ static SBR_ERROR sbrDecoder_DecodeElement(
timeData + offset1, strideOut, hSbrHeader, hFrameDataLeft, timeData + offset1, strideOut, hSbrHeader, hFrameDataLeft,
&pSbrChannel[0]->prevFrameData, &pSbrChannel[0]->prevFrameData,
(hSbrHeader->syncState == SBR_ACTIVE), h_ps_d, self->flags, (hSbrHeader->syncState == SBR_ACTIVE), h_ps_d, self->flags,
codecFrameSize); codecFrameSize, self->sbrInDataHeadroom);
if (stereo) { if (stereo) {
/* Process right channel */ /* Process right channel */
@ -1751,7 +1751,7 @@ static SBR_ERROR sbrDecoder_DecodeElement(
timeData + offset1, NULL, NULL, strideOut, hSbrHeader, timeData + offset1, NULL, NULL, strideOut, hSbrHeader,
hFrameDataRight, &pSbrChannel[1]->prevFrameData, hFrameDataRight, &pSbrChannel[1]->prevFrameData,
(hSbrHeader->syncState == SBR_ACTIVE), NULL, self->flags, (hSbrHeader->syncState == SBR_ACTIVE), NULL, self->flags,
codecFrameSize); codecFrameSize, self->sbrInDataHeadroom);
} }
C_ALLOC_SCRATCH_END(pPsScratch, struct PS_DEC_COEFFICIENTS, 1) C_ALLOC_SCRATCH_END(pPsScratch, struct PS_DEC_COEFFICIENTS, 1)
@ -1771,14 +1771,14 @@ static SBR_ERROR sbrDecoder_DecodeElement(
int copyFrameSize = int copyFrameSize =
codecFrameSize * self->pQmfDomain->QmfDomainOut->fb.no_channels; codecFrameSize * self->pQmfDomain->QmfDomainOut->fb.no_channels;
copyFrameSize /= self->pQmfDomain->QmfDomainIn->fb.no_channels; copyFrameSize /= self->pQmfDomain->QmfDomainIn->fb.no_channels;
INT_PCM *ptr; LONG *ptr;
INT i; INT i;
FDK_ASSERT(strideOut == 2); FDK_ASSERT(strideOut == 2);
ptr = timeData; ptr = timeData;
for (i = copyFrameSize >> 1; i--;) { for (i = copyFrameSize >> 1; i--;) {
INT_PCM tmp; /* This temporal variable is required because some LONG tmp; /* This temporal variable is required because some compilers
compilers can't do *ptr++ = *ptr++ correctly. */ can't do *ptr++ = *ptr++ correctly. */
tmp = *ptr++; tmp = *ptr++;
*ptr++ = tmp; *ptr++ = tmp;
tmp = *ptr++; tmp = *ptr++;
@ -1791,12 +1791,13 @@ static SBR_ERROR sbrDecoder_DecodeElement(
return errorStatus; return errorStatus;
} }
SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, INT_PCM *input, SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, LONG *input, LONG *timeData,
INT_PCM *timeData, const int timeDataSize, const int timeDataSize, int *numChannels,
int *numChannels, int *sampleRate, int *sampleRate,
const FDK_channelMapDescr *const mapDescr, const FDK_channelMapDescr *const mapDescr,
const int mapIdx, const int coreDecodedOk, const int mapIdx, const int coreDecodedOk,
UCHAR *psDecoded) { UCHAR *psDecoded, const INT inDataHeadroom,
INT *outDataHeadroom) {
SBR_ERROR errorStatus = SBRDEC_OK; SBR_ERROR errorStatus = SBRDEC_OK;
int psPossible; int psPossible;
@ -1833,6 +1834,9 @@ SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, INT_PCM *input,
psPossible = 0; psPossible = 0;
} }
self->sbrInDataHeadroom = inDataHeadroom;
*outDataHeadroom = (INT)(8);
/* Make sure that even if no SBR data was found/parsed *psDecoded is returned /* Make sure that even if no SBR data was found/parsed *psDecoded is returned
* 1 if psPossible was 0. */ * 1 if psPossible was 0. */
if (psPossible == 0) { if (psPossible == 0) {