From 31f66f6d3ffcfa429c170b2c35250982d11f5082 Mon Sep 17 00:00:00 2001 From: Fraunhofer IIS FDK Date: Thu, 19 Dec 2019 17:21:07 +0100 Subject: Extend decoder API with audio output loudness info (FDKdec v3.1.3). Bug: 148385721 Test: atest DecoderTestXheAac DecoderTestAacDrc Change-Id: I68b09883def21baef259c9ab914922567ab8cee3 --- documentation/aacDecoder.pdf | Bin 488412 -> 494126 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'documentation/aacDecoder.pdf') diff --git a/documentation/aacDecoder.pdf b/documentation/aacDecoder.pdf index eb2a75e..f2131ed 100644 Binary files a/documentation/aacDecoder.pdf and b/documentation/aacDecoder.pdf differ -- cgit v1.2.3 From 1d451971ca16a2ba3655dec3d23115b0a240a8bb Mon Sep 17 00:00:00 2001 From: Fraunhofer IIS FDK Date: Thu, 19 Dec 2019 17:21:57 +0100 Subject: Revise and straighten out useless references from decoder documentation. Bug: 149481606 Test: doc update in header, so just make Change-Id: I656e76762ee336931d4f1938e5c39c8ad7f65954 --- documentation/aacDecoder.pdf | Bin 494126 -> 490978 bytes libAACdec/include/aacdecoder_lib.h | 116 ++++++++++++++----------------------- 2 files changed, 44 insertions(+), 72 deletions(-) (limited to 'documentation/aacDecoder.pdf') diff --git a/documentation/aacDecoder.pdf b/documentation/aacDecoder.pdf index f2131ed..d04a7d6 100644 Binary files a/documentation/aacDecoder.pdf and b/documentation/aacDecoder.pdf differ diff --git a/libAACdec/include/aacdecoder_lib.h b/libAACdec/include/aacdecoder_lib.h index 6084bd3..56f4ec1 100644 --- a/libAACdec/include/aacdecoder_lib.h +++ b/libAACdec/include/aacdecoder_lib.h @@ -164,9 +164,6 @@ The contents of each file is described in detail in this document. All header files are provided for usage in specific C/C++ programs. The main AAC decoder library API functions are located in aacdecoder_lib.h header file. -In binary releases the decoder core resides in statically linkable libraries, -for example libAACdec.a. - \section Calling_Sequence Calling Sequence @@ -174,19 +171,7 @@ The following sequence is necessary for proper decoding of ISO/MPEG-2/4 AAC, HE-AAC v2, or MPEG-D USAC bitstreams. In the following description, input stream read and output write function details are left out, since they may be implemented in a variety of configurations depending on the user's specific -requirements. The example implementation uses file-based input/output, and in -such case one may call mpegFileRead_Open() to open an input file and to allocate -memory for the required structures, and the corresponding mpegFileRead_Close() -to close opened files and to de-allocate associated structures. -mpegFileRead_Open() will attempt to detect the bitstream format and in case of -MPEG-4 file format or Raw Packets file format (a proprietary Fraunhofer IIS file -format suitable only for testing) it will read the Audio Specific Config data -(ASC). An unsuccessful attempt to recognize the bitstream format requires the -user to provide this information manually. For any other bitstream formats that -are usually applicable in streaming applications, the decoder itself will try to -synchronize and parse the given bitstream fragment using the FDK transport -library. Hence, for streaming applications (without file access) this step is -not necessary. +requirements. -# Call aacDecoder_Open() to open and retrieve a handle to a new AAC decoder @@ -205,19 +190,17 @@ do { working memory (a client-supplied input buffer "inBuffer" in framework). This buffer will be used to load AAC bitstream data to the decoder. Only when all data in this buffer has been processed will the decoder signal an empty buffer. -For file-based input, you may invoke mpegFileRead_Read() to acquire new -bitstream data. -# Call aacDecoder_Fill() to fill the decoder's internal bitstream input buffer with the client-supplied bitstream input buffer. Note, if the data loaded in to the internal buffer is not sufficient to decode a frame, aacDecoder_DecodeFrame() will return ::AAC_DEC_NOT_ENOUGH_BITS until a sufficient amount of data is loaded in to the internal buffer. For streaming formats (ADTS, LOAS), it is acceptable to load more than one frame to the -decoder. However, for RAW file format (Fraunhofer IIS proprietary format), only -one frame may be loaded to the decoder per aacDecoder_DecodeFrame() call. For -least amount of communication delay, fill and decode should be performed on a -frame by frame basis. \code ErrorStatus = aacDecoder_Fill(aacDecoderInfo, -inBuffer, bytesRead, bytesValid); \endcode +decoder. However, for packed based formats, only one frame may be loaded to the +decoder per aacDecoder_DecodeFrame() call. For least amount of communication +delay, fill and decode should be performed on a frame by frame basis. \code + ErrorStatus = aacDecoder_Fill(aacDecoderInfo, inBuffer, bytesRead, +bytesValid); \endcode -# Call aacDecoder_DecodeFrame(). This function decodes one frame and writes decoded PCM audio data to a client-supplied buffer. It is the client's responsibility to allocate a buffer which is large enough to hold the decoded @@ -225,12 +208,9 @@ output data. \code ErrorStatus = aacDecoder_DecodeFrame(aacDecoderInfo, TimeData, OUT_BUF_SIZE, flags); \endcode If the bitstream configuration (number of channels, sample rate, frame size) is not known a priori, you may call aacDecoder_GetStreamInfo() to retrieve a structure that contains this -information. You may use this data to initialize an audio output device. In the -example program, if the number of channels or the sample rate has changed since -program start or the previously decoded frame, the audio output device is then -re-initialized. If WAVE file output is chosen, a new WAVE file for each new -stream configuration is be created. \code p_si = -aacDecoder_GetStreamInfo(aacDecoderInfo); \endcode +information. You may use this data to initialize an audio output device. \code + p_si = aacDecoder_GetStreamInfo(aacDecoderInfo); +\endcode -# Repeat steps 5 to 7 until no data is available to decode any more, or in case of error. \code } while (bytesRead[0] > 0 || doFlush || doBsFlush || forceContinue); \endcode @@ -239,7 +219,7 @@ structures. \code aacDecoder_Close(aacDecoderInfo); \endcode \image latex decode.png "Decode calling sequence" width=11cm -\image latex change_source.png "Change data source sequence" width 5cm +\image latex change_source.png "Change data source sequence" width=5cm \image latex conceal.png "Error concealment sequence" width=14cm @@ -296,16 +276,14 @@ input buffer, and one to hold the decoded output PCM sample data. In resource limited applications, the output buffer may be reused as an external input buffer prior to the subsequence aacDecoder_Fill() function call. -The external input buffer is set in the example program and its size is defined -by ::IN_BUF_SIZE. You may freely choose different buffer sizes. To feed the data -to the decoder-internal input buffer, use the function aacDecoder_Fill(). This -function returns important information regarding the number of bytes in the -external input buffer that have not yet been copied into the internal input -buffer (variable bytesValid). Once the external buffer has been fully copied, it -can be completely re-filled again. In case you wish to refill the buffer while -there are unprocessed bytes (bytesValid is unequal 0), you should preserve the -unconsumed data. However, we recommend to refill the buffer only when bytesValid -returns 0. +To feed the data to the decoder-internal input buffer, use the +function aacDecoder_Fill(). This function returns important information +regarding the number of bytes in the external input buffer that have not yet +been copied into the internal input buffer (variable bytesValid). Once the +external buffer has been fully copied, it can be completely re-filled again. In +case you wish to refill the buffer while there are unprocessed bytes (bytesValid +is unequal 0), you should preserve the unconsumed data. However, we recommend to +refill the buffer only when bytesValid returns 0. The bytesValid parameter is an input and output parameter to the FDK decoder. As an input, it signals how many valid bytes are available in the external buffer. @@ -340,10 +318,7 @@ explanation, please refer to ISO/IEC 13818-7:2005(E), chapter 8.5.3.2. In case a Program Config is included in the audio configuration, the channel mapping described within it will be adopted. -In case of MPEG-D Surround the channel mapping will follow the same criteria -described in ISO/IEC 13818-7:2005(E), but adding corresponding top channels (if -available) to the channel types in order to avoid ambiguity. The examples below -explain these aspects in detail. +The examples below explain these aspects in detail. \section OutputFormatChange Changing the audio output format @@ -689,9 +664,7 @@ typedef enum { 2. If the parameter value is greater than that of ::AAC_PCM_MAX_OUTPUT_CHANNELS both will be set to the same value. \n - 3. This parameter does not affect MPEG Surround processing. - \n - 4. This parameter will be ignored if the number of encoded + 3. This parameter will be ignored if the number of encoded audio channels is greater than 8. */ AAC_PCM_MAX_OUTPUT_CHANNELS = 0x0012, /*!< Maximum number of PCM output channels. If lower than the @@ -718,11 +691,7 @@ typedef enum { 2. If the parameter value is greater than zero but smaller than ::AAC_PCM_MIN_OUTPUT_CHANNELS both will be set to same value. \n - 3. The operating mode of the MPEG Surround module will be - set accordingly. \n - 4. Setting this parameter with any value will disable the - binaural processing of the MPEG Surround module - 5. This parameter will be ignored if the number of encoded + 3. This parameter will be ignored if the number of encoded audio channels is greater than 8. */ AAC_METADATA_PROFILE = 0x0020, /*!< See ::AAC_MD_PROFILE for all available values. */ @@ -803,11 +772,11 @@ typedef enum { sequences for fading in and out, if provided in the bitstream.\n Enabled album mode makes use of dedicated album loudness information, if provided in the bitstream.\n */ - AAC_QMF_LOWPOWER = 0x0300, /*!< Quadrature Mirror Filter (QMF) Bank processing - mode. \n -1: Use internal default. Implies MPEG - Surround partially complex accordingly. \n 0: - Use complex QMF data mode. \n 1: Use real (low - power) QMF data mode. \n */ + AAC_QMF_LOWPOWER = + 0x0300, /*!< Quadrature Mirror Filter (QMF) Bank processing mode. \n + -1: Use internal default. \n + 0: Use complex QMF data mode. \n + 1: Use real (low power) QMF data mode. \n */ AAC_TPDEC_CLEAR_BUFFER = 0x0603 /*!< Clear internal bit stream buffer of transport layers. The decoder will start decoding at new data passed after this event @@ -1038,21 +1007,24 @@ LINKSPEC_H AAC_DECODER_ERROR aacDecoder_Fill(HANDLE_AACDECODER self, const UINT bufferSize[], UINT *bytesValid); -#define AACDEC_CONCEAL \ - 1 /*!< Flag for aacDecoder_DecodeFrame(): Trigger the built-in error \ - concealment module to generate a substitute signal for one lost frame. \ - New input data will not be considered. */ -#define AACDEC_FLUSH \ - 2 /*!< Flag for aacDecoder_DecodeFrame(): Flush all filterbanks to get all \ - delayed audio without having new input data. Thus new input data will \ - not be considered.*/ -#define AACDEC_INTR \ - 4 /*!< Flag for aacDecoder_DecodeFrame(): Signal an input bit stream data \ - discontinuity. Resync any internals as necessary. */ -#define AACDEC_CLRHIST \ - 8 /*!< Flag for aacDecoder_DecodeFrame(): Clear all signal delay lines and \ - history buffers. CAUTION: This can cause discontinuities in the output \ - signal. */ +/** Flag for aacDecoder_DecodeFrame(): Trigger the built-in error concealment + * module to generate a substitute signal for one lost frame. New input data + * will not be considered. + */ +#define AACDEC_CONCEAL 1 +/** Flag for aacDecoder_DecodeFrame(): Flush all filterbanks to get all delayed + * audio without having new input data. Thus new input data will not be + * considered. + */ +#define AACDEC_FLUSH 2 +/** Flag for aacDecoder_DecodeFrame(): Signal an input bit stream data + * discontinuity. Resync any internals as necessary. + */ +#define AACDEC_INTR 4 +/** Flag for aacDecoder_DecodeFrame(): Clear all signal delay lines and history + * buffers. CAUTION: This can cause discontinuities in the output signal. + */ +#define AACDEC_CLRHIST 8 /** * \brief Decode one audio frame -- cgit v1.2.3 From e016635f0d3a5c7532b00711ce461f97a13f7bc2 Mon Sep 17 00:00:00 2001 From: Fraunhofer IIS FDK Date: Thu, 19 Dec 2019 17:28:15 +0100 Subject: 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 --- documentation/aacDecoder.pdf | Bin 490978 -> 490978 bytes libAACdec/src/FDK_delay.cpp | 26 ++--- libAACdec/src/FDK_delay.h | 6 +- libAACdec/src/aac_rom.h | 3 +- libAACdec/src/aacdecoder.cpp | 49 ++++---- libAACdec/src/aacdecoder.h | 11 +- libAACdec/src/aacdecoder_lib.cpp | 232 +++++++++++++++++++++---------------- libAACdec/src/block.cpp | 12 +- libAACdec/src/block.h | 8 +- libAACdec/src/conceal.cpp | 42 ++++--- libAACdec/src/conceal.h | 4 +- libAACdec/src/conceal_types.h | 4 +- libAACdec/src/ldfiltbank.cpp | 35 +++--- libAACdec/src/ldfiltbank.h | 5 +- libAACdec/src/usacdec_lpd.cpp | 34 +++--- libAACdec/src/usacdec_lpd.h | 19 +-- libFDK/include/FDK_qmf_domain.h | 5 - libFDK/include/mdct.h | 14 +-- libFDK/src/FDK_core.cpp | 4 +- libFDK/src/FDK_qmf_domain.cpp | 12 +- libPCMutils/include/limiter.h | 36 ++---- libPCMutils/src/limiter.cpp | 116 ++++++++----------- libPCMutils/src/version.h | 4 +- libSACdec/include/sac_dec_lib.h | 13 ++- libSACdec/src/sac_dec.cpp | 23 ++-- libSACdec/src/sac_dec.h | 5 +- libSACdec/src/sac_dec_interface.h | 8 +- libSACdec/src/sac_dec_lib.cpp | 24 ++-- libSACdec/src/sac_process.cpp | 30 +++-- libSACdec/src/sac_qmf.cpp | 4 +- libSACdec/src/sac_qmf.h | 4 +- libSACdec/src/sac_reshapeBBEnv.cpp | 18 +-- libSACdec/src/sac_rom.h | 15 --- libSBRdec/include/sbrdecoder.h | 15 ++- libSBRdec/src/HFgen_preFlat.cpp | 4 +- libSBRdec/src/hbe.cpp | 2 +- libSBRdec/src/hbe.h | 10 +- libSBRdec/src/sbr_dec.cpp | 26 +++-- libSBRdec/src/sbr_dec.h | 11 +- libSBRdec/src/sbr_ram.h | 5 +- libSBRdec/src/sbrdecoder.cpp | 32 ++--- 41 files changed, 488 insertions(+), 442 deletions(-) (limited to 'documentation/aacDecoder.pdf') diff --git a/documentation/aacDecoder.pdf b/documentation/aacDecoder.pdf index d04a7d6..cc7cf41 100644 Binary files a/documentation/aacDecoder.pdf and b/documentation/aacDecoder.pdf differ diff --git a/libAACdec/src/FDK_delay.cpp b/libAACdec/src/FDK_delay.cpp index 0ab1a66..0cc869c 100644 --- a/libAACdec/src/FDK_delay.cpp +++ b/libAACdec/src/FDK_delay.cpp @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -113,7 +113,7 @@ INT FDK_Delay_Create(FDK_SignalDelay* data, const USHORT delay, if (delay > 0) { data->delay_line = - (INT_PCM*)FDKcalloc(num_channels * delay, sizeof(INT_PCM)); + (PCM_DEC*)FDKcalloc(num_channels * delay, sizeof(PCM_DEC)); if (data->delay_line == NULL) { return -1; } @@ -126,36 +126,36 @@ INT FDK_Delay_Create(FDK_SignalDelay* data, const USHORT delay, return 0; } -void FDK_Delay_Apply(FDK_SignalDelay* data, FIXP_PCM* time_buffer, +void FDK_Delay_Apply(FDK_SignalDelay* data, PCM_DEC* time_buffer, const UINT frame_length, const UCHAR channel) { FDK_ASSERT(data != NULL); if (data->delay > 0) { - C_ALLOC_SCRATCH_START(tmp, FIXP_PCM, MAX_FRAME_LENGTH) + C_ALLOC_SCRATCH_START(tmp, PCM_DEC, MAX_FRAME_LENGTH) FDK_ASSERT(frame_length <= MAX_FRAME_LENGTH); FDK_ASSERT(channel < data->num_channels); FDK_ASSERT(time_buffer != NULL); if (frame_length >= data->delay) { FDKmemcpy(tmp, &time_buffer[frame_length - data->delay], - data->delay * sizeof(FIXP_PCM)); + data->delay * sizeof(PCM_DEC)); FDKmemmove(&time_buffer[data->delay], &time_buffer[0], - (frame_length - data->delay) * sizeof(FIXP_PCM)); + (frame_length - data->delay) * sizeof(PCM_DEC)); FDKmemcpy(&time_buffer[0], &data->delay_line[channel * data->delay], - data->delay * sizeof(FIXP_PCM)); + data->delay * sizeof(PCM_DEC)); FDKmemcpy(&data->delay_line[channel * data->delay], tmp, - data->delay * sizeof(FIXP_PCM)); + data->delay * sizeof(PCM_DEC)); } else { - FDKmemcpy(tmp, &time_buffer[0], frame_length * sizeof(FIXP_PCM)); + FDKmemcpy(tmp, &time_buffer[0], frame_length * sizeof(PCM_DEC)); FDKmemcpy(&time_buffer[0], &data->delay_line[channel * data->delay], - frame_length * sizeof(FIXP_PCM)); + frame_length * sizeof(PCM_DEC)); FDKmemcpy(&data->delay_line[channel * data->delay], &data->delay_line[channel * data->delay + frame_length], - (data->delay - frame_length) * sizeof(FIXP_PCM)); + (data->delay - frame_length) * sizeof(PCM_DEC)); FDKmemcpy(&data->delay_line[channel * data->delay + (data->delay - frame_length)], - tmp, frame_length * sizeof(FIXP_PCM)); + tmp, frame_length * sizeof(PCM_DEC)); } - C_ALLOC_SCRATCH_END(tmp, FIXP_PCM, MAX_FRAME_LENGTH) + C_ALLOC_SCRATCH_END(tmp, PCM_DEC, MAX_FRAME_LENGTH) } return; diff --git a/libAACdec/src/FDK_delay.h b/libAACdec/src/FDK_delay.h index f89c3a2..6317d9d 100644 --- a/libAACdec/src/FDK_delay.h +++ b/libAACdec/src/FDK_delay.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -109,7 +109,7 @@ amm-info@iis.fraunhofer.de * Structure representing one delay element for multiple channels. */ typedef struct { - INT_PCM* delay_line; /*!< Pointer which stores allocated delay line. */ + PCM_DEC* delay_line; /*!< Pointer which stores allocated delay line. */ USHORT delay; /*!< Delay required in samples (per channel). */ UCHAR num_channels; /*!< Number of channels to delay. */ } FDK_SignalDelay; @@ -137,7 +137,7 @@ INT FDK_Delay_Create(FDK_SignalDelay* data, const USHORT delay, * * \return void */ -void FDK_Delay_Apply(FDK_SignalDelay* data, FIXP_PCM* time_buffer, +void FDK_Delay_Apply(FDK_SignalDelay* data, PCM_DEC* time_buffer, const UINT frame_length, const UCHAR channel); /** diff --git a/libAACdec/src/aac_rom.h b/libAACdec/src/aac_rom.h index ffaf951..7a1597c 100644 --- a/libAACdec/src/aac_rom.h +++ b/libAACdec/src/aac_rom.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -108,6 +108,7 @@ amm-info@iis.fraunhofer.de #include "aacdec_hcr_types.h" #include "aacdec_hcrs.h" +#define PCM_AAC LONG #define PCM_DEC FIXP_DBL #define MAXVAL_PCM_DEC MAXVAL_DBL #define MINVAL_PCM_DEC MINVAL_DBL diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp index f747b2d..6a0254d 100644 --- a/libAACdec/src/aacdecoder.cpp +++ b/libAACdec/src/aacdecoder.cpp @@ -1281,6 +1281,7 @@ LINKSPEC_CPP HANDLE_AACDECODER CAacDecoder_Open( /* Set default frame delay */ aacDecoder_drcSetParam(self->hDrcInfo, DRC_BS_DELAY, CConcealment_GetDelay(&self->concealCommonData)); + self->workBufferCore1 = (FIXP_DBL *)GetWorkBufferCore1(); self->workBufferCore2 = GetWorkBufferCore2(); if (self->workBufferCore2 == NULL) goto bail; @@ -1456,6 +1457,10 @@ LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self) { FreeDrcInfo(&self->hDrcInfo); } + if (self->workBufferCore1 != NULL) { + FreeWorkBufferCore1((CWorkBufferCore1 **)&self->workBufferCore1); + } + /* Free WorkBufferCore2 */ if (self->workBufferCore2 != NULL) { FreeWorkBufferCore2(&self->workBufferCore2); @@ -1493,6 +1498,8 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc, UCHAR downscaleFactor = self->downscaleFactor; UCHAR downscaleFactorInBS = self->downscaleFactorInBS; + self->aacOutDataHeadroom = (3); + // set profile and check for supported aot // leave profile on default (=-1) for all other supported MPEG-4 aot's except // aot=2 (=AAC-LC) @@ -2394,7 +2401,7 @@ bail: } LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( - HANDLE_AACDECODER self, const UINT flags, FIXP_PCM *pTimeData, + HANDLE_AACDECODER self, const UINT flags, PCM_DEC *pTimeData, const INT timeDataSize, const int timeDataChannelOffset) { AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; @@ -3170,10 +3177,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( FDKmemcpy(drcChMap, self->chMapping, (8) * sizeof(UCHAR)); } - /* Turn on/off DRC modules level normalization in digital domain depending - * on the limiter status. */ - aacDecoder_drcSetParam(self->hDrcInfo, APPLY_NORMALIZATION, - (self->limiterEnableCurr) ? 0 : 1); + /* Turn off DRC modules level normalization in digital domain. */ + aacDecoder_drcSetParam(self->hDrcInfo, APPLY_NORMALIZATION, 0); /* deactivate legacy DRC in case uniDrc is active, i.e. uniDrc payload is * present and one of DRC or Loudness Normalization is switched on */ @@ -3325,9 +3330,11 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( &pAacDecoderStaticChannelInfo->drcData); } } + /* The DRC module demands to be called with the gain field holding the * gain scale. */ - self->extGain[0] = (FIXP_DBL)TDL_GAIN_SCALING; + self->extGain[0] = (FIXP_DBL)AACDEC_DRC_GAIN_SCALING; + /* DRC processing */ aacDecoder_drcApply( self->hDrcInfo, self->hSbrDecoder, pAacDecoderChannelInfo, @@ -3343,7 +3350,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( if (self->flushStatus && (self->flushCnt > 0) && !(flags & AACDEC_CONCEAL)) { FDKmemclear(pTimeData + offset, - sizeof(FIXP_PCM) * self->streamInfo.aacSamplesPerFrame); + sizeof(PCM_DEC) * self->streamInfo.aacSamplesPerFrame); } else switch (pAacDecoderChannelInfo->renderMode) { case AACDEC_RENDER_IMDCT: @@ -3355,7 +3362,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( !frameOk_butConceal), pAacDecoderChannelInfo->pComStaticData->pWorkBufferCore1 ->mdctOutTemp, - self->elFlags[el], elCh); + self->aacOutDataHeadroom, self->elFlags[el], elCh); self->extGainDelay = self->streamInfo.aacSamplesPerFrame; break; @@ -3376,7 +3383,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( &self->samplingRateInfo[streamIndex], (self->frameOK && !(flags & AACDEC_CONCEAL) && !frameOk_butConceal), - flags, self->flags[streamIndex]); + self->aacOutDataHeadroom, flags, self->flags[streamIndex]); self->extGainDelay = self->streamInfo.aacSamplesPerFrame; break; @@ -3388,7 +3395,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( if (!CConceal_TDFading_Applied[c]) { CConceal_TDFading_Applied[c] = CConcealment_TDFading( self->streamInfo.aacSamplesPerFrame, - &self->pAacDecoderStaticChannelInfo[c], pTimeData + offset, 0); + &self->pAacDecoderStaticChannelInfo[c], self->aacOutDataHeadroom, + pTimeData + offset, 0); if (c + 1 < (8) && c < aacChannels - 1) { /* update next TDNoise Seed to avoid muting in case of Parametric * Stereo */ @@ -3409,27 +3417,18 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( * LR) */ if ((aacChannels == 2) && bsPseudoLr) { int i, offset2; - const FIXP_SGL invSqrt2 = - FL2FXCONST_SGL(0.353553390593273f); /* scaled by -1 */ - FIXP_PCM *pTD = pTimeData; + const FIXP_SGL invSqrt2 = FL2FXCONST_SGL(0.707106781186547f); + PCM_DEC *pTD = pTimeData; offset2 = timeDataChannelOffset; for (i = 0; i < self->streamInfo.aacSamplesPerFrame; i++) { - FIXP_DBL L = FX_PCM2FX_DBL(pTD[0]); - FIXP_DBL R = FX_PCM2FX_DBL(pTD[offset2]); + FIXP_DBL L = PCM_DEC2FIXP_DBL(pTD[0]); + FIXP_DBL R = PCM_DEC2FIXP_DBL(pTD[offset2]); L = fMult(L, invSqrt2); R = fMult(R, invSqrt2); -#if (SAMPLE_BITS == 16) - pTD[0] = (FIXP_SGL)SATURATE_RIGHT_SHIFT(L + R + (FIXP_DBL)(1 << 14), - 15, FRACT_BITS); - pTD[offset2] = (FIXP_SGL)SATURATE_RIGHT_SHIFT( - L - R + (FIXP_DBL)(1 << 14), 15, FRACT_BITS); -#else - pTD[0] = SATURATE_LEFT_SHIFT(FX_DBL2FX_PCM(L + R), 1, DFRACT_BITS); - pTD[offset2] = - SATURATE_LEFT_SHIFT(FX_DBL2FX_PCM(L - R), 1, DFRACT_BITS); -#endif + pTD[0] = L + R; + pTD[offset2] = L - R; pTD++; } } diff --git a/libAACdec/src/aacdecoder.h b/libAACdec/src/aacdecoder.h index 20f4c45..bd1f38f 100644 --- a/libAACdec/src/aacdecoder.h +++ b/libAACdec/src/aacdecoder.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -191,6 +191,9 @@ struct AAC_DECODER_INSTANCE { INT outputInterleaved; /*!< PCM output format (interleaved/none interleaved). */ + INT aacOutDataHeadroom; /*!< Headroom of the output time signal to prevent + clipping */ + HANDLE_TRANSPORTDEC hInput; /*!< Transport layer handle. */ SamplingRateInfo @@ -235,6 +238,7 @@ struct AAC_DECODER_INSTANCE { CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[(8)]; /*!< Persistent channel memory */ + FIXP_DBL *workBufferCore1; FIXP_DBL *workBufferCore2; PCM_DEC *pTimeData2; INT timeData2Size; @@ -311,11 +315,10 @@ This structure is allocated once for each CPE. */ UCHAR limiterEnableUser; /*!< The limiter configuration requested by the library user */ UCHAR limiterEnableCurr; /*!< The current limiter configuration. */ + FIXP_DBL extGain[1]; /*!< Gain that must be applied to the output signal. */ UINT extGainDelay; /*!< Delay that must be accounted for extGain. */ - INT_PCM pcmOutputBuffer[(8) * (1024 * 2)]; - HANDLE_DRC_DECODER hUniDrcDecoder; UCHAR multibandDrcPresent; UCHAR numTimeSlots; @@ -427,7 +430,7 @@ LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, \return error status */ LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_DecodeFrame( - HANDLE_AACDECODER self, const UINT flags, FIXP_PCM *pTimeData, + HANDLE_AACDECODER self, const UINT flags, PCM_DEC *pTimeData, const INT timeDataSize, const int timeDataChannelOffset); /* Free config dependent AAC memory */ diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp index 2ba0e86..f5ce7e0 100644 --- a/libAACdec/src/aacdecoder_lib.cpp +++ b/libAACdec/src/aacdecoder_lib.cpp @@ -119,8 +119,8 @@ amm-info@iis.fraunhofer.de /* Decoder library info */ #define AACDECODER_LIB_VL0 3 -#define AACDECODER_LIB_VL1 1 -#define AACDECODER_LIB_VL2 3 +#define AACDECODER_LIB_VL1 2 +#define AACDECODER_LIB_VL2 0 #define AACDECODER_LIB_TITLE "AAC Decoder Lib" #ifdef __ANDROID__ #define AACDECODER_LIB_BUILD_DATE "" @@ -1131,35 +1131,31 @@ static INT aacDecoder_EstimateNumberOfLostFrames(HANDLE_AACDECODER self) { return n; } -LINKSPEC_CPP AAC_DECODER_ERROR -aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, - const INT timeDataSize_extern, const UINT flags) { +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self, + INT_PCM *pTimeData, + const INT timeDataSize, + const UINT flags) { AAC_DECODER_ERROR ErrorStatus; INT layer; INT nBits; + INT timeData2Size; + INT timeData3Size; + INT timeDataHeadroom; HANDLE_FDK_BITSTREAM hBs; int fTpInterruption = 0; /* Transport originated interruption detection. */ int fTpConceal = 0; /* Transport originated concealment. */ - INT_PCM *pTimeData = NULL; - INT timeDataSize = 0; UINT accessUnit = 0; UINT numAccessUnits = 1; UINT numPrerollAU = 0; - int fEndAuNotAdjusted = 0; /* The end of the access unit was not adjusted */ - int applyCrossfade = 1; /* flag indicates if flushing was possible */ - FIXP_PCM *pTimeDataFixpPcm; /* Signal buffer for decoding process before PCM - processing */ - INT timeDataFixpPcmSize; - PCM_DEC *pTimeDataPcmPost; /* Signal buffer for PCM post-processing */ - INT timeDataPcmPostSize; + int fEndAuNotAdjusted = 0; /* The end of the access unit was not adjusted */ + int applyCrossfade = 1; /* flag indicates if flushing was possible */ + PCM_DEC *pTimeData2; + PCM_AAC *pTimeData3; if (self == NULL) { return AAC_DEC_INVALID_HANDLE; } - pTimeData = self->pcmOutputBuffer; - timeDataSize = sizeof(self->pcmOutputBuffer) / sizeof(*self->pcmOutputBuffer); - if (flags & AACDEC_INTR) { self->streamInfo.numLostAccessUnits = 0; } @@ -1315,19 +1311,23 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, /* Use limiter configuration as requested. */ self->limiterEnableCurr = self->limiterEnableUser; } - /* reset limiter gain on a per frame basis */ - self->extGain[0] = FL2FXCONST_DBL(1.0f / (float)(1 << TDL_GAIN_SCALING)); - pTimeDataFixpPcm = pTimeData; - timeDataFixpPcmSize = timeDataSize; + /* reset DRC level normalization gain on a per frame basis */ + self->extGain[0] = AACDEC_DRC_GAIN_INIT_VALUE; + + pTimeData2 = self->pTimeData2; + timeData2Size = self->timeData2Size / sizeof(PCM_DEC); + pTimeData3 = (PCM_AAC *)self->pTimeData2; + timeData3Size = self->timeData2Size / sizeof(PCM_AAC); ErrorStatus = CAacDecoder_DecodeFrame( self, flags | (fTpConceal ? AACDEC_CONCEAL : 0) | ((self->flushStatus && !(flags & AACDEC_CONCEAL)) ? AACDEC_FLUSH : 0), - pTimeDataFixpPcm + 0, timeDataFixpPcmSize, - self->streamInfo.aacSamplesPerFrame + 0); + pTimeData2 + 0, timeData2Size, self->streamInfo.aacSamplesPerFrame + 0); + + timeDataHeadroom = self->aacOutDataHeadroom; /* if flushing for USAC DASH IPF was not possible go on with decoding * preroll */ @@ -1352,7 +1352,7 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, } } - /* If the current pTimeDataFixpPcm does not contain a valid signal, there + /* If the current pTimeData2 does not contain a valid signal, there * nothing else we can do, so bail. */ if (!IS_OUTPUT_VALID(ErrorStatus)) { goto bail; @@ -1366,10 +1366,10 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, self->streamInfo.numChannels = self->streamInfo.aacNumChannels; { - FDK_Delay_Apply(&self->usacResidualDelay, - pTimeDataFixpPcm + - 1 * (self->streamInfo.aacSamplesPerFrame + 0) + 0, - self->streamInfo.frameSize, 0); + FDK_Delay_Apply( + &self->usacResidualDelay, + pTimeData2 + 1 * (self->streamInfo.aacSamplesPerFrame + 0) + 0, + self->streamInfo.frameSize, 0); } /* Setting of internal MPS state; may be reset in CAacDecoder_SyncQmfMode @@ -1416,8 +1416,6 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, } } - self->qmfDomain.globalConf.TDinput = pTimeData; - switch (FDK_QmfDomain_Configure(&self->qmfDomain)) { default: case QMF_DOMAIN_INIT_ERROR: @@ -1474,18 +1472,18 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF, (self->mpsEnableCurr) ? 2 : 0); - INT_PCM *input; - input = (INT_PCM *)self->workBufferCore2; - FDKmemcpy(input, pTimeData, - sizeof(INT_PCM) * (self->streamInfo.numChannels) * + PCM_AAC *input; + input = (PCM_AAC *)self->workBufferCore2; + FDKmemcpy(input, pTimeData3, + sizeof(PCM_AAC) * (self->streamInfo.numChannels) * (self->streamInfo.frameSize)); /* apply SBR processing */ - sbrError = sbrDecoder_Apply(self->hSbrDecoder, input, pTimeData, - timeDataSize, &self->streamInfo.numChannels, - &self->streamInfo.sampleRate, - &self->mapDescr, self->chMapIndex, - self->frameOK, &self->psPossible); + sbrError = sbrDecoder_Apply( + self->hSbrDecoder, input, pTimeData3, timeData3Size, + &self->streamInfo.numChannels, &self->streamInfo.sampleRate, + &self->mapDescr, self->chMapIndex, self->frameOK, &self->psPossible, + self->aacOutDataHeadroom, &timeDataHeadroom); if (sbrError == SBRDEC_OK) { /* Update data in streaminfo structure. Assume that the SBR upsampling @@ -1564,10 +1562,11 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, if (err == 0) { err = mpegSurroundDecoder_Apply( (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, - (INT_PCM *)self->workBufferCore2, pTimeData, timeDataSize, + (PCM_AAC *)self->workBufferCore2, pTimeData3, timeData3Size, self->streamInfo.aacSamplesPerFrame, &nChannels, &frameSize, self->streamInfo.sampleRate, self->streamInfo.aot, - self->channelType, self->channelIndices, &self->mapDescr); + self->channelType, self->channelIndices, &self->mapDescr, + self->aacOutDataHeadroom, &timeDataHeadroom); } if (err == MPS_OUTPUT_BUFFER_TOO_SMALL) { @@ -1590,8 +1589,8 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, self->streamInfo.frameSize = self->mpsFrameSizeLast; /* ... and clear output buffer so that potentially corrupted data does * not reach the framework. */ - FDKmemclear(pTimeData, self->mpsOutChannelsLast * - self->mpsFrameSizeLast * sizeof(INT_PCM)); + FDKmemclear(pTimeData3, self->mpsOutChannelsLast * + self->mpsFrameSizeLast * sizeof(PCM_AAC)); /* Additionally proclaim that this frame had errors during decoding. */ ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; @@ -1612,11 +1611,11 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF, 1); /* apply SBR processing */ - sbrError = sbrDecoder_Apply(self->hSbrDecoder, pTimeData, pTimeData, - timeDataSize, &self->streamInfo.numChannels, - &self->streamInfo.sampleRate, - &self->mapDescr, self->chMapIndex, - self->frameOK, &self->psPossible); + sbrError = sbrDecoder_Apply( + self->hSbrDecoder, pTimeData3, pTimeData3, timeData3Size, + &self->streamInfo.numChannels, &self->streamInfo.sampleRate, + &self->mapDescr, self->chMapIndex, self->frameOK, &self->psPossible, + self->aacOutDataHeadroom, &timeDataHeadroom); if (sbrError == SBRDEC_OK) { /* Update data in streaminfo structure. Assume that the SBR upsampling @@ -1644,17 +1643,15 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, } } - /* Use dedicated memory for PCM postprocessing */ - pTimeDataPcmPost = self->pTimeData2; - timeDataPcmPostSize = self->timeData2Size; - { - const int size = - self->streamInfo.frameSize * self->streamInfo.numChannels; - FDK_ASSERT(timeDataPcmPostSize >= size); - for (int i = 0; i < size; i++) { - pTimeDataPcmPost[i] = - (PCM_DEC)FX_PCM2PCM_DEC(pTimeData[i]) >> PCM_OUT_HEADROOM; + if ((INT)PCM_OUT_HEADROOM != timeDataHeadroom) { + for (int i = ((self->streamInfo.frameSize * + self->streamInfo.numChannels) - + 1); + i >= 0; i--) { + pTimeData2[i] = + (PCM_DEC)pTimeData3[i] >> (PCM_OUT_HEADROOM - timeDataHeadroom); + } } } @@ -1709,22 +1706,21 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, if ((self->streamInfo.numChannels > 1) && (0 || (self->sbrEnabled) || (self->mpsEnableCurr))) { /* interleaving/deinterleaving is performed on upper part of - * pTimeDataPcmPost. Check if this buffer is large enough. */ - if (timeDataPcmPostSize < - (INT)(2 * self->streamInfo.numChannels * - self->streamInfo.frameSize * sizeof(PCM_DEC))) { + * pTimeData2. Check if this buffer is large enough. */ + if (timeData2Size < (INT)(2 * self->streamInfo.numChannels * + self->streamInfo.frameSize)) { ErrorStatus = AAC_DEC_UNKNOWN; goto bail; } needsDeinterleaving = 1; drcWorkBuffer = - (FIXP_DBL *)pTimeDataPcmPost + + (FIXP_DBL *)pTimeData2 + self->streamInfo.numChannels * self->streamInfo.frameSize; FDK_deinterleave( - pTimeDataPcmPost, drcWorkBuffer, self->streamInfo.numChannels, + pTimeData2, drcWorkBuffer, self->streamInfo.numChannels, self->streamInfo.frameSize, self->streamInfo.frameSize); } else { - drcWorkBuffer = (FIXP_DBL *)pTimeDataPcmPost; + drcWorkBuffer = pTimeData2; } /* prepare Loudness Normalisation gain */ @@ -1759,7 +1755,7 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, if (needsDeinterleaving) { FDK_interleave( - drcWorkBuffer, pTimeDataPcmPost, self->streamInfo.numChannels, + drcWorkBuffer, pTimeData2, self->streamInfo.numChannels, self->streamInfo.frameSize, self->streamInfo.frameSize); } } @@ -1799,6 +1795,9 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, if (self->streamInfo.extAot != AOT_AAC_SLS) { INT pcmLimiterScale = 0; + INT interleaved = 0; + interleaved |= (self->sbrEnabled) ? 1 : 0; + interleaved |= (self->mpsEnableCurr) ? 1 : 0; PCMDMX_ERROR dmxErr = PCMDMX_OK; if ((flags & AACDEC_INTR) && (accessUnit == 0)) { /* delete data from the past (e.g. mixdown coeficients) */ @@ -1811,17 +1810,12 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, } } - INT interleaved = 0; - interleaved |= (self->sbrEnabled) ? 1 : 0; - interleaved |= (self->mpsEnableCurr) ? 1 : 0; - /* do PCM post processing */ - dmxErr = pcmDmx_ApplyFrame( - self->hPcmUtils, pTimeDataPcmPost, timeDataFixpPcmSize, - self->streamInfo.frameSize, &self->streamInfo.numChannels, - interleaved, self->channelType, self->channelIndices, - &self->mapDescr, - (self->limiterEnableCurr) ? &pcmLimiterScale : NULL); + dmxErr = pcmDmx_ApplyFrame(self->hPcmUtils, pTimeData2, timeData2Size, + self->streamInfo.frameSize, + &self->streamInfo.numChannels, interleaved, + self->channelType, self->channelIndices, + &self->mapDescr, &pcmLimiterScale); if (dmxErr == PCMDMX_OUTPUT_BUFFER_TOO_SMALL) { ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; goto bail; @@ -1833,13 +1827,35 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; } + pcmLimiterScale += PCM_OUT_HEADROOM; + if (flags & AACDEC_CLRHIST) { if (!(self->flags[0] & AC_USAC)) { + /* Reset DRC data */ + aacDecoder_drcReset(self->hDrcInfo); /* Delete the delayed signal. */ pcmLimiter_Reset(self->hLimiter); } } + /* Set applyExtGain if DRC processing is enabled and if + progRefLevelPresent is present for the first time. Consequences: The + headroom of the output signal can be set to AACDEC_DRC_GAIN_SCALING + only for audio formats which support legacy DRC Level Normalization. + For all other audio formats the headroom of the output + signal is set to PCM_OUT_HEADROOM. */ + if (self->hDrcInfo->enable && + (self->hDrcInfo->progRefLevelPresent == 1)) { + self->hDrcInfo->applyExtGain |= 1; + } + + /* Check whether time data buffer is large enough. */ + if (timeDataSize < + (self->streamInfo.numChannels * self->streamInfo.frameSize)) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + goto bail; + } + if (self->limiterEnableCurr) { /* use workBufferCore2 buffer for interleaving */ PCM_LIM *pInterleaveBuffer; @@ -1848,44 +1864,72 @@ aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, /* Set actual signal parameters */ pcmLimiter_SetNChannels(self->hLimiter, self->streamInfo.numChannels); pcmLimiter_SetSampleRate(self->hLimiter, self->streamInfo.sampleRate); - pcmLimiterScale += PCM_OUT_HEADROOM; if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) || (self->mpsEnableCurr)) { - pInterleaveBuffer = (PCM_LIM *)pTimeDataPcmPost; + pInterleaveBuffer = (PCM_LIM *)pTimeData2; } else { - pInterleaveBuffer = (PCM_LIM *)pTimeData; + pInterleaveBuffer = (PCM_LIM *)self->workBufferCore2; + /* applyLimiter requests for interleaved data */ /* Interleave ouput buffer */ - FDK_interleave(pTimeDataPcmPost, pInterleaveBuffer, + FDK_interleave(pTimeData2, pInterleaveBuffer, self->streamInfo.numChannels, blockLength, self->streamInfo.frameSize); } + FIXP_DBL *pGainPerSample = NULL; + + if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) { + pGainPerSample = self->workBufferCore1; + + if ((INT)GetRequiredMemWorkBufferCore1() < + (INT)(self->streamInfo.frameSize * sizeof(FIXP_DBL))) { + ErrorStatus = AAC_DEC_UNKNOWN; + goto bail; + } + + pcmLimiterScale = applyDrcLevelNormalization( + self->hDrcInfo, (PCM_DEC *)pInterleaveBuffer, self->extGain, + pGainPerSample, pcmLimiterScale, self->extGainDelay, + self->streamInfo.frameSize, self->streamInfo.numChannels, 1, 1); + } + pcmLimiter_Apply(self->hLimiter, pInterleaveBuffer, pTimeData, - self->extGain, &pcmLimiterScale, 1, - self->extGainDelay, self->streamInfo.frameSize); + pGainPerSample, pcmLimiterScale, + self->streamInfo.frameSize); { /* Announce the additional limiter output delay */ self->streamInfo.outputDelay += pcmLimiter_GetDelay(self->hLimiter); } } else { + if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) { + pcmLimiterScale = applyDrcLevelNormalization( + self->hDrcInfo, pTimeData2, self->extGain, NULL, + pcmLimiterScale, self->extGainDelay, self->streamInfo.frameSize, + self->streamInfo.numChannels, + (interleaved || (self->streamInfo.numChannels == 1)) + ? 1 + : self->streamInfo.frameSize, + 0); + } + /* If numChannels = 1 we do not need interleaving. The same applies if SBR or MPS are used, since their output is interleaved already (resampled or not) */ if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) || (self->mpsEnableCurr)) { scaleValuesSaturate( - pTimeData, pTimeDataPcmPost, + pTimeData, pTimeData2, self->streamInfo.frameSize * self->streamInfo.numChannels, - PCM_OUT_HEADROOM); + pcmLimiterScale); } else { scaleValuesSaturate( - (INT_PCM *)self->workBufferCore2, pTimeDataPcmPost, + (INT_PCM *)self->workBufferCore2, pTimeData2, self->streamInfo.frameSize * self->streamInfo.numChannels, - PCM_OUT_HEADROOM); + pcmLimiterScale); /* Interleave ouput buffer */ FDK_interleave((INT_PCM *)self->workBufferCore2, pTimeData, self->streamInfo.numChannels, @@ -1981,20 +2025,8 @@ bail: ErrorStatus = AAC_DEC_UNKNOWN; } - /* Check whether external output buffer is large enough. */ - if (timeDataSize_extern < - self->streamInfo.numChannels * self->streamInfo.frameSize) { - ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; - } - - /* Update external output buffer. */ - if (IS_OUTPUT_VALID(ErrorStatus)) { - FDKmemcpy(pTimeData_extern, pTimeData, - self->streamInfo.numChannels * self->streamInfo.frameSize * - sizeof(*pTimeData)); - } else { - FDKmemclear(pTimeData_extern, - timeDataSize_extern * sizeof(*pTimeData_extern)); + if (!IS_OUTPUT_VALID(ErrorStatus)) { + FDKmemclear(pTimeData, timeDataSize * sizeof(*pTimeData)); } return ErrorStatus; diff --git a/libAACdec/src/block.cpp b/libAACdec/src/block.cpp index b3d09a6..0bca577 100644 --- a/libAACdec/src/block.cpp +++ b/libAACdec/src/block.cpp @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -1015,9 +1015,9 @@ FIXP_DBL get_gain(const FIXP_DBL *x, const FIXP_DBL *y, int n) { void CBlock_FrequencyToTime( CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, - CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[], + CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[], const SHORT frameLen, const int frameOk, FIXP_DBL *pWorkBuffer1, - UINT elFlags, INT elCh) { + const INT aacOutDataHeadroom, UINT elFlags, INT elCh) { int fr, fl, tl, nSpec; #if defined(FDK_ASSERT_ENABLE) @@ -1213,6 +1213,7 @@ void CBlock_FrequencyToTime( bass_pf_1sf_delay(p2_synth, pitch, pit_gain, frameLen, (LpdSfd + 2) * L_SUBFR + BPF_SFD * L_SUBFR, frameLen - (LpdSfd + 4) * L_SUBFR, outSamples, + aacOutDataHeadroom, pAacDecoderStaticChannelInfo->mem_bpf); } @@ -1236,7 +1237,8 @@ void CBlock_FrequencyToTime( ? MLT_FLAG_CURR_ALIAS_SYMMETRY : 0); - scaleValuesSaturate(outSamples, tmp, frameLen, MDCT_OUT_HEADROOM); + scaleValuesSaturate(outSamples, tmp, frameLen, + MDCT_OUT_HEADROOM - aacOutDataHeadroom); } } @@ -1251,7 +1253,7 @@ void CBlock_FrequencyToTime( #include "ldfiltbank.h" void CBlock_FrequencyToTimeLowDelay( CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, - CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[], + CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[], const short frameLen) { InvMdctTransformLowDelay_fdk( SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient), diff --git a/libAACdec/src/block.h b/libAACdec/src/block.h index f0f56cd..f5118a2 100644 --- a/libAACdec/src/block.h +++ b/libAACdec/src/block.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -218,16 +218,16 @@ void ApplyTools(CAacDecoderChannelInfo *pAacDecoderChannelInfo[], */ void CBlock_FrequencyToTime( CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, - CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[], + CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[], const SHORT frameLen, const int frameOk, FIXP_DBL *pWorkBuffer1, - UINT elFlags, INT elCh); + const INT aacOutDataHeadroom, UINT elFlags, INT elCh); /** * \brief Transform double lapped MDCT (AAC-ELD) spectral data into time domain. */ void CBlock_FrequencyToTimeLowDelay( CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, - CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[], + CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC outSamples[], const short frameLen); AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData( diff --git a/libAACdec/src/conceal.cpp b/libAACdec/src/conceal.cpp index 379e63a..0939bb5 100644 --- a/libAACdec/src/conceal.cpp +++ b/libAACdec/src/conceal.cpp @@ -226,7 +226,7 @@ static void CConcealment_ApplyRandomSign(int iRandomPhase, FIXP_DBL *spec, /* TimeDomainFading */ static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart, - FIXP_DBL fadeStop, FIXP_PCM *pcmdata); + FIXP_DBL fadeStop, PCM_DEC *pcmdata); static void CConcealment_TDFadeFillFadingStations(FIXP_DBL *fadingStations, int *fadingSteps, FIXP_DBL fadeStop, @@ -242,7 +242,9 @@ static int CConcealment_ApplyFadeOut( static int CConcealment_TDNoise_Random(ULONG *seed); static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo, - const int len, FIXP_PCM *const pcmdata); + const int len, + const INT aacOutDataHeadroom, + PCM_DEC *const pcmdata); static BLOCK_TYPE CConcealment_GetWinSeq(int prevWinSeq) { BLOCK_TYPE newWinSeq = BLOCK_LONG; @@ -1844,7 +1846,7 @@ Target fading level is determined by fading index cntFadeFrames. INT CConcealment_TDFading( int len, CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo, - FIXP_PCM *pcmdata, FIXP_PCM *pcmdata_1) { + const INT aacOutDataHeadroom, PCM_DEC *pcmdata, PCM_DEC *pcmdata_1) { /* Do the fading in Time domain based on concealment states and core mode */ @@ -1957,7 +1959,8 @@ INT CConcealment_TDFading( start += len; } } - CConcealment_TDNoise_Apply(pConcealmentInfo, len, pcmdata); + CConcealment_TDNoise_Apply(pConcealmentInfo, len, aacOutDataHeadroom, + pcmdata); /* Save end-of-frame attenuation and fading type */ pConcealmentInfo->lastFadingType = fadingType; @@ -1969,12 +1972,11 @@ INT CConcealment_TDFading( /* attenuate pcmdata in Time Domain Fading process */ static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart, - FIXP_DBL fadeStop, FIXP_PCM *pcmdata) { + FIXP_DBL fadeStop, PCM_DEC *pcmdata) { int i; FIXP_DBL dStep; FIXP_DBL dGain; FIXP_DBL dGain_apply; - int bitshift = (DFRACT_BITS - SAMPLE_BITS); /* set start energy */ dGain = fadeStart; @@ -1987,7 +1989,7 @@ static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart, */ dGain_apply = fMax((FIXP_DBL)0, dGain); /* finally, attenuate samples */ - pcmdata[i] = (FIXP_PCM)((fMult(pcmdata[i], (dGain_apply))) >> bitshift); + pcmdata[i] = FIXP_DBL2PCM_DEC(fMult(pcmdata[i], dGain_apply)); } } @@ -2050,9 +2052,11 @@ static int CConcealment_TDNoise_Random(ULONG *seed) { } static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo, - const int len, FIXP_PCM *const pcmdata) { - FIXP_PCM *states = pConcealmentInfo->TDNoiseStates; - FIXP_PCM noiseVal; + const int len, + const INT aacOutDataHeadroom, + PCM_DEC *const pcmdata) { + PCM_DEC *states = pConcealmentInfo->TDNoiseStates; + PCM_DEC noiseVal; FIXP_DBL noiseValLong; FIXP_SGL *coef = pConcealmentInfo->TDNoiseCoef; FIXP_DBL TDNoiseAtt; @@ -2070,18 +2074,20 @@ static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo, /* create filtered noise */ states[2] = states[1]; states[1] = states[0]; - states[0] = ((FIXP_PCM)CConcealment_TDNoise_Random(&seed)); + states[0] = + FIXP_DBL2PCM_DEC((FIXP_DBL)CConcealment_TDNoise_Random(&seed)); noiseValLong = fMult(states[0], coef[0]) + fMult(states[1], coef[1]) + fMult(states[2], coef[2]); - noiseVal = FX_DBL2FX_PCM(fMult(noiseValLong, TDNoiseAtt)); + noiseVal = FIXP_DBL2PCM_DEC(fMult(noiseValLong, TDNoiseAtt) >> + aacOutDataHeadroom); /* add filtered noise - check for clipping, before */ - if (noiseVal > (FIXP_PCM)0 && - pcmdata[ii] > (FIXP_PCM)MAXVAL_FIXP_PCM - noiseVal) { - noiseVal = noiseVal * (FIXP_PCM)-1; - } else if (noiseVal < (FIXP_PCM)0 && - pcmdata[ii] < (FIXP_PCM)MINVAL_FIXP_PCM - noiseVal) { - noiseVal = noiseVal * (FIXP_PCM)-1; + if (noiseVal > (PCM_DEC)0 && + pcmdata[ii] > (PCM_DEC)MAXVAL_PCM_DEC - noiseVal) { + noiseVal = noiseVal * (PCM_DEC)-1; + } else if (noiseVal < (PCM_DEC)0 && + pcmdata[ii] < (PCM_DEC)MINVAL_PCM_DEC - noiseVal) { + noiseVal = noiseVal * (PCM_DEC)-1; } pcmdata[ii] += noiseVal; diff --git a/libAACdec/src/conceal.h b/libAACdec/src/conceal.h index e01a796..0c002a5 100644 --- a/libAACdec/src/conceal.h +++ b/libAACdec/src/conceal.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -147,6 +147,6 @@ int CConcealment_GetLastFrameOk(CConcealmentInfo *hConcealmentInfo, INT CConcealment_TDFading( int len, CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo, - FIXP_PCM *pcmdata, FIXP_PCM *pcmdata_1); + const INT aacOutDataHeadroom, PCM_DEC *pcmdata, PCM_DEC *pcmdata_1); #endif /* #ifndef CONCEAL_H */ diff --git a/libAACdec/src/conceal_types.h b/libAACdec/src/conceal_types.h index d90374e..36e7dec 100644 --- a/libAACdec/src/conceal_types.h +++ b/libAACdec/src/conceal_types.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -194,7 +194,7 @@ typedef struct { FIXP_DBL last_tcx_gain; INT last_tcx_gain_e; ULONG TDNoiseSeed; - FIXP_PCM TDNoiseStates[3]; + PCM_DEC TDNoiseStates[3]; FIXP_SGL TDNoiseCoef[3]; FIXP_SGL TDNoiseAtt; diff --git a/libAACdec/src/ldfiltbank.cpp b/libAACdec/src/ldfiltbank.cpp index 1898557..13e61a5 100644 --- a/libAACdec/src/ldfiltbank.cpp +++ b/libAACdec/src/ldfiltbank.cpp @@ -112,17 +112,20 @@ amm-info@iis.fraunhofer.de #if defined(__arm__) #endif -static void multE2_DinvF_fdk(FIXP_PCM *output, FIXP_DBL *x, const FIXP_WTB *fb, +static void multE2_DinvF_fdk(PCM_DEC *output, FIXP_DBL *x, const FIXP_WTB *fb, FIXP_DBL *z, const int N) { int i; - /* scale for FIXP_DBL -> INT_PCM conversion. */ - const int scale = (DFRACT_BITS - SAMPLE_BITS) - LDFB_HEADROOM; -#if ((DFRACT_BITS - SAMPLE_BITS - LDFB_HEADROOM) > 0) + /* scale for FIXP_DBL -> PCM_DEC conversion: */ + const int scale = (DFRACT_BITS - PCM_OUT_BITS) - LDFB_HEADROOM + (3); + +#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - 1) > 0) FIXP_DBL rnd_val_wts0 = (FIXP_DBL)0; FIXP_DBL rnd_val_wts1 = (FIXP_DBL)0; +#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - WTS0 - 1) > 0) if (-WTS0 - 1 + scale) rnd_val_wts0 = (FIXP_DBL)(1 << (-WTS0 - 1 + scale - 1)); +#endif if (-WTS1 - 1 + scale) rnd_val_wts1 = (FIXP_DBL)(1 << (-WTS1 - 1 + scale - 1)); #endif @@ -141,16 +144,16 @@ static void multE2_DinvF_fdk(FIXP_PCM *output, FIXP_DBL *x, const FIXP_WTB *fb, tmp = (fMultDiv2(z[N / 2 + i], fb[N + N / 2 - 1 - i]) + fMultDiv2(z[i], fb[N + N / 2 + i])); -#if ((DFRACT_BITS - SAMPLE_BITS - LDFB_HEADROOM) > 0) +#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - 1) > 0) FDK_ASSERT((-WTS1 - 1 + scale) >= 0); FDK_ASSERT(tmp <= ((FIXP_DBL)0x7FFFFFFF - rnd_val_wts1)); /* rounding must not cause overflow */ - output[(N * 3 / 4 - 1 - i)] = (FIXP_PCM)SATURATE_RIGHT_SHIFT( + output[(N * 3 / 4 - 1 - i)] = (PCM_DEC)SATURATE_RIGHT_SHIFT( tmp + rnd_val_wts1, -WTS1 - 1 + scale, PCM_OUT_BITS); #else FDK_ASSERT((WTS1 + 1 - scale) >= 0); output[(N * 3 / 4 - 1 - i)] = - (FIXP_PCM)SATURATE_LEFT_SHIFT(tmp, WTS1 + 1 - scale, PCM_OUT_BITS); + (PCM_DEC)SATURATE_LEFT_SHIFT(tmp, WTS1 + 1 - scale, PCM_OUT_BITS); #endif z[i] = z0; @@ -173,22 +176,22 @@ static void multE2_DinvF_fdk(FIXP_PCM *output, FIXP_DBL *x, const FIXP_WTB *fb, tmp1 = (fMultDiv2(z[N / 2 + i], fb[N + N / 2 - 1 - i]) + fMultDiv2(z[i], fb[N + N / 2 + i])); -#if ((DFRACT_BITS - SAMPLE_BITS - LDFB_HEADROOM) > 0) +#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - 1) > 0) FDK_ASSERT((-WTS0 - 1 + scale) >= 0); FDK_ASSERT(tmp0 <= ((FIXP_DBL)0x7FFFFFFF - rnd_val_wts0)); /* rounding must not cause overflow */ FDK_ASSERT(tmp1 <= ((FIXP_DBL)0x7FFFFFFF - rnd_val_wts1)); /* rounding must not cause overflow */ - output[(i - N / 4)] = (FIXP_PCM)SATURATE_RIGHT_SHIFT( + output[(i - N / 4)] = (PCM_DEC)SATURATE_RIGHT_SHIFT( tmp0 + rnd_val_wts0, -WTS0 - 1 + scale, PCM_OUT_BITS); - output[(N * 3 / 4 - 1 - i)] = (FIXP_PCM)SATURATE_RIGHT_SHIFT( + output[(N * 3 / 4 - 1 - i)] = (PCM_DEC)SATURATE_RIGHT_SHIFT( tmp1 + rnd_val_wts1, -WTS1 - 1 + scale, PCM_OUT_BITS); #else FDK_ASSERT((WTS0 + 1 - scale) >= 0); output[(i - N / 4)] = - (FIXP_PCM)SATURATE_LEFT_SHIFT(tmp0, WTS0 + 1 - scale, PCM_OUT_BITS); + (PCM_DEC)SATURATE_LEFT_SHIFT(tmp0, WTS0 + 1 - scale, PCM_OUT_BITS); output[(N * 3 / 4 - 1 - i)] = - (FIXP_PCM)SATURATE_LEFT_SHIFT(tmp1, WTS1 + 1 - scale, PCM_OUT_BITS); + (PCM_DEC)SATURATE_LEFT_SHIFT(tmp1, WTS1 + 1 - scale, PCM_OUT_BITS); #endif z[i] = z0; z[N + i] = z2; @@ -198,22 +201,22 @@ static void multE2_DinvF_fdk(FIXP_PCM *output, FIXP_DBL *x, const FIXP_WTB *fb, for (i = 0; i < N / 4; i++) { FIXP_DBL tmp0 = fMultDiv2(z[i], fb[N / 2 + i]); -#if ((DFRACT_BITS - SAMPLE_BITS - LDFB_HEADROOM) > 0) +#if ((DFRACT_BITS - PCM_OUT_BITS - LDFB_HEADROOM + (3) - 1) > 0) FDK_ASSERT((-WTS0 - 1 + scale) >= 0); FDK_ASSERT(tmp0 <= ((FIXP_DBL)0x7FFFFFFF - rnd_val_wts0)); /* rounding must not cause overflow */ - output[(N * 3 / 4 + i)] = (FIXP_PCM)SATURATE_RIGHT_SHIFT( + output[(N * 3 / 4 + i)] = (PCM_DEC)SATURATE_RIGHT_SHIFT( tmp0 + rnd_val_wts0, -WTS0 - 1 + scale, PCM_OUT_BITS); #else FDK_ASSERT((WTS0 + 1 - scale) >= 0); output[(N * 3 / 4 + i)] = - (FIXP_PCM)SATURATE_LEFT_SHIFT(tmp0, WTS0 + 1 - scale, PCM_OUT_BITS); + (PCM_DEC)SATURATE_LEFT_SHIFT(tmp0, WTS0 + 1 - scale, PCM_OUT_BITS); #endif } } int InvMdctTransformLowDelay_fdk(FIXP_DBL *mdctData, const int mdctData_e, - FIXP_PCM *output, FIXP_DBL *fs_buffer, + PCM_DEC *output, FIXP_DBL *fs_buffer, const int N) { const FIXP_WTB *coef; FIXP_DBL gain = (FIXP_DBL)0; diff --git a/libAACdec/src/ldfiltbank.h b/libAACdec/src/ldfiltbank.h index b63da6b..02971d0 100644 --- a/libAACdec/src/ldfiltbank.h +++ b/libAACdec/src/ldfiltbank.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -104,9 +104,10 @@ amm-info@iis.fraunhofer.de #define LDFILTBANK_H #include "common_fix.h" +#include "aac_rom.h" int InvMdctTransformLowDelay_fdk(FIXP_DBL *mdctdata_m, const int mdctdata_e, - FIXP_PCM *mdctOut, FIXP_DBL *fs_buffer, + PCM_DEC *mdctOut, FIXP_DBL *fs_buffer, const int frameLength); #endif diff --git a/libAACdec/src/usacdec_lpd.cpp b/libAACdec/src/usacdec_lpd.cpp index de0c2de..fbf6fab 100644 --- a/libAACdec/src/usacdec_lpd.cpp +++ b/libAACdec/src/usacdec_lpd.cpp @@ -122,18 +122,21 @@ amm-info@iis.fraunhofer.de #include "ac_arith_coder.h" -void filtLP(const FIXP_DBL *syn, FIXP_PCM *syn_out, FIXP_DBL *noise, - const FIXP_SGL *filt, INT stop, int len) { +void filtLP(const FIXP_DBL *syn, PCM_DEC *syn_out, FIXP_DBL *noise, + const FIXP_SGL *filt, const INT aacOutDataHeadroom, INT stop, + int len) { INT i, j; FIXP_DBL tmp; + FDK_ASSERT((aacOutDataHeadroom - 1) >= -(MDCT_OUTPUT_SCALE)); + for (i = 0; i < stop; i++) { tmp = fMultDiv2(noise[i], filt[0]); // Filt in Q-1.16 for (j = 1; j <= len; j++) { tmp += fMult((noise[i - j] >> 1) + (noise[i + j] >> 1), filt[j]); } - syn_out[i] = (FIXP_PCM)(SATURATE_SHIFT( - (syn[i] >> 1) - (tmp >> 1), (MDCT_OUTPUT_SCALE - 1), PCM_OUT_BITS)); + syn_out[i] = (PCM_DEC)( + IMDCT_SCALE((syn[i] >> 1) - (tmp >> 1), aacOutDataHeadroom - 1)); } } @@ -143,8 +146,10 @@ void bass_pf_1sf_delay( FIXP_DBL *pit_gain, const int frame_length, /* (i) : frame length (should be 768|1024) */ const INT l_frame, - const INT l_next, /* (i) : look ahead for symmetric filtering */ - FIXP_PCM *synth_out, /* (o) : filtered synthesis (with delay of 1 subfr) */ + const INT l_next, /* (i) : look ahead for symmetric filtering */ + PCM_DEC *synth_out, /* (o) : filtered synthesis (with delay of 1 subfr) */ + const INT aacOutDataHeadroom, /* (i) : headroom of the output time signal to + prevent clipping */ FIXP_DBL mem_bpf[]) /* i/o : memory state [L_FILT+L_SUBFR] */ { INT i, sf, i_subfr, T, T2, lg; @@ -370,7 +375,7 @@ void bass_pf_1sf_delay( { filtLP(&syn[i_subfr - L_SUBFR], &synth_out[i_subfr], noise, - fdk_dec_filt_lp, L_SUBFR, L_FILT); + fdk_dec_filt_lp, aacOutDataHeadroom, L_SUBFR, L_FILT); } } @@ -383,9 +388,9 @@ void bass_pf_1sf_delay( /* Output scaling of the BPF memory */ scaleValues(mem_bpf, (L_FILT + L_SUBFR), -1); /* Copy the rest of the signal (after the fac) */ - scaleValuesSaturate((FIXP_PCM *)&synth_out[l_frame], - (FIXP_DBL *)&syn[l_frame - L_SUBFR], - (frame_length - l_frame), MDCT_OUT_HEADROOM); + scaleValuesSaturate( + (PCM_DEC *)&synth_out[l_frame], (FIXP_DBL *)&syn[l_frame - L_SUBFR], + (frame_length - l_frame), MDCT_OUT_HEADROOM - aacOutDataHeadroom); } return; @@ -1552,9 +1557,9 @@ void CLpdChannelStream_Decode( AAC_DECODER_ERROR CLpd_RenderTimeSignal( CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, - CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM *pTimeData, - INT lFrame, SamplingRateInfo *pSamplingRateInfo, UINT frameOk, UINT flags, - UINT strmFlags) { + CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC *pTimeData, + INT lFrame, SamplingRateInfo *pSamplingRateInfo, UINT frameOk, + const INT aacOutDataHeadroom, UINT flags, UINT strmFlags) { UCHAR *mod = pAacDecoderChannelInfo->data.usac.mod; AAC_DECODER_ERROR error = AAC_DEC_OK; int k, i_offset; @@ -2017,7 +2022,8 @@ AAC_DECODER_ERROR CLpd_RenderTimeSignal( { bass_pf_1sf_delay(p2_synth, pitch, pit_gain, lFrame, lFrame / facFB, mod[nbDiv - 1] ? (SynDelay - (lDiv / 2)) : SynDelay, - pTimeData, pAacDecoderStaticChannelInfo->mem_bpf); + pTimeData, aacOutDataHeadroom, + pAacDecoderStaticChannelInfo->mem_bpf); } } diff --git a/libAACdec/src/usacdec_lpd.h b/libAACdec/src/usacdec_lpd.h index 3e7938d..448dc55 100644 --- a/libAACdec/src/usacdec_lpd.h +++ b/libAACdec/src/usacdec_lpd.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -140,13 +140,14 @@ void CLpdChannelStream_Decode( * \param pTimeData pointer to output buffer * \param samplesPerFrame amount of output samples * \param pSamplingRateInfo holds the sampling rate information - * \param pWorkBuffer1 pointer to work buffer for temporal data + * \param aacOutDataHeadroom headroom of the output time signal to prevent + * clipping */ AAC_DECODER_ERROR CLpd_RenderTimeSignal( CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, - CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM *pTimeData, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC *pTimeData, INT samplesPerFrame, SamplingRateInfo *pSamplingRateInfo, UINT frameOk, - UINT flags, UINT strmFlags); + const INT aacOutDataHeadroom, UINT flags, UINT strmFlags); static inline INT CLpd_FAC_getLength(int fNotShortBlock, int fac_length_long) { if (fNotShortBlock) { @@ -156,8 +157,9 @@ static inline INT CLpd_FAC_getLength(int fNotShortBlock, int fac_length_long) { } } -void filtLP(const FIXP_DBL *syn, FIXP_PCM *syn_out, FIXP_DBL *noise, - const FIXP_SGL *filt, INT stop, int len); +void filtLP(const FIXP_DBL *syn, PCM_DEC *syn_out, FIXP_DBL *noise, + const FIXP_SGL *filt, const INT aacOutDataHeadroom, INT stop, + int len); /** * \brief perform a low-frequency pitch enhancement on time domain signal @@ -171,13 +173,14 @@ void filtLP(const FIXP_DBL *syn, FIXP_PCM *syn_out, FIXP_DBL *noise, * \param[in] l_frame length of filtering, must be multiple of L_SUBFR * \param[in] l_next length of allowed look ahead on syn[i], i < l_frame+l_next * \param[out] synth_out pointer to time domain output signal + * \param[in] headroom of the output time signal to prevent clipping * \param[in,out] mem_bpf pointer to filter memory (L_FILT+L_SUBFR) */ void bass_pf_1sf_delay(FIXP_DBL syn[], const INT T_sf[], FIXP_DBL *pit_gain, const int frame_length, const INT l_frame, - const INT l_next, FIXP_PCM *synth_out, - FIXP_DBL mem_bpf[]); + const INT l_next, PCM_DEC *synth_out, + const INT aacOutDataHeadroom, FIXP_DBL mem_bpf[]); /** * \brief random sign generator for FD and TCX noise filling diff --git a/libFDK/include/FDK_qmf_domain.h b/libFDK/include/FDK_qmf_domain.h index aa247e9..0e83da3 100644 --- a/libFDK/include/FDK_qmf_domain.h +++ b/libFDK/include/FDK_qmf_domain.h @@ -160,8 +160,6 @@ H_ALLOC_MEM(QmfSlotsImag32, FIXP_DBL *) H_ALLOC_MEM(QmfOverlapBuffer16, FIXP_DBL) H_ALLOC_MEM(QmfOverlapBuffer32, FIXP_DBL) -#define QDOM_PCM INT_PCM - /** * Structure to hold the configuration data which is global whithin a QMF domain * instance. @@ -181,9 +179,6 @@ typedef struct { park a channel if only one processing channel is available. */ UCHAR parkChannel_requested; - QDOM_PCM - *TDinput; /*!< Pointer to time domain data used as input for the QMF - analysis. */ FIXP_DBL * pWorkBuffer[QMF_MAX_WB_SECTIONS]; /*!< Pointerarray to volatile memory. */ UINT flags; /*!< Flags to be set on all QMF analysis/synthesis filter diff --git a/libFDK/include/mdct.h b/libFDK/include/mdct.h index 1382374..e7cf3ad 100644 --- a/libFDK/include/mdct.h +++ b/libFDK/include/mdct.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -106,18 +106,16 @@ amm-info@iis.fraunhofer.de #include "common_fix.h" #define MDCT_OUT_HEADROOM 2 /* Output additional headroom */ -#define PCM_OUT_BITS SAMPLE_BITS + +#define PCM_OUT_BITS DFRACT_BITS #define PCM_OUT_HEADROOM 8 /* Must have the same values as DMXH_HEADROOM */ -#define MDCT_OUTPUT_SCALE (-MDCT_OUT_HEADROOM + (DFRACT_BITS - SAMPLE_BITS)) +#define MDCT_OUTPUT_SCALE (-MDCT_OUT_HEADROOM + (DFRACT_BITS - PCM_OUT_BITS)) /* Refer to "Output word length" in ISO/IEC 14496-3:2008(E) 23.2.3.6 */ #define MDCT_OUTPUT_GAIN 16 -#if (MDCT_OUTPUT_SCALE >= 0) -#define IMDCT_SCALE(x) SATURATE_RIGHT_SHIFT(x, MDCT_OUTPUT_SCALE, PCM_OUT_BITS) -#else -#define IMDCT_SCALE(x) SATURATE_LEFT_SHIFT(x, -MDCT_OUTPUT_SCALE, PCM_OUT_BITS) -#endif +#define IMDCT_SCALE(x, s) \ + SATURATE_RIGHT_SHIFT((x), ((s) + MDCT_OUTPUT_SCALE), PCM_OUT_BITS) #define IMDCT_SCALE_DBL(x) (FIXP_DBL)(x) #define IMDCT_SCALE_DBL_LSH1(x) SATURATE_LEFT_SHIFT_ALT((x), 1, DFRACT_BITS) diff --git a/libFDK/src/FDK_core.cpp b/libFDK/src/FDK_core.cpp index 75ea8a2..2f77179 100644 --- a/libFDK/src/FDK_core.cpp +++ b/libFDK/src/FDK_core.cpp @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -104,7 +104,7 @@ amm-info@iis.fraunhofer.de /* FDK tools library info */ #define FDK_TOOLS_LIB_VL0 3 -#define FDK_TOOLS_LIB_VL1 0 +#define FDK_TOOLS_LIB_VL1 1 #define FDK_TOOLS_LIB_VL2 0 #define FDK_TOOLS_LIB_TITLE "FDK Tools" #ifdef __ANDROID__ diff --git a/libFDK/src/FDK_qmf_domain.cpp b/libFDK/src/FDK_qmf_domain.cpp index 71e2ef5..77c5ca2 100644 --- a/libFDK/src/FDK_qmf_domain.cpp +++ b/libFDK/src/FDK_qmf_domain.cpp @@ -637,10 +637,10 @@ void FDK_QmfDomain_GetSlot(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, const int ts, if (pQmfOutImag == NULL) { for (; b < fMin(lsb, stop_band); b++) { - pQmfOutReal[b] = scaleValue(real[b], lb_sf); + pQmfOutReal[b] = scaleValueSaturate(real[b], lb_sf); } for (; b < fMin(usb, stop_band); b++) { - pQmfOutReal[b] = scaleValue(real[b], hb_sf); + pQmfOutReal[b] = scaleValueSaturate(real[b], hb_sf); } for (; b < stop_band; b++) { pQmfOutReal[b] = (FIXP_DBL)0; @@ -648,12 +648,12 @@ void FDK_QmfDomain_GetSlot(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, const int ts, } else { FDK_ASSERT(imag != NULL); for (; b < fMin(lsb, stop_band); b++) { - pQmfOutReal[b] = scaleValue(real[b], lb_sf); - pQmfOutImag[b] = scaleValue(imag[b], lb_sf); + pQmfOutReal[b] = scaleValueSaturate(real[b], lb_sf); + pQmfOutImag[b] = scaleValueSaturate(imag[b], lb_sf); } for (; b < fMin(usb, stop_band); b++) { - pQmfOutReal[b] = scaleValue(real[b], hb_sf); - pQmfOutImag[b] = scaleValue(imag[b], hb_sf); + pQmfOutReal[b] = scaleValueSaturate(real[b], hb_sf); + pQmfOutImag[b] = scaleValueSaturate(imag[b], hb_sf); } for (; b < stop_band; b++) { pQmfOutReal[b] = (FIXP_DBL)0; diff --git a/libPCMutils/include/limiter.h b/libPCMutils/include/limiter.h index fab7226..419e891 100644 --- a/libPCMutils/include/limiter.h +++ b/libPCMutils/include/limiter.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -109,8 +109,6 @@ amm-info@iis.fraunhofer.de #define TDL_ATTACK_DEFAULT_MS (15) /* default attack time in ms */ #define TDL_RELEASE_DEFAULT_MS (50) /* default release time in ms */ -#define TDL_GAIN_SCALING (15) /* scaling of gain value. */ - #ifdef __cplusplus extern "C" { #endif @@ -128,10 +126,7 @@ struct TDLimiter { unsigned int maxBufIdx, delayBufIdx; FIXP_DBL smoothState0; FIXP_DBL minGain; - - FIXP_DBL additionalGainPrev; - FIXP_DBL additionalGainFilterState; - FIXP_DBL additionalGainFilterState1; + INT scaling; }; typedef enum { @@ -255,27 +250,16 @@ TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter, /****************************************************************************** * pcmLimiter_Apply * - * limiter: limiter handle * - * pGain : pointer to gains to be applied to the signal before limiting, * - * which are downscaled by TDL_GAIN_SCALING bit. * - * These gains are delayed by gain_delay, and smoothed. * - * Smoothing is done by a butterworth lowpass filter with a cutoff * - * frequency which is fixed with respect to the sampling rate. * - * It is a substitute for the smoothing due to windowing and * - * overlap/add, if a gain is applied in frequency domain. * - * gain_scale: pointer to scaling exponents to be applied to the signal before * - * limiting, without delay and without smoothing * - * gain_size: number of elements in pGain, currently restricted to 1 * - * gain_delay: delay [samples] with which the gains in pGain shall be applied * - * gain_delay <= nSamples * - * samples: input/output buffer containing interleaved samples * - * precision of output will be DFRACT_BITS-TDL_GAIN_SCALING bits * - * nSamples: number of samples per channel * + * limiter: limiter handle * + * samplesIn: pointer to input buffer containing interleaved samples * + * samplesOut: pointer to output buffer containing interleaved samples * + * pGainPerSample: pointer to gains for each sample * + * scaling: scaling of output samples * + * nSamples: number of samples per channel * * returns: error code * ******************************************************************************/ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn, - INT_PCM* samplesOut, FIXP_DBL* pGain, - const INT* gain_scale, const UINT gain_size, - const UINT gain_delay, const UINT nSamples); + INT_PCM* samplesOut, FIXP_DBL* pGainPerSample, + const INT scaling, const UINT nSamples); #endif /* #ifndef LIMITER_H */ diff --git a/libPCMutils/src/limiter.cpp b/libPCMutils/src/limiter.cpp index 60e3e3b..598dc0c 100644 --- a/libPCMutils/src/limiter.cpp +++ b/libPCMutils/src/limiter.cpp @@ -152,7 +152,7 @@ TDLimiterPtr pcmLimiter_Create(unsigned int maxAttackMs, unsigned int releaseMs, limiter->attack = attack; limiter->attackConst = attackConst; limiter->releaseConst = releaseConst; - limiter->threshold = threshold >> TDL_GAIN_SCALING; + limiter->threshold = threshold; limiter->channels = maxChannels; limiter->maxChannels = maxChannels; limiter->sampleRate = maxSampleRate; @@ -165,18 +165,13 @@ TDLimiterPtr pcmLimiter_Create(unsigned int maxAttackMs, unsigned int releaseMs, /* apply limiter */ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn, - INT_PCM* samplesOut, FIXP_DBL* RESTRICT pGain, - const INT* RESTRICT gain_scale, - const UINT gain_size, const UINT gain_delay, - const UINT nSamples) { + INT_PCM* samplesOut, FIXP_DBL* pGainPerSample, + const INT scaling, const UINT nSamples) { unsigned int i, j; - FIXP_DBL tmp1; FIXP_DBL tmp2; - FIXP_DBL tmp, old, gain, additionalGain = 0, additionalGainUnfiltered; + FIXP_DBL tmp, old, gain, additionalGain = 0; FIXP_DBL minGain = FL2FXCONST_DBL(1.0f / (1 << 1)); - - FDK_ASSERT(gain_size == 1); - FDK_ASSERT(gain_delay <= nSamples); + UINT additionalGainAvailable = 1; if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; @@ -185,7 +180,7 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn, unsigned int attack = limiter->attack; FIXP_DBL attackConst = limiter->attackConst; FIXP_DBL releaseConst = limiter->releaseConst; - FIXP_DBL threshold = limiter->threshold; + FIXP_DBL threshold = limiter->threshold >> scaling; FIXP_DBL max = limiter->max; FIXP_DBL* maxBuf = limiter->maxBuf; @@ -195,55 +190,34 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn, unsigned int delayBufIdx = limiter->delayBufIdx; FIXP_DBL smoothState0 = limiter->smoothState0; - FIXP_DBL additionalGainSmoothState = limiter->additionalGainFilterState; - FIXP_DBL additionalGainSmoothState1 = limiter->additionalGainFilterState1; - if (!gain_delay) { - additionalGain = pGain[0]; - if (gain_scale[0] > 0) { - additionalGain <<= gain_scale[0]; - } else { - additionalGain >>= -gain_scale[0]; - } + if (limiter->scaling != scaling) { + scaleValuesSaturate(delayBuf, attack * channels, + limiter->scaling - scaling); + scaleValuesSaturate(maxBuf, attack + 1, limiter->scaling - scaling); + max = scaleValueSaturate(max, limiter->scaling - scaling); + limiter->scaling = scaling; } - for (i = 0; i < nSamples; i++) { - if (gain_delay) { - if (i < gain_delay) { - additionalGainUnfiltered = limiter->additionalGainPrev; - } else { - additionalGainUnfiltered = pGain[0]; - } + if (pGainPerSample == NULL) { + additionalGainAvailable = 0; + } - /* Smooth additionalGain */ - /* [b,a] = butter(1, 0.01) */ - static const FIXP_SGL b[] = {FL2FXCONST_SGL(0.015466 * 2.0), - FL2FXCONST_SGL(0.015466 * 2.0)}; - static const FIXP_SGL a[] = {(FIXP_SGL)MAXVAL_SGL, - FL2FXCONST_SGL(-0.96907)}; - additionalGain = -fMult(additionalGainSmoothState, a[1]) + - fMultDiv2(additionalGainUnfiltered, b[0]) + - fMultDiv2(additionalGainSmoothState1, b[1]); - additionalGainSmoothState1 = additionalGainUnfiltered; - additionalGainSmoothState = additionalGain; - - /* Apply the additional scaling that has no delay and no smoothing */ - if (gain_scale[0] > 0) { - additionalGain <<= gain_scale[0]; - } else { - additionalGain >>= -gain_scale[0]; - } - } + for (i = 0; i < nSamples; i++) { /* get maximum absolute sample value of all channels, including the * additional gain. */ - tmp1 = (FIXP_DBL)0; + tmp = (FIXP_DBL)0; for (j = 0; j < channels; j++) { tmp2 = PCM_LIM2FIXP_DBL(samplesIn[j]); tmp2 = (tmp2 == (FIXP_DBL)MINVAL_DBL) ? (FIXP_DBL)MAXVAL_DBL : fAbs(tmp2); - tmp1 = fMax(tmp1, tmp2); + tmp = fMax(tmp, tmp2); + } + + if (additionalGainAvailable) { + additionalGain = pGainPerSample[i]; + tmp = fMult(tmp, additionalGain); } - tmp = fMult(tmp1, additionalGain); /* set threshold as lower border to save calculations in running maximum * algorithm */ @@ -314,22 +288,42 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn, /* lookahead delay, apply gain */ for (j = 0; j < channels; j++) { tmp = p_delayBuf[j]; - p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain); + + if (additionalGainAvailable) { + p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain); + } else { + p_delayBuf[j] = PCM_LIM2FIXP_DBL(samplesIn[j]); + } /* Apply gain to delayed signal */ tmp = fMultDiv2(tmp, gain); - +#if (SAMPLE_BITS == DFRACT_BITS) + samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM( + (FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling + 1, DFRACT_BITS)); +#else samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT( - tmp, TDL_GAIN_SCALING + 1, DFRACT_BITS)); + tmp + ((FIXP_DBL)0x8000 >> (scaling + 1)), scaling + 1, + DFRACT_BITS)); +#endif } gain >>= 1; } else { /* lookahead delay, apply gain=1.0f */ for (j = 0; j < channels; j++) { tmp = p_delayBuf[j]; - p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain); + if (additionalGainAvailable) { + p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain); + } else { + p_delayBuf[j] = PCM_LIM2FIXP_DBL(samplesIn[j]); + } + +#if (SAMPLE_BITS == DFRACT_BITS) + samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM( + (FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling, DFRACT_BITS)); +#else samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT( - tmp, TDL_GAIN_SCALING, DFRACT_BITS)); + tmp + ((FIXP_DBL)0x8000 >> scaling), scaling, DFRACT_BITS)); +#endif } } @@ -354,13 +348,9 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn, limiter->delayBufIdx = delayBufIdx; limiter->smoothState0 = smoothState0; - limiter->additionalGainFilterState = additionalGainSmoothState; - limiter->additionalGainFilterState1 = additionalGainSmoothState1; limiter->minGain = minGain; - limiter->additionalGainPrev = pGain[0]; - return TDLIMIT_OK; } } @@ -370,7 +360,7 @@ TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter, FIXP_DBL threshold) { if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; - limiter->threshold = threshold >> TDL_GAIN_SCALING; + limiter->threshold = threshold; return TDLIMIT_OK; } @@ -384,13 +374,7 @@ TDLIMITER_ERROR pcmLimiter_Reset(TDLimiterPtr limiter) { limiter->cor = FL2FXCONST_DBL(1.0f / (1 << 1)); limiter->smoothState0 = FL2FXCONST_DBL(1.0f / (1 << 1)); limiter->minGain = FL2FXCONST_DBL(1.0f / (1 << 1)); - - limiter->additionalGainPrev = - FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING)); - limiter->additionalGainFilterState = - FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING)); - limiter->additionalGainFilterState1 = - FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING)); + limiter->scaling = 0; FDKmemset(limiter->maxBuf, 0, (limiter->attack + 1) * sizeof(FIXP_DBL)); FDKmemset(limiter->delayBuf, 0, diff --git a/libPCMutils/src/version.h b/libPCMutils/src/version.h index fa31af1..05371f8 100644 --- a/libPCMutils/src/version.h +++ b/libPCMutils/src/version.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -105,7 +105,7 @@ amm-info@iis.fraunhofer.de /* library info */ #define PCMUTIL_LIB_VL0 3 -#define PCMUTIL_LIB_VL1 0 +#define PCMUTIL_LIB_VL1 1 #define PCMUTIL_LIB_VL2 0 #define PCMUTIL_LIB_TITLE "PCM Utility Lib" #ifdef __ANDROID__ diff --git a/libSACdec/include/sac_dec_lib.h b/libSACdec/include/sac_dec_lib.h index 9913279..1827504 100644 --- a/libSACdec/include/sac_dec_lib.h +++ b/libSACdec/include/sac_dec_lib.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -252,7 +252,7 @@ typedef enum { scenario. Default parameter value is 3 frames. */ } SACDEC_PARAM; -#define PCM_MPS INT_PCM +#define PCM_MPS LONG /** * \brief MPEG Surround decoder handle. @@ -401,17 +401,22 @@ int mpegSurroundDecoder_Parse(CMpegSurroundDecoder *pMpegSurroundDecoder, * for each output audio channel is stored into. * \param mapDescr Channep map descriptor for output channel mapping * to be used (From MPEG PCE ordering to whatever is required). + * \param inDataHeadroom Headroom of SAC input time signal to prevent + * clipping. + * \param outDataHeadroom Pointer to headroom of SAC output time signal to + * prevent clipping. * * \return Error code. */ int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder, - INT_PCM *input, PCM_MPS *pTimeData, + PCM_MPS *input, PCM_MPS *pTimeData, const int timeDataSize, int timeDataFrameSize, int *nChannels, int *frameSize, int sampleRate, AUDIO_OBJECT_TYPE coreCodec, AUDIO_CHANNEL_TYPE channelType[], UCHAR channelIndices[], - const FDK_channelMapDescr *const mapDescr); + const FDK_channelMapDescr *const mapDescr, + const INT inDataHeadroom, INT *outDataHeadroom); /** * \brief Deallocate a MPEG Surround decoder instance. diff --git a/libSACdec/src/sac_dec.cpp b/libSACdec/src/sac_dec.cpp index c1832f1..a7b50df 100644 --- a/libSACdec/src/sac_dec.cpp +++ b/libSACdec/src/sac_dec.cpp @@ -766,7 +766,7 @@ SACDEC_ERROR FDK_SpatialDecInit(spatialDec *self, SPATIAL_BS_FRAME *frame, /* output scaling */ for (nCh = 0; nCh < self->numOutputChannelsAT; nCh++) { - int outputScale = 0, outputGain_e = 0, scale = 0; + int outputScale = 0, outputGain_e = 0, scale = -(8) + (1); FIXP_DBL outputGain_m = getChGain(self, nCh, &outputGain_e); if (!isTwoChMode(self->upmixType) && !bypassMode) { @@ -775,7 +775,7 @@ SACDEC_ERROR FDK_SpatialDecInit(spatialDec *self, SPATIAL_BS_FRAME *frame, synthesis qmf */ } - scale = outputScale; + scale += outputScale; qmfChangeOutScalefactor(&self->pQmfDomain->QmfDomainOut[nCh].fb, scale); qmfChangeOutGain(&self->pQmfDomain->QmfDomainOut[nCh].fb, outputGain_m, @@ -1223,18 +1223,24 @@ static SACDEC_ERROR SpatialDecApplyParameterSets( !(self->stereoConfigIndex == 3)) { for (i = 0; i < self->qmfBands; i++) { self_qmfResidualReal__FDK_0_0[i] = - fMult(self_qmfResidualReal__FDK_0_0[i] << 1, + fMult(scaleValueSaturate(self_qmfResidualReal__FDK_0_0[i], + 1 + self->sacInDataHeadroom - (1)), self->clipProtectGain__FDK); self_qmfResidualImag__FDK_0_0[i] = - fMult(self_qmfResidualImag__FDK_0_0[i] << 1, + fMult(scaleValueSaturate(self_qmfResidualImag__FDK_0_0[i], + 1 + self->sacInDataHeadroom - (1)), self->clipProtectGain__FDK); } } else { for (i = 0; i < self->qmfBands; i++) { - self_qmfResidualReal__FDK_0_0[i] = fMult( - self_qmfResidualReal__FDK_0_0[i], self->clipProtectGain__FDK); - self_qmfResidualImag__FDK_0_0[i] = fMult( - self_qmfResidualImag__FDK_0_0[i], self->clipProtectGain__FDK); + self_qmfResidualReal__FDK_0_0[i] = + fMult(scaleValueSaturate(self_qmfResidualReal__FDK_0_0[i], + self->sacInDataHeadroom - (1)), + self->clipProtectGain__FDK); + self_qmfResidualImag__FDK_0_0[i] = + fMult(scaleValueSaturate(self_qmfResidualImag__FDK_0_0[i], + self->sacInDataHeadroom - (1)), + self->clipProtectGain__FDK); } } } @@ -1416,6 +1422,7 @@ SACDEC_ERROR SpatialDecApplyFrame( FDK_ASSERT(self != NULL); FDK_ASSERT(pControlFlags != NULL); FDK_ASSERT(pcmOutBuf != NULL); + FDK_ASSERT(self->sacInDataHeadroom >= (1)); self->errInt = err; /* Init internal error */ diff --git a/libSACdec/src/sac_dec.h b/libSACdec/src/sac_dec.h index 992acad..1c3df71 100644 --- a/libSACdec/src/sac_dec.h +++ b/libSACdec/src/sac_dec.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -523,6 +523,9 @@ struct spatialDec_struct { new frame after SSC change (aka decodeAfterConfigHasChangedFlag). */ SpatialDecConcealmentInfo concealInfo; + + INT sacInDataHeadroom; /* Headroom of the SAC input time signal to prevent + clipping */ }; #define SACDEC_SYNTAX_MPS 1 diff --git a/libSACdec/src/sac_dec_interface.h b/libSACdec/src/sac_dec_interface.h index a2eea92..05a9a75 100644 --- a/libSACdec/src/sac_dec_interface.h +++ b/libSACdec/src/sac_dec_interface.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -249,10 +249,10 @@ typedef struct { } MEM_REQUIREMENTS; -#define PCM_MPS INT_PCM -#define PCM_MPSF FIXP_PCM +#define PCM_MPS LONG +#define PCM_MPSF FIXP_DBL -#define FIXP_DBL2PCM_MPS(x) ((INT_PCM)FX_DBL2FX_PCM(x)) +#define FIXP_DBL2PCM_MPS(x) ((LONG)(x)) /* exposed functions (library interface) */ diff --git a/libSACdec/src/sac_dec_lib.cpp b/libSACdec/src/sac_dec_lib.cpp index bf6dedf..856a923 100644 --- a/libSACdec/src/sac_dec_lib.cpp +++ b/libSACdec/src/sac_dec_lib.cpp @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -1507,15 +1507,17 @@ bail: } int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder, - INT_PCM *input, PCM_MPS *pTimeData, + PCM_MPS *input, PCM_MPS *pTimeData, const int timeDataSize, int timeDataFrameSize, int *nChannels, int *frameSize, int sampleRate, AUDIO_OBJECT_TYPE coreCodec, AUDIO_CHANNEL_TYPE channelType[], UCHAR channelIndices[], - const FDK_channelMapDescr *const mapDescr) { + const FDK_channelMapDescr *const mapDescr, + const INT inDataHeadroom, INT *outDataHeadroom) { SACDEC_ERROR err = MPS_OK; PCM_MPS *pTimeOut = pTimeData; + PCM_MPS *TDinput = NULL; UINT initControlFlags = 0, controlFlags = 0; int timeDataRequiredSize = 0; int newData; @@ -1534,6 +1536,9 @@ int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder, return MPS_NOTOK; } + pMpegSurroundDecoder->pSpatialDec->sacInDataHeadroom = inDataHeadroom; + *outDataHeadroom = (INT)(8); + pMpegSurroundDecoder->pSpatialDec->pConfigCurrent = &pMpegSurroundDecoder ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode]; @@ -1682,8 +1687,7 @@ int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder, (timeDataFrameSize * pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsSynthesis) / pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis; - pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput = - pTimeData + timeDataFrameSizeOut - timeDataFrameSize; + TDinput = pTimeData + timeDataFrameSizeOut - timeDataFrameSize; for (int i = *nChannels - 1; i >= 0; i--) { FDKmemmove(pTimeData + (i + 1) * timeDataFrameSizeOut - timeDataFrameSize, pTimeData + timeDataFrameSize * i, @@ -1694,8 +1698,8 @@ int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder, } else { if (pMpegSurroundDecoder->mpegSurroundUseTimeInterface) { FDKmemcpy(input, pTimeData, - sizeof(INT_PCM) * (*nChannels) * (*frameSize)); - pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput = input; + sizeof(PCM_MPS) * (*nChannels) * (*frameSize)); + TDinput = input; } } @@ -1707,8 +1711,8 @@ int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder, &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode], pMpegSurroundDecoder->mpegSurroundUseTimeInterface ? INPUTMODE_TIME : INPUTMODE_QMF_SBR, - pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput, NULL, NULL, - pTimeOut, *frameSize, &controlFlags, *nChannels, mapDescr); + TDinput, NULL, NULL, pTimeOut, *frameSize, &controlFlags, *nChannels, + mapDescr); *nChannels = pMpegSurroundDecoder->pSpatialDec->numOutputChannelsAT; if (err != @@ -1781,7 +1785,7 @@ void mpegSurroundDecoder_Close(CMpegSurroundDecoder *pMpegSurroundDecoder) { } #define SACDEC_VL0 2 -#define SACDEC_VL1 0 +#define SACDEC_VL1 1 #define SACDEC_VL2 0 int mpegSurroundDecoder_GetLibInfo(LIB_INFO *info) { diff --git a/libSACdec/src/sac_process.cpp b/libSACdec/src/sac_process.cpp index 95128f3..22091a9 100644 --- a/libSACdec/src/sac_process.cpp +++ b/libSACdec/src/sac_process.cpp @@ -187,8 +187,12 @@ SACDEC_ERROR SpatialDecQMFAnalysis(spatialDec *self, const PCM_MPS *inData, if (!isTwoChMode(self->upmixType) && !bypassMode) { int i; for (i = 0; i < self->qmfBands; i++) { - qmfReal[ch][i] = fMult(qmfReal[ch][i], self->clipProtectGain__FDK); - qmfImag[ch][i] = fMult(qmfImag[ch][i], self->clipProtectGain__FDK); + qmfReal[ch][i] = fMult( + scaleValueSaturate(qmfReal[ch][i], self->sacInDataHeadroom - (1)), + self->clipProtectGain__FDK); + qmfImag[ch][i] = fMult( + scaleValueSaturate(qmfImag[ch][i], self->sacInDataHeadroom - (1)), + self->clipProtectGain__FDK); } } } @@ -216,16 +220,17 @@ SACDEC_ERROR SpatialDecFeedQMF(spatialDec *self, FIXP_DBL **qmfInDataReal, /* Write Input data to pQmfRealAnalysis. */ if (self->bShareDelayWithSBR) { - FDK_QmfDomain_GetSlot( - &self->pQmfDomain->QmfDomainIn[ch], ts + HYBRID_FILTER_DELAY, 0, - MAX_QMF_BANDS_TO_HYBRID, pQmfRealAnalysis, pQmfImagAnalysis, 15); + FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], + ts + HYBRID_FILTER_DELAY, 0, + MAX_QMF_BANDS_TO_HYBRID, pQmfRealAnalysis, + pQmfImagAnalysis, 15 + (1)); FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, MAX_QMF_BANDS_TO_HYBRID, self->qmfBands, - pQmfRealAnalysis, pQmfImagAnalysis, 15); + pQmfRealAnalysis, pQmfImagAnalysis, 15 + (1)); } else { FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, 0, self->qmfBands, pQmfRealAnalysis, - pQmfImagAnalysis, 15); + pQmfImagAnalysis, 15 + (1)); } if (ts == self->pQmfDomain->globalConf.nQmfTimeSlots - 1) { /* Is currently also needed in case we dont have any overlap. We need to @@ -501,8 +506,8 @@ SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding( for (pb = 0, qs = 3; pb < 2; pb++) { INT s; FIXP_DBL maxVal; - FIXP_SGL mReal1; - FIXP_SGL mReal0, mImag0; + FIXP_DBL mReal1; + FIXP_DBL mReal0, mImag0; FIXP_DBL iReal0, iImag0, iReal1; iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]); @@ -515,9 +520,9 @@ SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding( s = fMax(CntLeadingZeros(maxVal) - 1, 0); s = fMin(s, scale_param_m2); - mReal0 = FX_DBL2FX_SGL(iReal0 << s); - mImag0 = FX_DBL2FX_SGL(iImag0 << s); - mReal1 = FX_DBL2FX_SGL(iReal1 << s); + mReal0 = iReal0 << s; + mImag0 = iImag0 << s; + mReal1 = iReal1 << s; s = scale_param_m2 - s; @@ -934,6 +939,7 @@ SACDEC_ERROR SpatialDecSynthesis(spatialDec *self, const INT ts, self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= self->clipProtectGainSF__FDK; + self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= (1); } else { /* Call the QMF synthesis for dry. */ err = CalculateSpaceSynthesisQmf(&self->pQmfDomain->QmfDomainOut[outCh], diff --git a/libSACdec/src/sac_qmf.cpp b/libSACdec/src/sac_qmf.cpp index a075490..fd7599d 100644 --- a/libSACdec/src/sac_qmf.cpp +++ b/libSACdec/src/sac_qmf.cpp @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -110,7 +110,7 @@ amm-info@iis.fraunhofer.de SACDEC_ERROR CalculateSpaceSynthesisQmf( const HANDLE_FDK_QMF_DOMAIN_OUT hQmfDomainOutCh, const FIXP_DBL *Sr, - const FIXP_DBL *Si, const INT stride, INT_PCM *timeSig) { + const FIXP_DBL *Si, const INT stride, PCM_MPS *timeSig) { SACDEC_ERROR err = MPS_OK; if (hQmfDomainOutCh == NULL) { diff --git a/libSACdec/src/sac_qmf.h b/libSACdec/src/sac_qmf.h index d1dc837..5cd573e 100644 --- a/libSACdec/src/sac_qmf.h +++ b/libSACdec/src/sac_qmf.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -124,7 +124,7 @@ amm-info@iis.fraunhofer.de */ SACDEC_ERROR CalculateSpaceSynthesisQmf( const HANDLE_FDK_QMF_DOMAIN_OUT hQmfDomainOutCh, const FIXP_DBL *Sr, - const FIXP_DBL *Si, const INT stride, INT_PCM *timeSig); + const FIXP_DBL *Si, const INT stride, PCM_MPS *timeSig); /** * \brief Convert audio input data to qmf representation. diff --git a/libSACdec/src/sac_reshapeBBEnv.cpp b/libSACdec/src/sac_reshapeBBEnv.cpp index b44ce4e..272d009 100644 --- a/libSACdec/src/sac_reshapeBBEnv.cpp +++ b/libSACdec/src/sac_reshapeBBEnv.cpp @@ -253,17 +253,17 @@ static inline void slotAmp(FIXP_DBL *RESTRICT slotAmp_dry, dry = wet = FL2FXCONST_DBL(0.0f); for (qs = 0; qs < cplxBands; qs++) { - dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs]) + - fPow2Div2(pHybOutputImagDry[qs])); - wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs]) + - fPow2Div2(pHybOutputImagWet[qs])); + dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs] << (1)) + + fPow2Div2(pHybOutputImagDry[qs] << (1))); + wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs] << (1)) + + fPow2Div2(pHybOutputImagWet[qs] << (1))); } for (; qs < hybBands; qs++) { - dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs])); - wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs])); + dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs] << (1))); + wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs] << (1))); } - *slotAmp_dry = dry; - *slotAmp_wet = wet; + *slotAmp_dry = dry >> (2 * (1)); + *slotAmp_wet = wet >> (2 * (1)); } #if defined(__aarch64__) @@ -327,7 +327,7 @@ static void extractBBEnv(spatialDec *self, INT inp, INT start, INT channels, INT shapeActiv = 1; INT hybBands = fixMin(42, self->hybridBands); - INT staticScale = self->staticDecScale; + INT staticScale = self->staticDecScale + (1); INT cplxBands; cplxBands = fixMin(42, self->hybridBands); diff --git a/libSACdec/src/sac_rom.h b/libSACdec/src/sac_rom.h index 38f17f2..d317856 100644 --- a/libSACdec/src/sac_rom.h +++ b/libSACdec/src/sac_rom.h @@ -111,21 +111,12 @@ amm-info@iis.fraunhofer.de #include "machine_type.h" /* Global ROM table data type: */ -#ifndef ARCH_PREFER_MULT_32x32 -#define FIXP_CFG FIXP_SGL -#define FX_CFG2FX_DBL FX_SGL2FX_DBL -#define FX_CFG2FX_SGL -#define CFG(a) (FX_DBL2FXCONST_SGL(a)) -#define FL2FXCONST_CFG FL2FXCONST_SGL -#define FX_DBL2FX_CFG(x) FX_DBL2FX_SGL((FIXP_DBL)(x)) -#else #define FIXP_CFG FIXP_DBL #define FX_CFG2FX_DBL #define FX_CFG2FX_SGL FX_DBL2FX_SGL #define CFG(a) FIXP_DBL(a) #define FL2FXCONST_CFG FL2FXCONST_DBL #define FX_DBL2FX_CFG(x) ((FIXP_DBL)(x)) -#endif /* others */ #define SCALE_INV_ICC (2) @@ -133,15 +124,9 @@ amm-info@iis.fraunhofer.de #define QCC_SCALE 1 #define M1M2_DATA FIXP_DBL -#ifndef ARCH_PREFER_MULT_32x32 -#define M1M2_CDATA FIXP_SGL -#define M1M2_CDATA2FX_DBL(a) FX_SGL2FX_DBL(a) -#define FX_DBL2M1M2_CDATA(a) FX_DBL2FX_SGL(a) -#else #define M1M2_CDATA FIXP_DBL #define M1M2_CDATA2FX_DBL(a) (a) #define FX_DBL2M1M2_CDATA(a) (a) -#endif #define CLIP_PROTECT_GAIN_0(x) FL2FXCONST_CFG(((x) / (float)(1 << 0))) #define CLIP_PROTECT_GAIN_1(x) FL2FXCONST_CFG(((x) / (float)(1 << 1))) diff --git a/libSBRdec/include/sbrdecoder.h b/libSBRdec/include/sbrdecoder.h index cc55572..c09c985 100644 --- a/libSBRdec/include/sbrdecoder.h +++ b/libSBRdec/include/sbrdecoder.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -361,15 +361,20 @@ SBR_ERROR sbrDecoder_Parse(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs, * error (0: core decoder found errors, 1: no errors). * \param psDecoded Pointer to a buffer holding a flag. Input: PS is * possible, Output: PS has been rendered. + * \param inDataHeadroom Headroom of the SBR input time signal to prevent + * clipping. + * \param outDataHeadroom Pointer to headroom of the SBR output time signal to + * prevent clipping. * * \return Error code. */ -SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, INT_PCM *input, - INT_PCM *timeData, const int timeDataSize, - int *numChannels, int *sampleRate, +SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, LONG *input, LONG *timeData, + const int timeDataSize, int *numChannels, + int *sampleRate, const FDK_channelMapDescr *const mapDescr, const int mapIdx, const int coreDecodedOk, - UCHAR *psDecoded); + UCHAR *psDecoded, const INT inDataHeadroom, + INT *outDataHeadroom); /** * \brief Close SBR decoder instance and free memory. diff --git a/libSBRdec/src/HFgen_preFlat.cpp b/libSBRdec/src/HFgen_preFlat.cpp index 268011e..ad4caba 100644 --- a/libSBRdec/src/HFgen_preFlat.cpp +++ b/libSBRdec/src/HFgen_preFlat.cpp @@ -897,10 +897,10 @@ void sbrDecoder_calculateGainVec(FIXP_DBL **sourceBufferReal, for (i = startSample; i < stopSample; i++) { maxVal |= (FIXP_DBL)((LONG)(sourceBufferReal[i][loBand]) ^ - ((LONG)sourceBufferReal[i][loBand] >> (SAMPLE_BITS - 1))); + ((LONG)sourceBufferReal[i][loBand] >> (DFRACT_BITS - 1))); maxVal |= (FIXP_DBL)((LONG)(sourceBufferImag[i][loBand]) ^ - ((LONG)sourceBufferImag[i][loBand] >> (SAMPLE_BITS - 1))); + ((LONG)sourceBufferImag[i][loBand] >> (DFRACT_BITS - 1))); } if (maxVal != FL2FX_DBL(0.0f)) { diff --git a/libSBRdec/src/hbe.cpp b/libSBRdec/src/hbe.cpp index 2284c42..d210bb6 100644 --- a/libSBRdec/src/hbe.cpp +++ b/libSBRdec/src/hbe.cpp @@ -957,7 +957,7 @@ QmfTransposerCreate(HANDLE_HBE_TRANSPOSER* hQmfTransposer, const int frameSize, hQmfTran->qmfOutBufSize = 2 * (hQmfTran->noCols / 2 + QMF_WIN_LEN - 1); hQmfTran->inBuf_F = - (INT_PCM*)FDKcalloc(QMF_SYNTH_CHANNELS + 20 + 1, sizeof(INT_PCM)); + (LONG*)FDKcalloc(QMF_SYNTH_CHANNELS + 20 + 1, sizeof(LONG)); /* buffered time signal needs to be delayed by synthesis_size; max * synthesis_size = 20; */ if (hQmfTran->inBuf_F == NULL) { diff --git a/libSBRdec/src/hbe.h b/libSBRdec/src/hbe.h index fdffe1e..3556783 100644 --- a/libSBRdec/src/hbe.h +++ b/libSBRdec/src/hbe.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -132,6 +132,9 @@ typedef enum { } KEEP_STATES_SYNCED_MODE; struct hbeTransposer { + FIXP_DBL anaQmfStates[HBE_QMF_FILTER_STATE_ANA_SIZE]; + FIXP_QSS synQmfStates[HBE_QMF_FILTER_STATE_SYN_SIZE]; + int xOverQmf[MAX_NUM_PATCHES_HBE]; int maxStretch; @@ -144,7 +147,7 @@ struct hbeTransposer { int stopBand; int bSbr41; - INT_PCM *inBuf_F; + LONG *inBuf_F; FIXP_DBL **qmfInBufReal_F; FIXP_DBL **qmfInBufImag_F; @@ -156,9 +159,6 @@ struct hbeTransposer { FIXP_DBL const *synthesisQmfPreModCos_F; FIXP_DBL const *synthesisQmfPreModSin_F; - FIXP_QAS anaQmfStates[HBE_QMF_FILTER_STATE_ANA_SIZE]; - FIXP_QSS synQmfStates[HBE_QMF_FILTER_STATE_SYN_SIZE]; - FIXP_DBL **qmfHBEBufReal_F; FIXP_DBL **qmfHBEBufImag_F; diff --git a/libSBRdec/src/sbr_dec.cpp b/libSBRdec/src/sbr_dec.cpp index 30611e7..b1fb0da 100644 --- a/libSBRdec/src/sbr_dec.cpp +++ b/libSBRdec/src/sbr_dec.cpp @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -259,17 +259,18 @@ static void copyHarmonicSpectrum(int *xOverQmf, FIXP_DBL **qmfReal, void sbr_dec( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ - INT_PCM *timeIn, /*!< pointer to input time signal */ - INT_PCM *timeOut, /*!< pointer to output time signal */ + LONG *timeIn, /*!< pointer to input time signal */ + LONG *timeOut, /*!< pointer to output time signal */ HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ - INT_PCM *timeOutRight, /*!< pointer to output time signal */ + LONG *timeOutRight, /*!< pointer to output time signal */ const int strideOut, /*!< Time data traversal strideOut */ HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */ const int applyProcessing, /*!< Flag for SBR operation */ - HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize) { + HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize, + const INT sbrInDataHeadroom) { int i, slot, reserve; int saveLbScale; int lastSlotOffs; @@ -278,7 +279,7 @@ void sbr_dec( /* temporary pointer / variable for QMF; required as we want to use temporary buffer creating one frame delay for HBE in LP mode */ - INT_PCM *pTimeInQmf = timeIn; + LONG *pTimeInQmf = timeIn; /* Number of QMF timeslots in the overlap buffer: */ int ov_len = hSbrDec->LppTrans.pSettings->overlap; @@ -341,8 +342,8 @@ void sbr_dec( } else { C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2 * (64)); qmfAnalysisFiltering(&hSbrDec->qmfDomainInCh->fb, pReal, pImag, - &hSbrDec->qmfDomainInCh->scaling, pTimeInQmf, 0, 1, - qmfTemp); + &hSbrDec->qmfDomainInCh->scaling, pTimeInQmf, + 0 + sbrInDataHeadroom, 1, qmfTemp); C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2 * (64)); } @@ -658,7 +659,7 @@ void sbr_dec( if (!(flags & SBRDEC_PS_DECODED)) { if (!(flags & SBRDEC_SKIP_QMF_SYN)) { - int outScalefactor = 0; + int outScalefactor = -(8); if (h_ps_d != NULL) { h_ps_d->procFrameBased = 1; /* we here do frame based processing */ @@ -743,6 +744,7 @@ void sbr_dec( */ FDK_ASSERT(hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis <= QMF_MAX_SYNTHESIS_BANDS); + qmfChangeOutScalefactor(synQmfRight, -(8)); FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates, 9 * hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis * sizeof(FIXP_QSS)); @@ -814,7 +816,8 @@ void sbr_dec( : scaleFactorLowBand_no_ov, scaleFactorHighBand, synQmf->lsb, synQmf->usb); - outScalefactorL = outScalefactorR = 1; /* psDiffScale! (MPEG-PS) */ + outScalefactorL = outScalefactorR = + 1 + sbrInDataHeadroom; /* psDiffScale! (MPEG-PS) */ } sbrDecoder_drcApplySlot(/* right channel */ @@ -831,6 +834,9 @@ void sbr_dec( outScalefactorL += maxShift; if (!(flags & SBRDEC_SKIP_QMF_SYN)) { + qmfChangeOutScalefactor(synQmf, -(8)); + qmfChangeOutScalefactor(synQmfRight, -(8)); + qmfSynthesisFilteringSlot( synQmfRight, rQmfReal, /* QMF real buffer */ rQmfImag, /* QMF imag buffer */ diff --git a/libSBRdec/src/sbr_dec.h b/libSBRdec/src/sbr_dec.h index 156da03..eb9c394 100644 --- a/libSBRdec/src/sbr_dec.h +++ b/libSBRdec/src/sbr_dec.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -176,17 +176,18 @@ typedef SBR_CHANNEL *HANDLE_SBR_CHANNEL; void sbr_dec( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ - INT_PCM *timeIn, /*!< pointer to input time signal */ - INT_PCM *timeOut, /*!< pointer to output time signal */ + LONG *timeIn, /*!< pointer to input time signal */ + LONG *timeOut, /*!< pointer to output time signal */ HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ - INT_PCM *timeOutRight, /*!< pointer to output time signal */ + LONG *timeOutRight, /*!< pointer to output time signal */ INT strideOut, /*!< Time data traversal strideOut */ HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */ const int applyProcessing, /*!< Flag for SBR operation */ - HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize); + HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize, + const INT sbrInDataHeadroom); SBR_ERROR createSbrDec(SBR_CHANNEL *hSbrChannel, HANDLE_SBR_HEADER_DATA hHeaderData, diff --git a/libSBRdec/src/sbr_ram.h b/libSBRdec/src/sbr_ram.h index e00f8b5..452f835 100644 --- a/libSBRdec/src/sbr_ram.h +++ b/libSBRdec/src/sbr_ram.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -170,6 +170,9 @@ struct SBR_DECODER_INSTANCE { flushed consecutively. */ UINT flags; + + INT sbrInDataHeadroom; /* Headroom of the SBR input time signal to prevent + clipping */ }; H_ALLOC_MEM(Ram_SbrDecElement, SBR_DECODER_ELEMENT) diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp index 52403f6..6e4aad4 100644 --- a/libSBRdec/src/sbrdecoder.cpp +++ b/libSBRdec/src/sbrdecoder.cpp @@ -155,7 +155,7 @@ amm-info@iis.fraunhofer.de /* Decoder library info */ #define SBRDECODER_LIB_VL0 3 -#define SBRDECODER_LIB_VL1 0 +#define SBRDECODER_LIB_VL1 1 #define SBRDECODER_LIB_VL2 0 #define SBRDECODER_LIB_TITLE "SBR Decoder" #ifdef __ANDROID__ @@ -1570,10 +1570,10 @@ bail: * \return SBRDEC_OK if successfull, else error code */ static SBR_ERROR sbrDecoder_DecodeElement( - HANDLE_SBRDECODER self, QDOM_PCM *input, INT_PCM *timeData, - const int timeDataSize, const FDK_channelMapDescr *const mapDescr, - const int mapIdx, int channelIndex, const int elementIndex, - const int numInChannels, int *numOutChannels, const int psPossible) { + HANDLE_SBRDECODER self, LONG *input, LONG *timeData, const int timeDataSize, + const FDK_channelMapDescr *const mapDescr, const int mapIdx, + int channelIndex, const int elementIndex, const int numInChannels, + int *numOutChannels, const int psPossible) { SBR_DECODER_ELEMENT *hSbrElement = self->pSbrElement[elementIndex]; HANDLE_SBR_CHANNEL *pSbrChannel = self->pSbrElement[elementIndex]->pSbrChannel; @@ -1743,7 +1743,7 @@ static SBR_ERROR sbrDecoder_DecodeElement( timeData + offset1, strideOut, hSbrHeader, hFrameDataLeft, &pSbrChannel[0]->prevFrameData, (hSbrHeader->syncState == SBR_ACTIVE), h_ps_d, self->flags, - codecFrameSize); + codecFrameSize, self->sbrInDataHeadroom); if (stereo) { /* Process right channel */ @@ -1751,7 +1751,7 @@ static SBR_ERROR sbrDecoder_DecodeElement( timeData + offset1, NULL, NULL, strideOut, hSbrHeader, hFrameDataRight, &pSbrChannel[1]->prevFrameData, (hSbrHeader->syncState == SBR_ACTIVE), NULL, self->flags, - codecFrameSize); + codecFrameSize, self->sbrInDataHeadroom); } C_ALLOC_SCRATCH_END(pPsScratch, struct PS_DEC_COEFFICIENTS, 1) @@ -1771,14 +1771,14 @@ static SBR_ERROR sbrDecoder_DecodeElement( int copyFrameSize = codecFrameSize * self->pQmfDomain->QmfDomainOut->fb.no_channels; copyFrameSize /= self->pQmfDomain->QmfDomainIn->fb.no_channels; - INT_PCM *ptr; + LONG *ptr; INT i; FDK_ASSERT(strideOut == 2); ptr = timeData; for (i = copyFrameSize >> 1; i--;) { - INT_PCM tmp; /* This temporal variable is required because some - compilers can't do *ptr++ = *ptr++ correctly. */ + LONG tmp; /* This temporal variable is required because some compilers + can't do *ptr++ = *ptr++ correctly. */ tmp = *ptr++; *ptr++ = tmp; tmp = *ptr++; @@ -1791,12 +1791,13 @@ static SBR_ERROR sbrDecoder_DecodeElement( return errorStatus; } -SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, INT_PCM *input, - INT_PCM *timeData, const int timeDataSize, - int *numChannels, int *sampleRate, +SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, LONG *input, LONG *timeData, + const int timeDataSize, int *numChannels, + int *sampleRate, const FDK_channelMapDescr *const mapDescr, const int mapIdx, const int coreDecodedOk, - UCHAR *psDecoded) { + UCHAR *psDecoded, const INT inDataHeadroom, + INT *outDataHeadroom) { SBR_ERROR errorStatus = SBRDEC_OK; int psPossible; @@ -1833,6 +1834,9 @@ SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, INT_PCM *input, psPossible = 0; } + self->sbrInDataHeadroom = inDataHeadroom; + *outDataHeadroom = (INT)(8); + /* Make sure that even if no SBR data was found/parsed *psDecoded is returned * 1 if psPossible was 0. */ if (psPossible == 0) { -- cgit v1.2.3