diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2012-07-11 10:15:24 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2012-07-11 10:15:24 -0700 |
commit | 2228e360595641dd906bf1773307f43d304f5b2e (patch) | |
tree | 57f3d390ebb0782cc0de0fb984c8ea7e45b4f386 /libAACdec/src/rvlcconceal.cpp | |
download | fdk-aac-dabplus-2228e360595641dd906bf1773307f43d304f5b2e.tar.gz fdk-aac-dabplus-2228e360595641dd906bf1773307f43d304f5b2e.tar.bz2 fdk-aac-dabplus-2228e360595641dd906bf1773307f43d304f5b2e.zip |
Snapshot 2bda038c163298531d47394bc2c09e1409c5d0db
Change-Id: If584e579464f28b97d50e51fc76ba654a5536c54
Diffstat (limited to 'libAACdec/src/rvlcconceal.cpp')
-rw-r--r-- | libAACdec/src/rvlcconceal.cpp | 697 |
1 files changed, 697 insertions, 0 deletions
diff --git a/libAACdec/src/rvlcconceal.cpp b/libAACdec/src/rvlcconceal.cpp new file mode 100644 index 0000000..682e6eb --- /dev/null +++ b/libAACdec/src/rvlcconceal.cpp @@ -0,0 +1,697 @@ + +/* ----------------------------------------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief rvlc concealment + \author Josef Hoepfl +*/ + +#include "rvlcconceal.h" + + +#include "block.h" +#include "rvlc.h" + +/*--------------------------------------------------------------------------------------------- + function: calcRefValFwd + + description: The function determines the scalefactor which is closed to the scalefactorband + conceal_min. The same is done for intensity data and noise energies. +----------------------------------------------------------------------------------------------- + output: - reference value scf + - reference value internsity data + - reference value noise energy +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +static +void calcRefValFwd (CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + int *refIsFwd, + int *refNrgFwd, + int *refScfFwd) +{ + int band,bnds,group,startBand; + int idIs,idNrg,idScf; + int conceal_min,conceal_group_min; + int MaximumScaleFactorBands; + + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) + MaximumScaleFactorBands = 16; + else + MaximumScaleFactorBands = 64; + + conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands; + conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands; + + /* calculate first reference value for approach in forward direction */ + idIs = idNrg = idScf = 1; + + /* set reference values */ + *refIsFwd = - SF_OFFSET; + *refNrgFwd = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - 90 - 256; + *refScfFwd = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET; + + startBand = conceal_min-1; + for (group=conceal_group_min; group >= 0; group--) { + for (band=startBand; band >= 0; band--) { + bnds = 16*group+band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (idIs) { + *refIsFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + idIs=0; /* reference value has been set */ + } + break; + case NOISE_HCB: + if (idNrg) { + *refNrgFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + idNrg=0; /* reference value has been set */ + } + break ; + default: + if (idScf) { + *refScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + idScf=0; /* reference value has been set */ + } + break; + } + } + startBand = pRvlc->maxSfbTransmitted-1; + } + +} + +/*--------------------------------------------------------------------------------------------- + function: calcRefValBwd + + description: The function determines the scalefactor which is closed to the scalefactorband + conceal_max. The same is done for intensity data and noise energies. +----------------------------------------------------------------------------------------------- + output: - reference value scf + - reference value internsity data + - reference value noise energy +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +static +void calcRefValBwd (CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + int *refIsBwd, + int *refNrgBwd, + int *refScfBwd) +{ + int band,bnds,group,startBand; + int idIs,idNrg,idScf; + int conceal_max,conceal_group_max; + int MaximumScaleFactorBands; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) + MaximumScaleFactorBands = 16; + else + MaximumScaleFactorBands = 64; + + conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands; + conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands; + + /* calculate first reference value for approach in backward direction */ + idIs = idNrg = idScf = 1; + + /* set reference values */ + *refIsBwd = pRvlc->dpcm_is_last_position - SF_OFFSET; + *refNrgBwd = pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - SF_OFFSET - 90 - 256 + pRvlc->dpcm_noise_nrg; + *refScfBwd = pRvlc->rev_global_gain - SF_OFFSET; + + startBand=conceal_max+1; + + /* if needed, re-set reference values */ + for (group=conceal_group_max; group < pRvlc->numWindowGroups; group++) { + for (band=startBand; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16*group+band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (idIs) { + *refIsBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + idIs=0; /* reference value has been set */ + } + break; + case NOISE_HCB: + if (idNrg) { + *refNrgBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + idNrg=0; /* reference value has been set */ + } + break ; + default: + if (idScf) { + *refScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + idScf=0; /* reference value has been set */ + } + break; + } + } + startBand=0; + } + +} + + +/*--------------------------------------------------------------------------------------------- + function: BidirectionalEstimation_UseLowerScfOfCurrentFrame + + description: This approach by means of bidirectional estimation is generally performed when + a single bit error has been detected, the bit error can be isolated between + 'conceal_min' and 'conceal_max' and the 'sf_concealment' flag is not set. The + sets of scalefactors decoded in forward and backward direction are compared + with each other. The smaller scalefactor will be considered as the correct one + respectively. The reconstruction of the scalefactors with this approach archieve + good results in audio quality. The strategy must be applied to scalefactors, + intensity data and noise energy seperately. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data between conceal_min and + conceal_max +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +void BidirectionalEstimation_UseLowerScfOfCurrentFrame (CAacDecoderChannelInfo *pAacDecoderChannelInfo) +{ + CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band,bnds,startBand,endBand,group; + int conceal_min,conceal_max; + int conceal_group_min,conceal_group_max; + int MaximumScaleFactorBands; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) { + MaximumScaleFactorBands = 16; + } + else { + MaximumScaleFactorBands = 64; + } + + /* If an error was detected just in forward or backward direction, set the corresponding border for concealment to a + appropriate scalefactor band. The border is set to first or last sfb respectively, because the error will possibly + not follow directly after the corrupt bit but just after decoding some more (wrong) scalefactors. */ + if (pRvlc->conceal_min == CONCEAL_MIN_INIT) + pRvlc->conceal_min = 0; + + if (pRvlc->conceal_max == CONCEAL_MAX_INIT) + pRvlc->conceal_max = (pRvlc->numWindowGroups-1)*16+pRvlc->maxSfbTransmitted-1; + + conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands; + conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands; + conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands; + conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands; + + if (pRvlc->conceal_min == pRvlc->conceal_max) { + + int refIsFwd,refNrgFwd,refScfFwd; + int refIsBwd,refNrgBwd,refScfBwd; + + bnds = pRvlc->conceal_min; + calcRefValFwd(pRvlc,pAacDecoderChannelInfo,&refIsFwd,&refNrgFwd,&refScfFwd); + calcRefValBwd(pRvlc,pAacDecoderChannelInfo,&refIsBwd,&refNrgBwd,&refScfBwd); + + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (refIsFwd < refIsBwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refIsFwd; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refIsBwd; + break; + case NOISE_HCB: + if (refNrgFwd < refNrgBwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refNrgFwd; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refNrgBwd; + break; + default: + if (refScfFwd < refScfBwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refScfFwd; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refScfBwd; + break; + } + } + else { + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_max] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_max]; + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_min] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_min]; + + /* consider the smaller of the forward and backward decoded value as the correct one */ + startBand = conceal_min; + if (conceal_group_min == conceal_group_max) + endBand = conceal_max; + else + endBand = pRvlc->maxSfbTransmitted-1; + + for (group=conceal_group_min; group <= conceal_group_max; group++) { + for (band=startBand; band <= endBand; band++) { + bnds = 16*group+band; + if (pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds] < pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + } + startBand = 0; + if ((group+1) == conceal_group_max) + endBand = conceal_max; + } + } + + /* now copy all data to the output buffer which needs not to be concealed */ + if (conceal_group_min == 0) + endBand = conceal_min; + else + endBand = pRvlc->maxSfbTransmitted; + for (group=0; group <= conceal_group_min; group++) { + for (band=0; band < endBand; band++) { + bnds = 16*group+band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + } + if ((group+1) == conceal_group_min) + endBand = conceal_min; + } + + startBand = conceal_max+1; + for (group=conceal_group_max; group < pRvlc->numWindowGroups; group++) { + for (band=startBand; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16*group+band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + } + startBand = 0; + } +} + +/*--------------------------------------------------------------------------------------------- + function: BidirectionalEstimation_UseScfOfPrevFrameAsReference + + description: This approach by means of bidirectional estimation is generally performed when + a single bit error has been detected, the bit error can be isolated between + 'conceal_min' and 'conceal_max', the 'sf_concealment' flag is set and the + previous frame has the same block type as the current frame. The scalefactor + decoded in forward and backward direction and the scalefactor of the previous + frame are compared with each other. The smaller scalefactor will be considered + as the correct one. At this the codebook of the previous and current frame must + be of the same set (scf, nrg, is) in each scalefactorband. Otherwise the + scalefactor of the previous frame is not considered in the minimum calculation. + The reconstruction of the scalefactors with this approach archieve good results + in audio quality. The strategy must be applied to scalefactors, intensity data + and noise energy seperately. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data between conceal_min and + conceal_max +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +void BidirectionalEstimation_UseScfOfPrevFrameAsReference ( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo + ) +{ + CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band,bnds,startBand,endBand,group; + int conceal_min,conceal_max; + int conceal_group_min,conceal_group_max; + int MaximumScaleFactorBands; + int commonMin; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) { + MaximumScaleFactorBands = 16; + } + else { + MaximumScaleFactorBands = 64; + } + + /* If an error was detected just in forward or backward direction, set the corresponding border for concealment to a + appropriate scalefactor band. The border is set to first or last sfb respectively, because the error will possibly + not follow directly after the corrupt bit but just after decoding some more (wrong) scalefactors. */ + if (pRvlc->conceal_min == CONCEAL_MIN_INIT) + pRvlc->conceal_min = 0; + + if (pRvlc->conceal_max == CONCEAL_MAX_INIT) + pRvlc->conceal_max = (pRvlc->numWindowGroups-1)*16+pRvlc->maxSfbTransmitted-1; + + conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands; + conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands; + conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands; + conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands; + + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_max] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_max]; + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_min] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_min]; + + /* consider the smaller of the forward and backward decoded value as the correct one */ + startBand = conceal_min; + if (conceal_group_min == conceal_group_max) + endBand = conceal_max; + else + endBand = pRvlc->maxSfbTransmitted-1; + + for (group=conceal_group_min; group <= conceal_group_max; group++) { + for (band=startBand; band <= endBand; band++) { + bnds = 16*group+band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0; + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB) || (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB2) ) { + commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]); + } + else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + } + break; + + case NOISE_HCB: + if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==NOISE_HCB) ) { + commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + } + break; + + default: + if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=ZERO_HCB) + && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=NOISE_HCB) + && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB) + && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB2) ) + { + commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + } + break; + } + } + startBand = 0; + if ((group+1) == conceal_group_max) + endBand = conceal_max; + } + + /* now copy all data to the output buffer which needs not to be concealed */ + if (conceal_group_min == 0) + endBand = conceal_min; + else + endBand = pRvlc->maxSfbTransmitted; + for (group=0; group <= conceal_group_min; group++) { + for (band=0; band < endBand; band++) { + bnds = 16*group+band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + } + if ((group+1) == conceal_group_min) + endBand = conceal_min; + } + + startBand = conceal_max+1; + for (group=conceal_group_max; group < pRvlc->numWindowGroups; group++) { + for (band=startBand; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16*group+band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + } + startBand = 0; + } +} + +/*--------------------------------------------------------------------------------------------- + function: StatisticalEstimation + + description: This approach by means of statistical estimation is generally performed when + both the start value and the end value are different and no further errors have + been detected. Considering the forward and backward decoded scalefactors, the + set with the lower scalefactors in sum will be considered as the correct one. + The scalefactors are differentially encoded. Normally it would reach to compare + one pair of the forward and backward decoded scalefactors to specify the lower + set. But having detected no further errors does not necessarily mean the absence + of errors. Therefore all scalefactors decoded in forward and backward direction + are summed up seperately. The set with the lower sum will be used. The strategy + must be applied to scalefactors, intensity data and noise energy seperately. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +void StatisticalEstimation (CAacDecoderChannelInfo *pAacDecoderChannelInfo) +{ + CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band,bnds,group; + int sumIsFwd,sumIsBwd; /* sum of intensity data forward/backward */ + int sumNrgFwd,sumNrgBwd; /* sum of noise energy data forward/backward */ + int sumScfFwd,sumScfBwd; /* sum of scalefactor data forward/backward */ + int useIsFwd,useNrgFwd,useScfFwd; /* the flags signals the elements which are used for the final result */ + int MaximumScaleFactorBands; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) + MaximumScaleFactorBands = 16; + else + MaximumScaleFactorBands = 64; + + sumIsFwd = sumIsBwd = sumNrgFwd = sumNrgBwd = sumScfFwd = sumScfBwd = 0; + useIsFwd = useNrgFwd = useScfFwd = 0; + + /* calculate sum of each group (scf,nrg,is) of forward and backward direction */ + for (group=0; group<pRvlc->numWindowGroups; group++) { + for (band=0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16*group+band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + sumIsFwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + sumIsBwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + + case NOISE_HCB: + sumNrgFwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + sumNrgBwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break ; + + default: + sumScfFwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + sumScfBwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + } + } + } + + /* find for each group (scf,nrg,is) the correct direction */ + if ( sumIsFwd < sumIsBwd ) + useIsFwd = 1; + + if ( sumNrgFwd < sumNrgBwd ) + useNrgFwd = 1; + + if ( sumScfFwd < sumScfBwd ) + useScfFwd = 1; + + /* conceal each group (scf,nrg,is) */ + for (group=0; group<pRvlc->numWindowGroups; group++) { + for (band=0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16*group+band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (useIsFwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + + case NOISE_HCB: + if (useNrgFwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break ; + + default: + if (useScfFwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + } + } + } +} + + +/*--------------------------------------------------------------------------------------------- + description: Approach by means of predictive interpolation + This approach by means of predictive estimation is generally performed when + the error cannot be isolated between 'conceal_min' and 'conceal_max', the + 'sf_concealment' flag is set and the previous frame has the same block type + as the current frame. Check for each scalefactorband if the same type of data + (scalefactor, internsity data, noise energies) is transmitted. If so use the + scalefactor (intensity data, noise energy) in the current frame. Otherwise set + the scalefactor (intensity data, noise energy) for this scalefactorband to zero. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +void PredictiveInterpolation ( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo + ) +{ + CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band,bnds,group; + int MaximumScaleFactorBands; + int commonMin; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) + MaximumScaleFactorBands = 16; + else + MaximumScaleFactorBands = 64; + + for (group=0; group<pRvlc->numWindowGroups; group++) { + for (band=0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16*group+band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0; + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB) || (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB2) ) { + commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]); + } + else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = -110; + } + break; + + case NOISE_HCB: + if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==NOISE_HCB) ) { + commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]); + } + else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = -110; + } + break; + + default: + if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=ZERO_HCB) + && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=NOISE_HCB) + && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB) + && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB2) ) { + commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]); + } + else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0; + } + break; + } + } + } +} + |