summaryrefslogtreecommitdiffstats
path: root/libAACdec/src/aacdec_drc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libAACdec/src/aacdec_drc.cpp')
-rw-r--r--libAACdec/src/aacdec_drc.cpp1063
1 files changed, 1063 insertions, 0 deletions
diff --git a/libAACdec/src/aacdec_drc.cpp b/libAACdec/src/aacdec_drc.cpp
new file mode 100644
index 0000000..c660b83
--- /dev/null
+++ b/libAACdec/src/aacdec_drc.cpp
@@ -0,0 +1,1063 @@
+
+/* -----------------------------------------------------------------------------------------------------------
+Software License for The Fraunhofer FDK AAC Codec Library for Android
+
+© Copyright 1995 - 2012 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+ All rights reserved.
+
+ 1. INTRODUCTION
+The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
+the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
+This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
+
+AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
+audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
+independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
+of the MPEG specifications.
+
+Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
+may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
+individually for the purpose of encoding or decoding bit streams in products that are compliant with
+the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
+these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
+software may already be covered under those patent licenses when it is used for those licensed purposes only.
+
+Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
+are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
+applications information and documentation.
+
+2. COPYRIGHT LICENSE
+
+Redistribution and use in source and binary forms, with or without modification, are permitted without
+payment of copyright license fees provided that you satisfy the following conditions:
+
+You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
+your modifications thereto in source code form.
+
+You must retain the complete text of this software license in the documentation and/or other materials
+provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
+You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
+modifications thereto to recipients of copies in binary form.
+
+The name of Fraunhofer may not be used to endorse or promote products derived from this library without
+prior written permission.
+
+You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
+software or your modifications thereto.
+
+Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
+and the date of any change. For modified versions of the FDK AAC Codec, the term
+"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
+"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
+
+3. NO PATENT LICENSE
+
+NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
+ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
+respect to this software.
+
+You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
+by appropriate patent licenses.
+
+4. DISCLAIMER
+
+This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
+"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
+of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
+including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
+or business interruption, however caused and on any theory of liability, whether in contract, strict
+liability, or tort (including negligence), arising in any way out of the use of this software, even if
+advised of the possibility of such damage.
+
+5. CONTACT INFORMATION
+
+Fraunhofer Institute for Integrated Circuits IIS
+Attention: Audio and Multimedia Departments - FDK AAC LL
+Am Wolfsmantel 33
+91058 Erlangen, Germany
+
+www.iis.fraunhofer.de/amm
+amm-info@iis.fraunhofer.de
+----------------------------------------------------------------------------------------------------------- */
+
+/***************************** MPEG-4 AAC Decoder **************************
+
+ Author(s): Christian Griebel
+ Description: Dynamic range control (DRC) decoder tool for AAC
+
+******************************************************************************/
+
+#include "aacdec_drc.h"
+
+
+#include "channelinfo.h"
+#include "aac_rom.h"
+
+ #include "sbrdecoder.h"
+
+/*
+ * Dynamic Range Control
+ */
+
+/* For parameter conversion */
+#define DRC_PARAMETER_BITS ( 7 )
+#define DRC_MAX_QUANT_STEPS ( 1<<DRC_PARAMETER_BITS )
+#define DRC_MAX_QUANT_FACTOR ( DRC_MAX_QUANT_STEPS-1 )
+#define DRC_PARAM_QUANT_STEP ( FL2FXCONST_DBL(1.0f/(float)DRC_MAX_QUANT_FACTOR) )
+#define DRC_PARAM_SCALE ( 1 )
+
+#define MAX_REFERENCE_LEVEL ( 127 )
+
+ #define DVB_ANC_DATA_SYNC_BYTE ( 0xBC ) /* DVB ancillary data sync byte. */
+
+/*!
+ \brief Initialize DRC information
+
+ \self Handle of DRC info
+
+ \return none
+*/
+void aacDecoder_drcInit (
+ HANDLE_AAC_DRC self )
+{
+ CDrcParams *pParams;
+
+ if (self == NULL) {
+ return;
+ }
+
+ /* init control fields */
+ self->enable = 0;
+ self->numThreads = 0;
+ self->digitalNorm = 0;
+
+ /* init params */
+ pParams = &self->params;
+ pParams->bsDelayEnable = 0;
+ pParams->cut = FL2FXCONST_DBL(0.0f);
+ pParams->boost = FL2FXCONST_DBL(0.0f);
+ pParams->targetRefLevel = AACDEC_DRC_DEFAULT_REF_LEVEL;
+ pParams->expiryFrame = AACDEC_DRC_DFLT_EXPIRY_FRAMES;
+
+ /* initial program ref level = target ref level */
+ self->progRefLevel = pParams->targetRefLevel;
+}
+
+
+/*!
+ \brief Initialize DRC control data for one channel
+
+ \self Handle of DRC info
+
+ \return none
+*/
+void aacDecoder_drcInitChannelData (
+ CDrcChannelData *pDrcChData )
+{
+ if (pDrcChData != NULL) {
+ pDrcChData->expiryCount = 0;
+ pDrcChData->numBands = 1;
+ pDrcChData->bandTop[0] = (1024 >> 2) - 1;
+ pDrcChData->drcValue[0] = 0;
+ pDrcChData->drcInterpolationScheme = 0;
+ pDrcChData->drcDataType = UNKNOWN_PAYLOAD;
+ }
+}
+
+
+/*!
+ \brief Set one single DRC parameter
+
+ \self Handle of DRC info.
+ \param Parameter to be set.
+ \value Value to be set.
+
+ \return an error code.
+*/
+AAC_DECODER_ERROR aacDecoder_drcSetParam (
+ HANDLE_AAC_DRC self,
+ AACDEC_DRC_PARAM param,
+ INT value )
+{
+ AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
+
+ switch (param)
+ {
+ case DRC_CUT_SCALE:
+ /* set attenuation scale factor */
+ if ( (value < 0)
+ || (value > DRC_MAX_QUANT_FACTOR) ) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ self->params.cut = (FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP>>DRC_PARAM_SCALE) * (INT)value);
+ break;
+ case DRC_BOOST_SCALE:
+ /* set boost factor */
+ if ( (value < 0)
+ || (value > DRC_MAX_QUANT_FACTOR) ) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ self->params.boost = (FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP>>DRC_PARAM_SCALE) * (INT)value);
+ break;
+ case TARGET_REF_LEVEL:
+ if ( value > MAX_REFERENCE_LEVEL
+ || value < -MAX_REFERENCE_LEVEL ) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ if (value < 0) {
+ self->digitalNorm = 0;
+ }
+ else {
+ /* ref_level must be between 0 and MAX_REFERENCE_LEVEL, inclusive */
+ self->digitalNorm = 1;
+ self->progRefLevel = AACDEC_DRC_DEFAULT_REF_LEVEL;
+ self->params.targetRefLevel = value;
+ }
+ break;
+ case APPLY_HEAVY_COMPRESSION:
+ if (value < 0 || value > 1) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ self->params.applyHeavyCompression = (UCHAR)value;
+ break;
+ case DRC_BS_DELAY:
+ if (value < 0 || value > 1) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ self->params.bsDelayEnable = value;
+ break;
+ case DRC_DATA_EXPIRY_FRAME:
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ self->params.expiryFrame = (UINT)value;
+ break;
+ default:
+ return AAC_DEC_SET_PARAM_FAIL;
+ } /* switch(param) */
+
+ /* switch on/off processing */
+ self->enable = ( (self->params.boost > (FIXP_DBL)0)
+ || (self->params.cut > (FIXP_DBL)0)
+ || (self->params.applyHeavyCompression != 0)
+ || (self->digitalNorm == 1) );
+
+
+ return ErrorStatus;
+}
+
+
+static int parseExcludedChannels( UINT *excludedChnsMask,
+ HANDLE_FDK_BITSTREAM bs )
+{
+ UINT excludeMask = 0;
+ UINT i, j;
+ int bitCnt = 9;
+
+ for (i = 0, j = 1; i < 7; i++, j<<=1) {
+ if (FDKreadBits(bs,1)) {
+ excludeMask |= j;
+ }
+ }
+
+ /* additional_excluded_chns */
+ while (FDKreadBits(bs,1)) {
+ for (i = 0; i < 7; i++, j<<=1) {
+ if (FDKreadBits(bs,1)) {
+ excludeMask |= j;
+ }
+ }
+ bitCnt += 9;
+ FDK_ASSERT(j < (UINT)-1);
+ }
+
+ *excludedChnsMask = excludeMask;
+
+ return (bitCnt);
+}
+
+
+/*!
+ \brief Save DRC payload bitstream position
+
+ \self Handle of DRC info
+ \bs Handle of FDK bitstream
+
+ \return The number of DRC payload bits
+*/
+int aacDecoder_drcMarkPayload (
+ HANDLE_AAC_DRC self,
+ HANDLE_FDK_BITSTREAM bs,
+ AACDEC_DRC_PAYLOAD_TYPE type )
+{
+ UINT bsStartPos;
+ int i, numBands = 1, bitCnt = 0;
+
+ if (self == NULL) {
+ return 0;
+ }
+
+ bsStartPos = FDKgetValidBits(bs);
+
+ switch (type) {
+ case MPEG_DRC_EXT_DATA:
+ {
+ bitCnt = 4;
+
+ if (FDKreadBits(bs,1)) { /* pce_tag_present */
+ FDKreadBits(bs,8); /* pce_instance_tag + drc_tag_reserved_bits */
+ bitCnt+=8;
+ }
+
+ if (FDKreadBits(bs,1)) { /* excluded_chns_present */
+ FDKreadBits(bs,7); /* exclude mask [0..7] */
+ bitCnt+=8;
+ while (FDKreadBits(bs,1)) { /* additional_excluded_chns */
+ FDKreadBits(bs,7); /* exclude mask [x..y] */
+ bitCnt+=8;
+ }
+ }
+
+ if (FDKreadBits(bs,1)) { /* drc_bands_present */
+ numBands += FDKreadBits(bs, 4); /* drc_band_incr */
+ FDKreadBits(bs,4); /* reserved */
+ bitCnt+=8;
+ for (i = 0; i < numBands; i++) {
+ FDKreadBits(bs,8); /* drc_band_top[i] */
+ bitCnt+=8;
+ }
+ }
+
+ if (FDKreadBits(bs,1)) { /* prog_ref_level_present */
+ FDKreadBits(bs,8); /* prog_ref_level + prog_ref_level_reserved_bits */
+ bitCnt+=8;
+ }
+
+ for (i = 0; i < numBands; i++) {
+ FDKreadBits(bs,8); /* dyn_rng_sgn[i] + dyn_rng_ctl[i] */
+ bitCnt+=8;
+ }
+
+ if ( (self->numPayloads < MAX_DRC_THREADS)
+ && ((INT)FDKgetValidBits(bs) >= 0) )
+ {
+ self->drcPayloadPosition[self->numPayloads++] = bsStartPos;
+ }
+ }
+ break;
+
+ case DVB_DRC_ANC_DATA:
+ bitCnt += 8;
+ /* check sync word */
+ if (FDKreadBits(bs, 8) == DVB_ANC_DATA_SYNC_BYTE)
+ {
+ int dmxLevelsPresent, compressionPresent;
+ int coarseGrainTcPresent, fineGrainTcPresent;
+
+ /* bs_info field */
+ FDKreadBits(bs, 8); /* mpeg_audio_type, dolby_surround_mode, presentation_mode */
+ bitCnt+=8;
+
+ /* Evaluate ancillary_data_status */
+ FDKreadBits(bs, 3); /* reserved, set to 0 */
+ dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */
+ FDKreadBits(bs, 1); /* reserved, set to 0 */
+ compressionPresent = FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */
+ coarseGrainTcPresent = FDKreadBits(bs, 1); /* coarse_grain_timecode_status */
+ fineGrainTcPresent = FDKreadBits(bs, 1); /* fine_grain_timecode_status */
+ bitCnt+=8;
+
+ /* MPEG4 downmixing levels */
+ if (dmxLevelsPresent) {
+ FDKreadBits(bs, 8); /* downmixing_levels_MPEG4 */
+ bitCnt+=8;
+ }
+ /* audio coding mode and compression status */
+ if (compressionPresent) {
+ FDKreadBits(bs, 16); /* audio_coding_mode, Compression_value */
+ bitCnt+=16;
+ }
+ /* coarse grain timecode */
+ if (coarseGrainTcPresent) {
+ FDKreadBits(bs, 16); /* coarse_grain_timecode */
+ bitCnt+=16;
+ }
+ /* fine grain timecode */
+ if (fineGrainTcPresent) {
+ FDKreadBits(bs, 16); /* fine_grain_timecode */
+ bitCnt+=16;
+ }
+ if ( !self->dvbAncDataAvailable
+ && ((INT)FDKgetValidBits(bs) >= 0) )
+ {
+ self->dvbAncDataPosition = bsStartPos;
+ self->dvbAncDataAvailable = 1;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return (bitCnt);
+}
+
+
+/*!
+ \brief Parse DRC parameters from bitstream
+
+ \bs Handle of FDK bitstream (in)
+ \pDrcBs Pointer to DRC payload data container (out)
+ \payloadPosition Bitstream position of MPEG DRC data junk (in)
+
+ \return Number of bits read (0 in case of a parse error)
+*/
+static int aacDecoder_drcParse (
+ HANDLE_FDK_BITSTREAM bs,
+ CDrcPayload *pDrcBs,
+ UINT payloadPosition )
+{
+ int i, numBands, bitCnt = 4;
+
+ /* Move to the beginning of the DRC payload field */
+ FDKpushBiDirectional(bs, FDKgetValidBits(bs)-payloadPosition);
+
+ /* pce_tag_present */
+ if (FDKreadBits(bs,1))
+ {
+ pDrcBs->pceInstanceTag = FDKreadBits(bs, 4); /* pce_instance_tag */
+ /* only one program supported */
+ FDKreadBits(bs, 4); /* drc_tag_reserved_bits */
+ bitCnt += 8;
+ } else {
+ pDrcBs->pceInstanceTag = -1; /* not present */
+ }
+
+ if (FDKreadBits(bs,1)) { /* excluded_chns_present */
+ /* get excluded_chn_mask */
+ bitCnt += parseExcludedChannels(&pDrcBs->excludedChnsMask, bs);
+ } else {
+ pDrcBs->excludedChnsMask = 0;
+ }
+
+ numBands = 1;
+ if (FDKreadBits(bs,1)) /* drc_bands_present */
+ {
+ /* get band_incr */
+ numBands += FDKreadBits(bs, 4); /* drc_band_incr */
+ pDrcBs->channelData.drcInterpolationScheme = FDKreadBits(bs, 4); /* drc_interpolation_scheme */
+ bitCnt += 8;
+ /* band_top */
+ for (i = 0; i < numBands; i++)
+ {
+ pDrcBs->channelData.bandTop[i] = FDKreadBits(bs, 8); /* drc_band_top[i] */
+ bitCnt += 8;
+ }
+ }
+ else {
+ pDrcBs->channelData.bandTop[0] = 255;
+ }
+
+ pDrcBs->channelData.numBands = numBands;
+
+ if (FDKreadBits(bs,1)) /* prog_ref_level_present */
+ {
+ pDrcBs->progRefLevel = FDKreadBits(bs, 7); /* prog_ref_level */
+ FDKreadBits(bs, 1); /* prog_ref_level_reserved_bits */
+ bitCnt += 8;
+ } else {
+ pDrcBs->progRefLevel = -1;
+ }
+
+ for (i = 0; i < numBands; i++)
+ {
+ pDrcBs->channelData.drcValue[i] = FDKreadBits(bs, 1) << 7; /* dyn_rng_sgn[i] */
+ pDrcBs->channelData.drcValue[i] |= FDKreadBits(bs, 7) & 0x7F; /* dyn_rng_ctl[i] */
+ bitCnt += 8;
+ }
+
+ /* Set DRC payload type */
+ pDrcBs->channelData.drcDataType = MPEG_DRC_EXT_DATA;
+
+ return (bitCnt);
+}
+
+
+/*!
+ \brief Parse heavy compression value transported in DSEs of DVB streams with MPEG-4 content.
+
+ \bs Handle of FDK bitstream (in)
+ \pDrcBs Pointer to DRC payload data container (out)
+ \payloadPosition Bitstream position of DVB ancillary data junk
+
+ \return Number of bits read (0 in case of a parse error)
+*/
+#define DVB_COMPRESSION_SCALE ( 8 ) /* 48,164 dB */
+
+static int aacDecoder_drcReadCompression (
+ HANDLE_FDK_BITSTREAM bs,
+ CDrcPayload *pDrcBs,
+ UINT payloadPosition )
+{
+ int bitCnt = 0;
+ int dmxLevelsPresent, compressionPresent;
+ int coarseGrainTcPresent, fineGrainTcPresent;
+
+ /* Move to the beginning of the DRC payload field */
+ FDKpushBiDirectional(bs, FDKgetValidBits(bs)-payloadPosition);
+
+ /* Sanity checks */
+ if ( FDKgetValidBits(bs) < 24 ) {
+ return 0;
+ }
+
+ /* Check sync word */
+ if (FDKreadBits(bs, 8) != DVB_ANC_DATA_SYNC_BYTE) {
+ return 0;
+ }
+
+ /* Evaluate bs_info field */
+ if (FDKreadBits(bs, 2) != 3) { /* mpeg_audio_type */
+ /* No MPEG-4 audio data */
+ return 0;
+ }
+ FDKreadBits(bs, 2); /* dolby_surround_mode */
+ FDKreadBits(bs, 2); /* presentation_mode */
+ if (FDKreadBits(bs, 2) != 0) { /* reserved, set to 0 */
+ return 0;
+ }
+
+ /* Evaluate ancillary_data_status */
+ if (FDKreadBits(bs, 3) != 0) { /* reserved, set to 0 */
+ return 0;
+ }
+ dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */
+ if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */
+ return 0;
+ }
+ compressionPresent = FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */
+ coarseGrainTcPresent = FDKreadBits(bs, 1); /* coarse_grain_timecode_status */
+ fineGrainTcPresent = FDKreadBits(bs, 1); /* fine_grain_timecode_status */
+ bitCnt += 24;
+
+ if (dmxLevelsPresent) {
+ FDKreadBits(bs, 8); /* downmixing_levels_MPEG4 */
+ bitCnt += 8;
+ }
+
+ /* audio_coding_mode_and_compression_status */
+ if (compressionPresent)
+ {
+ UCHAR compressionOn, compressionValue;
+
+ /* audio_coding_mode */
+ if ( FDKreadBits(bs, 7) != 0 ) { /* The reserved bits shall be set to "0". */
+ return 0;
+ }
+ compressionOn = (UCHAR)FDKreadBits(bs, 1); /* compression_on */
+ compressionValue = (UCHAR)FDKreadBits(bs, 8); /* Compression_value */
+ bitCnt += 16;
+
+ if ( compressionOn ) {
+ /* A compression value is available so store the data just like MPEG DRC data */
+ pDrcBs->channelData.numBands = 1; /* One band ... */
+ pDrcBs->channelData.drcValue[0] = compressionValue; /* ... with one value ... */
+ pDrcBs->channelData.bandTop[0] = (1024 >> 2) - 1; /* ... comprising the whole spectrum. */
+ pDrcBs->pceInstanceTag = -1; /* Not present */
+ pDrcBs->progRefLevel = -1; /* Not present */
+ pDrcBs->channelData.drcDataType = DVB_DRC_ANC_DATA; /* Set DRC payload type to DVB. */
+ } else {
+ /* No compression value available */
+ /* CAUTION: It is not clearly defined by standard how to react in this situation. */
+ /* Turn down the compression value to aprox. 0dB */
+ pDrcBs->channelData.numBands = 1; /* One band ... */
+ pDrcBs->channelData.drcValue[0] = 0x80; /* ... with aprox. 0dB ... */
+ pDrcBs->channelData.bandTop[0] = (1024 >> 2) - 1; /* ... comprising the whole spectrum. */
+ pDrcBs->channelData.drcDataType = DVB_DRC_ANC_DATA; /* Set DRC payload type to DVB. */
+
+ /* If compression_on field is set to "0" the compression_value field shall be "0000 0000". */
+ if (compressionValue != 0) {
+ return 0;
+ }
+ }
+ }
+
+ /* Read timecodes if available just to get the right amount of bits. */
+ if (coarseGrainTcPresent) {
+ FDKreadBits(bs, 16); /* coarse_grain_timecode */
+ bitCnt += 16;
+ }
+ if (fineGrainTcPresent) {
+ FDKreadBits(bs, 16); /* fine_grain_timecode */
+ bitCnt += 16;
+ }
+
+ return (bitCnt);
+}
+
+
+/*
+ * Prepare DRC processing
+ */
+static int aacDecoder_drcExtractAndMap (
+ HANDLE_AAC_DRC self,
+ HANDLE_FDK_BITSTREAM hBs,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
+ UCHAR pceInstanceTag,
+ UCHAR channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */
+ int validChannels )
+{
+ CDrcPayload threadBs[MAX_DRC_THREADS];
+ CDrcPayload *validThreadBs[MAX_DRC_THREADS];
+ UINT backupBsPosition;
+ int i, thread, validThreads = 0;
+ int numExcludedChns[MAX_DRC_THREADS];
+
+ self->numThreads = 0;
+ backupBsPosition = FDKgetValidBits(hBs);
+
+ for (i = 0; i < self->numPayloads && self->numThreads < MAX_DRC_THREADS; i++) {
+ int bitsParsed;
+
+ /* Init payload data chunk. The memclear is very important because it initializes
+ the most values. Without it the module wouldn't work properly or crash. */
+ FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload));
+ threadBs[self->numThreads].channelData.bandTop[0] = (1024 >> 2) - 1;
+
+ /* Extract payload */
+ bitsParsed = aacDecoder_drcParse( hBs,
+ &threadBs[self->numThreads],
+ self->drcPayloadPosition[i] );
+ if (bitsParsed > 0) {
+ self->numThreads++;
+ }
+ }
+ self->numPayloads = 0;
+
+ if (self->dvbAncDataAvailable)
+ { /* Append a DVB heavy compression payload thread if available. */
+ int bitsParsed;
+
+ /* Init payload data chunk. The memclear is very important because it initializes
+ the most values. Without it the module wouldn't work properly or crash. */
+ FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload));
+ threadBs[self->numThreads].channelData.bandTop[0] = (1024 >> 2) - 1;
+
+ /* Extract payload */
+ bitsParsed = aacDecoder_drcReadCompression( hBs,
+ &threadBs[self->numThreads],
+ self->dvbAncDataPosition );
+ if (bitsParsed > 0) {
+ self->numThreads++;
+ }
+ }
+ self->dvbAncDataAvailable = 0;
+
+ /* Reset the bitbufffer */
+ FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - backupBsPosition);
+
+ /* calculate number of valid bits in excl_chn_mask */
+
+ /* coupling channels not supported */
+
+ /* check for valid threads */
+ for (thread = 0; thread < self->numThreads; thread++) {
+ CDrcPayload *pThreadBs = &threadBs[thread];
+ int numExclChns = 0;
+
+ switch ((AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType) {
+ default:
+ continue;
+ case MPEG_DRC_EXT_DATA:
+ case DVB_DRC_ANC_DATA:
+ break;
+ }
+
+ if (pThreadBs->pceInstanceTag >= 0) { /* if PCE tag present */
+ if (pThreadBs->pceInstanceTag != pceInstanceTag) {
+ continue; /* don't accept */
+ }
+ }
+
+ /* calculate number of excluded channels */
+ if (pThreadBs->excludedChnsMask > 0) {
+ INT exclMask = pThreadBs->excludedChnsMask;
+ int ch;
+ for (ch = 0; ch < validChannels; ch++) {
+ numExclChns += exclMask & 0x1;
+ exclMask >>= 1;
+ }
+ }
+ if (numExclChns < validChannels) {
+ validThreadBs[validThreads] = pThreadBs;
+ numExcludedChns[validThreads] = numExclChns;
+ validThreads++;
+ }
+ }
+
+ if (validThreads > 1) {
+ int ch;
+
+ /* check consistency of excl_chn_mask amongst valid DRC threads */
+ for (ch = 0; ch < validChannels; ch++) {
+ int present = 0;
+
+ for (thread = 0; thread < validThreads; thread++) {
+ CDrcPayload *pThreadBs = validThreadBs[thread];
+
+
+ /* thread applies to this channel */
+ if ( (pThreadBs->channelData.drcDataType == MPEG_DRC_EXT_DATA)
+ && ( (numExcludedChns[thread] == 0)
+ || (!(pThreadBs->excludedChnsMask & (1<<ch))) ) ) {
+ present++;
+ }
+ }
+
+
+ if (present > 1) {
+ return -1;
+ }
+ }
+ }
+
+ /* map DRC bitstream information onto DRC channel information */
+ for (thread = 0; thread < validThreads; thread++)
+ {
+ CDrcPayload *pThreadBs = validThreadBs[thread];
+ INT exclMask = pThreadBs->excludedChnsMask;
+ AACDEC_DRC_PAYLOAD_TYPE drcPayloadType = (AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType;
+ int ch;
+
+ /* last progRefLevel transmitted is the one that is used
+ * (but it should really only be transmitted once per block!)
+ */
+ if (pThreadBs->progRefLevel >= 0) {
+ self->progRefLevel = pThreadBs->progRefLevel;
+ }
+
+ /* SCE, CPE and LFE */
+ for (ch = 0; ch < validChannels; ch++) {
+ int mapedChannel = channelMapping[ch];
+
+ if ( ((exclMask & (1<<mapedChannel)) == 0)
+ && ( (drcPayloadType == MPEG_DRC_EXT_DATA)
+ || ((drcPayloadType == DVB_DRC_ANC_DATA) && self->params.applyHeavyCompression)
+ ) ) {
+ /* copy thread to channel */
+ pAacDecoderStaticChannelInfo[ch]->drcData = pThreadBs->channelData;
+ }
+ }
+ /* CCEs not supported by now */
+ }
+
+ return 0;
+}
+
+
+void aacDecoder_drcApply (
+ HANDLE_AAC_DRC self,
+ void *pSbrDec,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CDrcChannelData *pDrcChData,
+ int ch, /* needed only for SBR */
+ int aacFrameSize,
+ int bSbrPresent )
+{
+ int band, top, bin, numBands;
+ int bottom = 0;
+
+ FIXP_DBL max_mantissa;
+ INT max_exponent;
+
+ FIXP_DBL norm_mantissa = FL2FXCONST_DBL(0.0f);
+ INT norm_exponent = 0;
+
+ FIXP_DBL fact_mantissa[MAX_DRC_BANDS];
+ INT fact_exponent[MAX_DRC_BANDS];
+
+ CDrcParams *pParams = &self->params;
+
+ FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
+ CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
+ SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
+
+ int winSeq = pIcsInfo->WindowSequence;
+
+ /* Increment and check expiry counter */
+ if ( (pParams->expiryFrame > 0)
+ && (++pDrcChData->expiryCount > pParams->expiryFrame) )
+ { /* The DRC data is too old, so delete it. */
+ aacDecoder_drcInitChannelData( pDrcChData );
+ }
+
+ if (!self->enable) {
+ sbrDecoder_drcDisable( (HANDLE_SBRDECODER)pSbrDec, ch );
+ return;
+ }
+
+ numBands = pDrcChData->numBands;
+ top = FDKmax(0, numBands-1);
+
+ pDrcChData->bandTop[0] = fixMin(pDrcChData->bandTop[0], (aacFrameSize >> 2) - 1);
+
+ /* If program reference normalization is done in the digital domain,
+ modify factor to perform normalization. prog_ref_level can
+ alternatively be passed to the system for modification of the level in
+ the analog domain. Analog level modification avoids problems with
+ reduced DAC SNR (if signal is attenuated) or clipping (if signal is
+ boosted) */
+
+ if (self->digitalNorm == 1)
+ {
+ /* 0.5^((targetRefLevel - progRefLevel)/24) */
+ norm_mantissa = fLdPow(
+ FL2FXCONST_DBL(-1.0), /* log2(0.5) */
+ 0,
+ (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0f/24.0)>>3) * (INT)(pParams->targetRefLevel-self->progRefLevel)),
+ 3,
+ &norm_exponent );
+ }
+ else {
+ norm_mantissa = FL2FXCONST_DBL(0.5f);
+ norm_exponent = 1;
+ }
+
+
+ /* calc scale factors */
+ for (band = 0; band < numBands; band++)
+ {
+ UCHAR drcVal = pDrcChData->drcValue[band];
+ top = fixMin((int)( (pDrcChData->bandTop[band]+1)<<2 ), aacFrameSize);
+
+ fact_mantissa[band] = FL2FXCONST_DBL(0.5f);
+ fact_exponent[band] = 1;
+
+ if ( pParams->applyHeavyCompression
+ && ((AACDEC_DRC_PAYLOAD_TYPE)pDrcChData->drcDataType == DVB_DRC_ANC_DATA) )
+ {
+ INT compressionFactorVal_e;
+ int valX, valY;
+
+ valX = drcVal >> 4;
+ valY = drcVal & 0x0F;
+
+ /* calculate the unscaled heavy compression factor.
+ compressionFactor = 48.164 - 6.0206*valX - 0.4014*valY dB
+ range: -48.166 dB to 48.164 dB */
+ if ( drcVal != 0x7F ) {
+ fact_mantissa[band] =
+ fPowInt( FL2FXCONST_DBL(0.95483867181), /* -0.4014dB = 0.95483867181 */
+ 0,
+ valY,
+ &compressionFactorVal_e );
+
+ /* -0.0008dB (48.164 - 6.0206*8 = -0.0008) */
+ fact_mantissa[band] = fMult(FL2FXCONST_DBL(0.99990790084), fact_mantissa[band]);
+
+ fact_exponent[band] = DVB_COMPRESSION_SCALE - valX + compressionFactorVal_e;
+ }
+ } else
+ if ((AACDEC_DRC_PAYLOAD_TYPE)pDrcChData->drcDataType == MPEG_DRC_EXT_DATA)
+ {
+ /* apply the scaled dynamic range control words to factor.
+ * if scaling drc_cut (or drc_boost), or control word drc_mantissa is 0
+ * then there is no dynamic range compression
+ *
+ * if pDrcChData->drcSgn[band] is
+ * 1 then gain is < 1 : factor = 2^(-self->cut * pDrcChData->drcMag[band] / 24)
+ * 0 then gain is > 1 : factor = 2^( self->boost * pDrcChData->drcMag[band] / 24)
+ */
+
+ if ((drcVal&0x7F) > 0) {
+ FIXP_DBL tParamVal = (drcVal & 0x80) ? -pParams->cut : pParams->boost;
+
+ fact_mantissa[band] =
+ f2Pow( (FIXP_DBL)((INT)fMult(FL2FXCONST_DBL(1.0f/192.0f), tParamVal) * (drcVal&0x7F)),
+ 3+DRC_PARAM_SCALE,
+ &fact_exponent[band] );
+ }
+ }
+
+ fact_mantissa[band] = fMult(fact_mantissa[band], norm_mantissa);
+ fact_exponent[band] += norm_exponent;
+
+
+ bottom = top;
+
+ } /* end loop over bands */
+
+
+ /* normalizations */
+ {
+ int res;
+
+ max_mantissa = FL2FXCONST_DBL(0.0f);
+ max_exponent = 0;
+ for (band = 0; band < numBands; band++) {
+ max_mantissa = fixMax(max_mantissa, fact_mantissa[band]);
+ max_exponent = fixMax(max_exponent, fact_exponent[band]);
+ }
+
+ /* left shift factors to gain accurancy */
+ res = CntLeadingZeros(max_mantissa) - 1;
+
+ /* above topmost DRC band gain factor is 1 */
+ if (((pDrcChData->bandTop[numBands-1]+1)<<2) < aacFrameSize) res = 0;
+
+ if (res > 0) {
+ res = fixMin(res, max_exponent);
+ max_exponent -= res;
+
+ for (band = 0; band < numBands; band++) {
+ fact_mantissa[band] <<= res;
+ fact_exponent[band] -= res;
+ }
+ }
+
+ /* normalize magnitudes to one scale factor */
+ for (band = 0; band < numBands; band++) {
+ if (fact_exponent[band] < max_exponent) {
+ fact_mantissa[band] >>= max_exponent - fact_exponent[band];
+ }
+ }
+ }
+
+ /* apply factor to spectral lines
+ * short blocks must take care that bands fall on
+ * block boundaries!
+ */
+ if (!bSbrPresent)
+ {
+ bottom = 0;
+
+ for (band = 0; band < numBands; band++)
+ {
+ top = fixMin((int)( (pDrcChData->bandTop[band]+1)<<2 ), aacFrameSize); /* ... * DRC_BAND_MULT; */
+
+ for (bin = bottom; bin < top; bin++) {
+ pSpectralCoefficient[bin] = fMult(pSpectralCoefficient[bin], fact_mantissa[band]);
+ }
+
+ bottom = top;
+ }
+
+ /* above topmost DRC band gain factor is 1 */
+ if (max_exponent > 0) {
+ FIXP_DBL fact = FL2FXCONST_DBL(0.5f) >> (max_exponent - 1);
+
+ for (bin = top; bin < aacFrameSize; bin++) {
+ pSpectralCoefficient[bin] = fMult(pSpectralCoefficient[bin], fact);
+ }
+ }
+
+ /* adjust scaling */
+ pSpecScale[0] += max_exponent;
+
+ if (winSeq == EightShortSequence) {
+ int win;
+ for (win = 1; win < 8; win++) {
+ pSpecScale[win] += max_exponent;
+ }
+ }
+ }
+ else {
+ HANDLE_SBRDECODER hSbrDecoder = (HANDLE_SBRDECODER)pSbrDec;
+
+ /* feed factors into SBR decoder for application in QMF domain. */
+ sbrDecoder_drcFeedChannel (
+ hSbrDecoder,
+ ch,
+ pDrcChData->numBands,
+ fact_mantissa,
+ max_exponent,
+ pDrcChData->drcInterpolationScheme,
+ winSeq,
+ pDrcChData->bandTop
+ );
+ }
+
+ return;
+}
+
+
+/*
+ * Prepare DRC processing
+ */
+int aacDecoder_drcProlog (
+ HANDLE_AAC_DRC self,
+ HANDLE_FDK_BITSTREAM hBs,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
+ UCHAR pceInstanceTag,
+ UCHAR channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */
+ int validChannels )
+{
+ int err = 0;
+
+ if (self == NULL) {
+ return -1;
+ }
+
+ if (!self->params.bsDelayEnable)
+ {
+ err = aacDecoder_drcExtractAndMap (
+ self,
+ hBs,
+ pAacDecoderStaticChannelInfo,
+ pceInstanceTag,
+ channelMapping,
+ validChannels );
+ }
+
+ return err;
+}
+
+
+/*
+ * Finalize DRC processing
+ */
+int aacDecoder_drcEpilog (
+ HANDLE_AAC_DRC self,
+ HANDLE_FDK_BITSTREAM hBs,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
+ UCHAR pceInstanceTag,
+ UCHAR channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */
+ int validChannels )
+{
+ int err = 0;
+
+ if (self == NULL) {
+ return -1;
+ }
+
+ if (self->params.bsDelayEnable)
+ {
+ err = aacDecoder_drcExtractAndMap (
+ self,
+ hBs,
+ pAacDecoderStaticChannelInfo,
+ pceInstanceTag,
+ channelMapping,
+ validChannels );
+ }
+
+ return err;
+}
+