/***************************** MPEG-4 AAC Decoder ************************** (C) Copyright Fraunhofer IIS (2004) All Rights Reserved Please be advised that this software and/or program delivery is Confidential Information of Fraunhofer and subject to and covered by the Fraunhofer IIS Software Evaluation Agreement between Google Inc. and Fraunhofer effective and in full force since March 1, 2012. You may use this software and/or program only under the terms and conditions described in the above mentioned Fraunhofer IIS Software Evaluation Agreement. Any other and/or further use requires a separate agreement. $Id$ Author(s): Christian Griebel Description: Dynamic range control (DRC) decoder tool for AAC This software and/or program is protected by copyright law and international treaties. Any reproduction or distribution of this software and/or program, or any portion of it, may result in severe civil and criminal penalties, and will be prosecuted to the maximum extent possible under law. ******************************************************************************/ #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<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; } } /*! \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+1)); 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+1)); 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: /* check sync word */ if (FDKreadBits(bs, 8) == DVB_ANC_DATA_SYNC_BYTE) { int dmxLevelsPresent, compressionPresent; int coarseGrainTcPresent, fineGrainTcPresent; bitCnt+=8; /* 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->type = 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.drcValue[0] = compressionValue; pDrcBs->channelData.numBands = 1; /* one value for all bands */ pDrcBs->pceInstanceTag = -1; /* not present */ pDrcBs->progRefLevel = -1; /* not present */ } else { /* No compression value available */ /* CAUTION: It is not clearly defined by standard how to react in this situation. */ pDrcBs->channelData.drcValue[0] = 0x7F; /* 0dB */ pDrcBs->channelData.bandTop[0] = 0; /* If compression_on field is set to "0" the compression_value field shall be "0000 0000". */ if (compressionValue != 0) { return 0; } } /* Set DRC payload type now because the payload seems to be correct. */ pDrcBs->type = DVB_DRC_ANC_DATA; } /* 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 (pThreadBs->type) { 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->type == MPEG_DRC_EXT_DATA) && ( (numExcludedChns[thread] == 0) || (!(pThreadBs->excludedChnsMask & (1< 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; 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<params.applyHeavyCompression && (pThreadBs->type == DVB_DRC_ANC_DATA)) || (!self->params.applyHeavyCompression && (pThreadBs->type == MPEG_DRC_EXT_DATA)) ) ) { /* 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); if ( pParams->applyHeavyCompression ) { INT compressionFactorVal_e; int valX = drcVal >> 4; int 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 { fact_mantissa[band] = FL2FXCONST_DBL(0.5f); fact_exponent[band] = 1; } } else { /* 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] ); } else { fact_mantissa[band] = FL2FXCONST_DBL(0.5f); fact_exponent[band] = 1; } } 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; }