aboutsummaryrefslogtreecommitdiffstats
path: root/fdk-aac/libAACdec/src/block.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fdk-aac/libAACdec/src/block.cpp')
-rw-r--r--fdk-aac/libAACdec/src/block.cpp1260
1 files changed, 1260 insertions, 0 deletions
diff --git a/fdk-aac/libAACdec/src/block.cpp b/fdk-aac/libAACdec/src/block.cpp
new file mode 100644
index 0000000..b3d09a6
--- /dev/null
+++ b/fdk-aac/libAACdec/src/block.cpp
@@ -0,0 +1,1260 @@
+/* -----------------------------------------------------------------------------
+Software License for The Fraunhofer FDK AAC Codec Library for Android
+
+© Copyright 1995 - 2018 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
+----------------------------------------------------------------------------- */
+
+/**************************** AAC decoder library ******************************
+
+ Author(s): Josef Hoepfl
+
+ Description: long/short-block decoding
+
+*******************************************************************************/
+
+#include "block.h"
+
+#include "aac_rom.h"
+#include "FDK_bitstream.h"
+#include "scale.h"
+#include "FDK_tools_rom.h"
+
+#include "usacdec_fac.h"
+#include "usacdec_lpd.h"
+#include "usacdec_lpc.h"
+#include "FDK_trigFcts.h"
+
+#include "ac_arith_coder.h"
+
+#include "aacdec_hcr.h"
+#include "rvlc.h"
+
+#if defined(__arm__)
+#include "arm/block_arm.cpp"
+#endif
+
+/*!
+ \brief Read escape sequence of codeword
+
+ The function reads the escape sequence from the bitstream,
+ if the absolute value of the quantized coefficient has the
+ value 16.
+ A limitation is implemented to maximal 21 bits according to
+ ISO/IEC 14496-3:2009(E) 4.6.3.3.
+ This limits the escape prefix to a maximum of eight 1's.
+ If more than eight 1's are read, MAX_QUANTIZED_VALUE + 1 is
+ returned, independent of the sign of parameter q.
+
+ \return quantized coefficient
+*/
+LONG CBlock_GetEscape(HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */
+ const LONG q) /*!< quantized coefficient */
+{
+ if (fAbs(q) != 16) return (q);
+
+ LONG i, off;
+ for (i = 4; i < 13; i++) {
+ if (FDKreadBit(bs) == 0) break;
+ }
+
+ if (i == 13) return (MAX_QUANTIZED_VALUE + 1);
+
+ off = FDKreadBits(bs, i);
+ i = off + (1 << i);
+
+ if (q < 0) i = -i;
+
+ return i;
+}
+
+AAC_DECODER_ERROR CBlock_ReadScaleFactorData(
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo, HANDLE_FDK_BITSTREAM bs,
+ UINT flags) {
+ int temp;
+ int band;
+ int group;
+ int position = 0; /* accu for intensity delta coding */
+ int factor = pAacDecoderChannelInfo->pDynData->RawDataInfo
+ .GlobalGain; /* accu for scale factor delta coding */
+ UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
+ SHORT *pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor;
+ const CodeBookDescription *hcb = &AACcodeBookDescriptionTable[BOOKSCL];
+
+ const USHORT(*CodeBook)[HuffmanEntries] = hcb->CodeBook;
+
+ int ScaleFactorBandsTransmitted =
+ GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+ for (group = 0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo);
+ group++) {
+ for (band = 0; band < ScaleFactorBandsTransmitted; band++) {
+ switch (pCodeBook[band]) {
+ case ZERO_HCB: /* zero book */
+ pScaleFactor[band] = 0;
+ break;
+
+ default: /* decode scale factor */
+ if (!((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) && band == 0 &&
+ group == 0)) {
+ temp = CBlock_DecodeHuffmanWordCB(bs, CodeBook);
+ factor += temp - 60; /* MIDFAC 1.5 dB */
+ }
+ pScaleFactor[band] = factor - 100;
+ break;
+
+ case INTENSITY_HCB: /* intensity steering */
+ case INTENSITY_HCB2:
+ temp = CBlock_DecodeHuffmanWordCB(bs, CodeBook);
+ position += temp - 60;
+ pScaleFactor[band] = position - 100;
+ break;
+
+ case NOISE_HCB: /* PNS */
+ if (flags & (AC_MPEGD_RES | AC_USAC | AC_RSVD50 | AC_RSV603DA)) {
+ return AAC_DEC_PARSE_ERROR;
+ }
+ CPns_Read(&pAacDecoderChannelInfo->data.aac.PnsData, bs, hcb,
+ pAacDecoderChannelInfo->pDynData->aScaleFactor,
+ pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain,
+ band, group);
+ break;
+ }
+ }
+ pCodeBook += 16;
+ pScaleFactor += 16;
+ }
+
+ return AAC_DEC_OK;
+}
+
+void CBlock_ScaleSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ UCHAR maxSfbs,
+ SamplingRateInfo *pSamplingRateInfo) {
+ int band;
+ int window;
+ const SHORT *RESTRICT pSfbScale = pAacDecoderChannelInfo->pDynData->aSfbScale;
+ SHORT *RESTRICT pSpecScale = pAacDecoderChannelInfo->specScale;
+ int groupwin, group;
+ const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets(
+ &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
+ SPECTRAL_PTR RESTRICT pSpectralCoefficient =
+ pAacDecoderChannelInfo->pSpectralCoefficient;
+
+ FDKmemclear(pSpecScale, 8 * sizeof(SHORT));
+
+ for (window = 0, group = 0;
+ group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++) {
+ for (groupwin = 0; groupwin < GetWindowGroupLength(
+ &pAacDecoderChannelInfo->icsInfo, group);
+ groupwin++, window++) {
+ int SpecScale_window = pSpecScale[window];
+ FIXP_DBL *pSpectrum = SPEC(pSpectralCoefficient, window,
+ pAacDecoderChannelInfo->granuleLength);
+
+ /* find scaling for current window */
+ for (band = 0; band < maxSfbs; band++) {
+ SpecScale_window =
+ fMax(SpecScale_window, (int)pSfbScale[window * 16 + band]);
+ }
+
+ if (pAacDecoderChannelInfo->pDynData->TnsData.Active &&
+ pAacDecoderChannelInfo->pDynData->TnsData.NumberOfFilters[window] >
+ 0) {
+ int filter_index, SpecScale_window_tns;
+ int tns_start, tns_stop;
+
+ /* Find max scale of TNS bands */
+ SpecScale_window_tns = 0;
+ tns_start = GetMaximumTnsBands(&pAacDecoderChannelInfo->icsInfo,
+ pSamplingRateInfo->samplingRateIndex);
+ tns_stop = 0;
+ for (filter_index = 0;
+ filter_index < (int)pAacDecoderChannelInfo->pDynData->TnsData
+ .NumberOfFilters[window];
+ filter_index++) {
+ for (band = pAacDecoderChannelInfo->pDynData->TnsData
+ .Filter[window][filter_index]
+ .StartBand;
+ band < pAacDecoderChannelInfo->pDynData->TnsData
+ .Filter[window][filter_index]
+ .StopBand;
+ band++) {
+ SpecScale_window_tns =
+ fMax(SpecScale_window_tns, (int)pSfbScale[window * 16 + band]);
+ }
+ /* Find TNS line boundaries for all TNS filters */
+ tns_start =
+ fMin(tns_start, (int)pAacDecoderChannelInfo->pDynData->TnsData
+ .Filter[window][filter_index]
+ .StartBand);
+ tns_stop =
+ fMax(tns_stop, (int)pAacDecoderChannelInfo->pDynData->TnsData
+ .Filter[window][filter_index]
+ .StopBand);
+ }
+ SpecScale_window_tns = SpecScale_window_tns +
+ pAacDecoderChannelInfo->pDynData->TnsData.GainLd;
+ FDK_ASSERT(tns_stop >= tns_start);
+ /* Consider existing headroom of all MDCT lines inside the TNS bands. */
+ SpecScale_window_tns -=
+ getScalefactor(pSpectrum + BandOffsets[tns_start],
+ BandOffsets[tns_stop] - BandOffsets[tns_start]);
+ if (SpecScale_window <= 17) {
+ SpecScale_window_tns++;
+ }
+ /* Add enough mantissa head room such that the spectrum is still
+ representable after applying TNS. */
+ SpecScale_window = fMax(SpecScale_window, SpecScale_window_tns);
+ }
+
+ /* store scaling of current window */
+ pSpecScale[window] = SpecScale_window;
+
+#ifdef FUNCTION_CBlock_ScaleSpectralData_func1
+
+ CBlock_ScaleSpectralData_func1(pSpectrum, maxSfbs, BandOffsets,
+ SpecScale_window, pSfbScale, window);
+
+#else /* FUNCTION_CBlock_ScaleSpectralData_func1 */
+ for (band = 0; band < maxSfbs; band++) {
+ int scale = fMin(DFRACT_BITS - 1,
+ SpecScale_window - pSfbScale[window * 16 + band]);
+ if (scale) {
+ FDK_ASSERT(scale > 0);
+
+ /* following relation can be used for optimizations:
+ * (BandOffsets[i]%4) == 0 for all i */
+ int max_index = BandOffsets[band + 1];
+ DWORD_ALIGNED(pSpectrum);
+ for (int index = BandOffsets[band]; index < max_index; index++) {
+ pSpectrum[index] >>= scale;
+ }
+ }
+ }
+#endif /* FUNCTION_CBlock_ScaleSpectralData_func1 */
+ }
+ }
+}
+
+AAC_DECODER_ERROR CBlock_ReadSectionData(
+ HANDLE_FDK_BITSTREAM bs, CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo, const UINT flags) {
+ int top, band;
+ int sect_len, sect_len_incr;
+ int group;
+ UCHAR sect_cb;
+ UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
+ /* HCR input (long) */
+ SHORT *pNumLinesInSec =
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.aNumLineInSec4Hcr;
+ int numLinesInSecIdx = 0;
+ UCHAR *pHcrCodeBook =
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.aCodeBooks4Hcr;
+ const SHORT *BandOffsets = GetScaleFactorBandOffsets(
+ &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection = 0;
+ AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
+
+ FDKmemclear(pCodeBook, sizeof(UCHAR) * (8 * 16));
+
+ const int nbits =
+ (IsLongBlock(&pAacDecoderChannelInfo->icsInfo) == 1) ? 5 : 3;
+
+ int sect_esc_val = (1 << nbits) - 1;
+
+ UCHAR ScaleFactorBandsTransmitted =
+ GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+ for (group = 0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo);
+ group++) {
+ for (band = 0; band < ScaleFactorBandsTransmitted;) {
+ sect_len = 0;
+ if (flags & AC_ER_VCB11) {
+ sect_cb = (UCHAR)FDKreadBits(bs, 5);
+ } else
+ sect_cb = (UCHAR)FDKreadBits(bs, 4);
+
+ if (((flags & AC_ER_VCB11) == 0) || (sect_cb < 11) ||
+ ((sect_cb > 11) && (sect_cb < 16))) {
+ sect_len_incr = FDKreadBits(bs, nbits);
+ while (sect_len_incr == sect_esc_val) {
+ sect_len += sect_esc_val;
+ sect_len_incr = FDKreadBits(bs, nbits);
+ }
+ } else {
+ sect_len_incr = 1;
+ }
+
+ sect_len += sect_len_incr;
+
+ top = band + sect_len;
+
+ if (flags & AC_ER_HCR) {
+ /* HCR input (long) -- collecting sideinfo (for HCR-_long_ only) */
+ if (numLinesInSecIdx >= MAX_SFB_HCR) {
+ return AAC_DEC_PARSE_ERROR;
+ }
+ if (top > (int)GetNumberOfScaleFactorBands(
+ &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo)) {
+ return AAC_DEC_PARSE_ERROR;
+ }
+ pNumLinesInSec[numLinesInSecIdx] = BandOffsets[top] - BandOffsets[band];
+ numLinesInSecIdx++;
+ if (sect_cb == BOOKSCL) {
+ return AAC_DEC_INVALID_CODE_BOOK;
+ } else {
+ *pHcrCodeBook++ = sect_cb;
+ }
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection++;
+ }
+
+ /* Check spectral line limits */
+ if (IsLongBlock(&(pAacDecoderChannelInfo->icsInfo))) {
+ if (top > 64) {
+ return AAC_DEC_DECODE_FRAME_ERROR;
+ }
+ } else { /* short block */
+ if (top + group * 16 > (8 * 16)) {
+ return AAC_DEC_DECODE_FRAME_ERROR;
+ }
+ }
+
+ /* Check if decoded codebook index is feasible */
+ if ((sect_cb == BOOKSCL) ||
+ ((sect_cb == INTENSITY_HCB || sect_cb == INTENSITY_HCB2) &&
+ pAacDecoderChannelInfo->pDynData->RawDataInfo.CommonWindow == 0)) {
+ return AAC_DEC_INVALID_CODE_BOOK;
+ }
+
+ /* Store codebook index */
+ for (; band < top; band++) {
+ pCodeBook[group * 16 + band] = sect_cb;
+ }
+ }
+ }
+
+ return ErrorStatus;
+}
+
+/* mso: provides a faster way to i-quantize a whole band in one go */
+
+/**
+ * \brief inverse quantize one sfb. Each value of the sfb is processed according
+ * to the formula: spectrum[i] = Sign(spectrum[i]) * Matissa(spectrum[i])^(4/3)
+ * * 2^(lsb/4).
+ * \param spectrum pointer to first line of the sfb to be inverse quantized.
+ * \param noLines number of lines belonging to the sfb.
+ * \param lsb last 2 bits of the scale factor of the sfb.
+ * \param scale max allowed shift scale for the sfb.
+ */
+static inline void InverseQuantizeBand(
+ FIXP_DBL *RESTRICT spectrum, const FIXP_DBL *RESTRICT InverseQuantTabler,
+ const FIXP_DBL *RESTRICT MantissaTabler,
+ const SCHAR *RESTRICT ExponentTabler, INT noLines, INT scale) {
+ scale = scale + 1; /* +1 to compensate fMultDiv2 shift-right in loop */
+
+ FIXP_DBL *RESTRICT ptr = spectrum;
+ FIXP_DBL signedValue;
+
+ for (INT i = noLines; i--;) {
+ if ((signedValue = *ptr++) != FL2FXCONST_DBL(0)) {
+ FIXP_DBL value = fAbs(signedValue);
+ UINT freeBits = CntLeadingZeros(value);
+ UINT exponent = 32 - freeBits;
+
+ UINT x = (UINT)(LONG)value << (INT)freeBits;
+ x <<= 1; /* shift out sign bit to avoid masking later on */
+ UINT tableIndex = x >> 24;
+ x = (x >> 20) & 0x0F;
+
+ UINT r0 = (UINT)(LONG)InverseQuantTabler[tableIndex + 0];
+ UINT r1 = (UINT)(LONG)InverseQuantTabler[tableIndex + 1];
+ UINT temp = (r1 - r0) * x + (r0 << 4);
+
+ value = fMultDiv2((FIXP_DBL)temp, MantissaTabler[exponent]);
+
+ /* + 1 compensates fMultDiv2() */
+ scaleValueInPlace(&value, scale + ExponentTabler[exponent]);
+
+ signedValue = (signedValue < (FIXP_DBL)0) ? -value : value;
+ ptr[-1] = signedValue;
+ }
+ }
+}
+
+static inline FIXP_DBL maxabs_D(const FIXP_DBL *pSpectralCoefficient,
+ const int noLines) {
+ /* Find max spectral line value of the current sfb */
+ FIXP_DBL locMax = (FIXP_DBL)0;
+ int i;
+
+ DWORD_ALIGNED(pSpectralCoefficient);
+
+ for (i = noLines; i-- > 0;) {
+ /* Expensive memory access */
+ locMax = fMax(fixp_abs(pSpectralCoefficient[i]), locMax);
+ }
+
+ return locMax;
+}
+
+AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData(
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ SamplingRateInfo *pSamplingRateInfo, UCHAR *band_is_noise,
+ UCHAR active_band_search) {
+ int window, group, groupwin, band;
+ int ScaleFactorBandsTransmitted =
+ GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+ UCHAR *RESTRICT pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
+ SHORT *RESTRICT pSfbScale = pAacDecoderChannelInfo->pDynData->aSfbScale;
+ SHORT *RESTRICT pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor;
+ const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets(
+ &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
+ const SHORT total_bands =
+ GetScaleFactorBandsTotal(&pAacDecoderChannelInfo->icsInfo);
+
+ FDKmemclear(pAacDecoderChannelInfo->pDynData->aSfbScale,
+ (8 * 16) * sizeof(SHORT));
+
+ for (window = 0, group = 0;
+ group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++) {
+ for (groupwin = 0; groupwin < GetWindowGroupLength(
+ &pAacDecoderChannelInfo->icsInfo, group);
+ groupwin++, window++) {
+ /* inverse quantization */
+ for (band = 0; band < ScaleFactorBandsTransmitted; band++) {
+ FIXP_DBL *pSpectralCoefficient =
+ SPEC(pAacDecoderChannelInfo->pSpectralCoefficient, window,
+ pAacDecoderChannelInfo->granuleLength) +
+ BandOffsets[band];
+ FIXP_DBL locMax;
+
+ const int noLines = BandOffsets[band + 1] - BandOffsets[band];
+ const int bnds = group * 16 + band;
+
+ if ((pCodeBook[bnds] == ZERO_HCB) ||
+ (pCodeBook[bnds] == INTENSITY_HCB) ||
+ (pCodeBook[bnds] == INTENSITY_HCB2))
+ continue;
+
+ if (pCodeBook[bnds] == NOISE_HCB) {
+ /* Leave headroom for PNS values. + 1 because ceil(log2(2^(0.25*3))) =
+ 1, worst case of additional headroom required because of the
+ scalefactor. */
+ pSfbScale[window * 16 + band] = (pScaleFactor[bnds] >> 2) + 1;
+ continue;
+ }
+
+ locMax = maxabs_D(pSpectralCoefficient, noLines);
+
+ if (active_band_search) {
+ if (locMax != FIXP_DBL(0)) {
+ band_is_noise[group * 16 + band] = 0;
+ }
+ }
+
+ /* Cheap robustness improvement - Do not remove!!! */
+ if (fixp_abs(locMax) > (FIXP_DBL)MAX_QUANTIZED_VALUE) {
+ return AAC_DEC_PARSE_ERROR;
+ }
+
+ /* Added by Youliy Ninov:
+ The inverse quantization operation is given by (ISO/IEC 14496-3:2009(E))
+ by:
+
+ x_invquant=Sign(x_quant). abs(x_quant)^(4/3)
+
+ We apply a gain, derived from the scale factor for the particular sfb,
+ according to the following function:
+
+ gain=2^(0.25*ScaleFactor)
+
+ So, after scaling we have:
+
+ x_rescale=gain*x_invquant=Sign(x_quant)*2^(0.25*ScaleFactor)*abs(s_quant)^(4/3)
+
+ We could represent the ScaleFactor as:
+
+ ScaleFactor= (ScaleFactor >> 2)*4 + ScaleFactor %4
+
+ When we substitute it we get:
+
+ x_rescale=Sign(x_quant)*2^(ScaleFactor>>2)* (
+ 2^(0.25*(ScaleFactor%4))*abs(s_quant)^(4/3))
+
+ When we set: msb=(ScaleFactor>>2) and lsb=(ScaleFactor%4), we obtain:
+
+ x_rescale=Sign(x_quant)*(2^msb)* ( 2^(lsb/4)*abs(s_quant)^(4/3))
+
+ The rescaled output can be represented by:
+ mantissa : Sign(x_quant)*( 2^(lsb/4)*abs(s_quant)^(4/3))
+ exponent :(2^msb)
+
+ */
+
+ int msb = pScaleFactor[bnds] >> 2;
+
+ /* Inverse quantize band only if it is not empty */
+ if (locMax != FIXP_DBL(0)) {
+ int lsb = pScaleFactor[bnds] & 0x03;
+
+ int scale = EvaluatePower43(&locMax, lsb);
+
+ scale = CntLeadingZeros(locMax) - scale - 2;
+
+ pSfbScale[window * 16 + band] = msb - scale;
+ InverseQuantizeBand(pSpectralCoefficient, InverseQuantTable,
+ MantissaTable[lsb], ExponentTable[lsb], noLines,
+ scale);
+ } else {
+ pSfbScale[window * 16 + band] = msb;
+ }
+
+ } /* for (band=0; band < ScaleFactorBandsTransmitted; band++) */
+
+ /* Make sure the array is cleared to the end */
+ SHORT start_clear = BandOffsets[ScaleFactorBandsTransmitted];
+ SHORT end_clear = BandOffsets[total_bands];
+ int diff_clear = (int)(end_clear - start_clear);
+ FIXP_DBL *pSpectralCoefficient =
+ SPEC(pAacDecoderChannelInfo->pSpectralCoefficient, window,
+ pAacDecoderChannelInfo->granuleLength) +
+ start_clear;
+ FDKmemclear(pSpectralCoefficient, diff_clear * sizeof(FIXP_DBL));
+
+ } /* for (groupwin=0; groupwin <
+ GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group);
+ groupwin++, window++) */
+ } /* for (window=0, group=0; group <
+ GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++)*/
+
+ return AAC_DEC_OK;
+}
+
+AAC_DECODER_ERROR CBlock_ReadSpectralData(
+ HANDLE_FDK_BITSTREAM bs, CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo, const UINT flags) {
+ int index, i;
+ const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets(
+ &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
+
+ SPECTRAL_PTR pSpectralCoefficient =
+ pAacDecoderChannelInfo->pSpectralCoefficient;
+
+ FDK_ASSERT(BandOffsets != NULL);
+
+ FDKmemclear(pSpectralCoefficient, sizeof(SPECTRUM));
+
+ if ((flags & AC_ER_HCR) == 0) {
+ int group;
+ int groupoffset;
+ UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
+ int ScaleFactorBandsTransmitted =
+ GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+ int granuleLength = pAacDecoderChannelInfo->granuleLength;
+
+ groupoffset = 0;
+
+ /* plain huffman decoder short */
+ int max_group = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo);
+
+ for (group = 0; group < max_group; group++) {
+ int max_groupwin =
+ GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo, group);
+ int band;
+
+ int bnds = group * 16;
+
+ int bandOffset1 = BandOffsets[0];
+ for (band = 0; band < ScaleFactorBandsTransmitted; band++, bnds++) {
+ UCHAR currentCB = pCodeBook[bnds];
+ int bandOffset0 = bandOffset1;
+ bandOffset1 = BandOffsets[band + 1];
+
+ /* patch to run plain-huffman-decoder with vcb11 input codebooks
+ * (LAV-checking might be possible below using the virtual cb and a
+ * LAV-table) */
+ if ((currentCB >= 16) && (currentCB <= 31)) {
+ pCodeBook[bnds] = currentCB = 11;
+ }
+ if (((currentCB != ZERO_HCB) && (currentCB != NOISE_HCB) &&
+ (currentCB != INTENSITY_HCB) && (currentCB != INTENSITY_HCB2))) {
+ const CodeBookDescription *hcb =
+ &AACcodeBookDescriptionTable[currentCB];
+ int step = hcb->Dimension;
+ int offset = hcb->Offset;
+ int bits = hcb->numBits;
+ int mask = (1 << bits) - 1;
+ const USHORT(*CodeBook)[HuffmanEntries] = hcb->CodeBook;
+ int groupwin;
+
+ FIXP_DBL *mdctSpectrum =
+ &pSpectralCoefficient[groupoffset * granuleLength];
+
+ if (offset == 0) {
+ for (groupwin = 0; groupwin < max_groupwin; groupwin++) {
+ for (index = bandOffset0; index < bandOffset1; index += step) {
+ int idx = CBlock_DecodeHuffmanWordCB(bs, CodeBook);
+ for (i = 0; i < step; i++, idx >>= bits) {
+ FIXP_DBL tmp = (FIXP_DBL)((idx & mask) - offset);
+ if (tmp != FIXP_DBL(0)) tmp = (FDKreadBit(bs)) ? -tmp : tmp;
+ mdctSpectrum[index + i] = tmp;
+ }
+
+ if (currentCB == ESCBOOK) {
+ for (int j = 0; j < 2; j++)
+ mdctSpectrum[index + j] = (FIXP_DBL)CBlock_GetEscape(
+ bs, (LONG)mdctSpectrum[index + j]);
+ }
+ }
+ mdctSpectrum += granuleLength;
+ }
+ } else {
+ for (groupwin = 0; groupwin < max_groupwin; groupwin++) {
+ for (index = bandOffset0; index < bandOffset1; index += step) {
+ int idx = CBlock_DecodeHuffmanWordCB(bs, CodeBook);
+ for (i = 0; i < step; i++, idx >>= bits) {
+ mdctSpectrum[index + i] = (FIXP_DBL)((idx & mask) - offset);
+ }
+ if (currentCB == ESCBOOK) {
+ for (int j = 0; j < 2; j++)
+ mdctSpectrum[index + j] = (FIXP_DBL)CBlock_GetEscape(
+ bs, (LONG)mdctSpectrum[index + j]);
+ }
+ }
+ mdctSpectrum += granuleLength;
+ }
+ }
+ }
+ }
+ groupoffset += max_groupwin;
+ }
+ /* plain huffman decoding (short) finished */
+ }
+
+ /* HCR - Huffman Codeword Reordering short */
+ else /* if ( flags & AC_ER_HCR ) */
+
+ {
+ H_HCR_INFO hHcr = &pAacDecoderChannelInfo->pComData->overlay.aac.erHcrInfo;
+
+ int hcrStatus = 0;
+
+ /* advanced Huffman decoding starts here (HCR decoding :) */
+ if (pAacDecoderChannelInfo->pDynData->specificTo.aac
+ .lenOfReorderedSpectralData != 0) {
+ /* HCR initialization short */
+ hcrStatus = HcrInit(hHcr, pAacDecoderChannelInfo, pSamplingRateInfo, bs);
+
+ if (hcrStatus != 0) {
+ return AAC_DEC_DECODE_FRAME_ERROR;
+ }
+
+ /* HCR decoding short */
+ hcrStatus =
+ HcrDecoder(hHcr, pAacDecoderChannelInfo, pSamplingRateInfo, bs);
+
+ if (hcrStatus != 0) {
+#if HCR_ERROR_CONCEALMENT
+ HcrMuteErroneousLines(hHcr);
+#else
+ return AAC_DEC_DECODE_FRAME_ERROR;
+#endif /* HCR_ERROR_CONCEALMENT */
+ }
+
+ FDKpushFor(bs, pAacDecoderChannelInfo->pDynData->specificTo.aac
+ .lenOfReorderedSpectralData);
+ }
+ }
+ /* HCR - Huffman Codeword Reordering short finished */
+
+ if (IsLongBlock(&pAacDecoderChannelInfo->icsInfo) &&
+ !(flags & (AC_ELD | AC_SCALABLE))) {
+ /* apply pulse data */
+ CPulseData_Apply(
+ &pAacDecoderChannelInfo->pDynData->specificTo.aac.PulseData,
+ GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo,
+ pSamplingRateInfo),
+ SPEC_LONG(pSpectralCoefficient));
+ }
+
+ return AAC_DEC_OK;
+}
+
+static const FIXP_SGL noise_level_tab[8] = {
+ /* FDKpow(2, (float)(noise_level-14)/3.0f) * 2; (*2 to compensate for
+ fMultDiv2) noise_level_tab(noise_level==0) == 0 by definition
+ */
+ FX_DBL2FXCONST_SGL(0x00000000 /*0x0a145173*/),
+ FX_DBL2FXCONST_SGL(0x0cb2ff5e),
+ FX_DBL2FXCONST_SGL(0x10000000),
+ FX_DBL2FXCONST_SGL(0x1428a2e7),
+ FX_DBL2FXCONST_SGL(0x1965febd),
+ FX_DBL2FXCONST_SGL(0x20000000),
+ FX_DBL2FXCONST_SGL(0x28514606),
+ FX_DBL2FXCONST_SGL(0x32cbfd33)};
+
+void CBlock_ApplyNoise(CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ SamplingRateInfo *pSamplingRateInfo, ULONG *nfRandomSeed,
+ UCHAR *band_is_noise) {
+ const SHORT *swb_offset = GetScaleFactorBandOffsets(
+ &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
+ int g, win, gwin, sfb, noiseFillingStartOffset, nfStartOffset_sfb;
+
+ /* Obtain noise level and scale factor offset. */
+ int noise_level = pAacDecoderChannelInfo->pDynData->specificTo.usac
+ .fd_noise_level_and_offset >>
+ 5;
+ const FIXP_SGL noiseVal_pos = noise_level_tab[noise_level];
+
+ /* noise_offset can change even when noise_level=0. Neccesary for IGF stereo
+ * filling */
+ const int noise_offset = (pAacDecoderChannelInfo->pDynData->specificTo.usac
+ .fd_noise_level_and_offset &
+ 0x1f) -
+ 16;
+
+ int max_sfb =
+ GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+
+ noiseFillingStartOffset =
+ (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT)
+ ? 20
+ : 160;
+ if (pAacDecoderChannelInfo->granuleLength == 96) {
+ noiseFillingStartOffset =
+ (3 * noiseFillingStartOffset) /
+ 4; /* scale offset with 3/4 for coreCoderFrameLength == 768 */
+ }
+
+ /* determine sfb from where on noise filling is applied */
+ for (sfb = 0; swb_offset[sfb] < noiseFillingStartOffset; sfb++)
+ ;
+ nfStartOffset_sfb = sfb;
+
+ /* if (noise_level!=0) */
+ {
+ for (g = 0, win = 0; g < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo);
+ g++) {
+ int windowGroupLength =
+ GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo, g);
+ for (sfb = nfStartOffset_sfb; sfb < max_sfb; sfb++) {
+ int bin_start = swb_offset[sfb];
+ int bin_stop = swb_offset[sfb + 1];
+
+ int flagN = band_is_noise[g * 16 + sfb];
+
+ /* if all bins of one sfb in one window group are zero modify the scale
+ * factor by noise_offset */
+ if (flagN) {
+ /* Change scaling factors for empty signal bands */
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[g * 16 + sfb] +=
+ noise_offset;
+ /* scale factor "sf" implied gain "g" is g = 2^(sf/4) */
+ for (gwin = 0; gwin < windowGroupLength; gwin++) {
+ pAacDecoderChannelInfo->pDynData
+ ->aSfbScale[(win + gwin) * 16 + sfb] += (noise_offset >> 2);
+ }
+ }
+
+ ULONG seed = *nfRandomSeed;
+ /* + 1 because exponent of MantissaTable[lsb][0] is always 1. */
+ int scale =
+ (pAacDecoderChannelInfo->pDynData->aScaleFactor[g * 16 + sfb] >>
+ 2) +
+ 1;
+ int lsb =
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[g * 16 + sfb] & 3;
+ FIXP_DBL mantissa = MantissaTable[lsb][0];
+
+ for (gwin = 0; gwin < windowGroupLength; gwin++) {
+ FIXP_DBL *pSpec =
+ SPEC(pAacDecoderChannelInfo->pSpectralCoefficient, win + gwin,
+ pAacDecoderChannelInfo->granuleLength);
+
+ int scale1 = scale - pAacDecoderChannelInfo->pDynData
+ ->aSfbScale[(win + gwin) * 16 + sfb];
+ FIXP_DBL scaled_noiseVal_pos =
+ scaleValue(fMultDiv2(noiseVal_pos, mantissa), scale1);
+ FIXP_DBL scaled_noiseVal_neg = -scaled_noiseVal_pos;
+
+ /* If the whole band is zero, just fill without checking */
+ if (flagN) {
+ for (int bin = bin_start; bin < bin_stop; bin++) {
+ seed = (ULONG)(
+ (UINT64)seed * 69069 +
+ 5); /* Inlined: UsacRandomSign - origin in usacdec_lpd.h */
+ pSpec[bin] =
+ (seed & 0x10000) ? scaled_noiseVal_neg : scaled_noiseVal_pos;
+ } /* for (bin...) */
+ }
+ /*If band is sparsely filled, check for 0 and fill */
+ else {
+ for (int bin = bin_start; bin < bin_stop; bin++) {
+ if (pSpec[bin] == (FIXP_DBL)0) {
+ seed = (ULONG)(
+ (UINT64)seed * 69069 +
+ 5); /* Inlined: UsacRandomSign - origin in usacdec_lpd.h */
+ pSpec[bin] = (seed & 0x10000) ? scaled_noiseVal_neg
+ : scaled_noiseVal_pos;
+ }
+ } /* for (bin...) */
+ }
+
+ } /* for (gwin...) */
+ *nfRandomSeed = seed;
+ } /* for (sfb...) */
+ win += windowGroupLength;
+ } /* for (g...) */
+
+ } /* ... */
+}
+
+AAC_DECODER_ERROR CBlock_ReadAcSpectralData(
+ HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo, const UINT frame_length,
+ const UINT flags) {
+ AAC_DECODER_ERROR errorAAC = AAC_DEC_OK;
+ ARITH_CODING_ERROR error = ARITH_CODER_OK;
+ int arith_reset_flag, lg, numWin, win, winLen;
+ const SHORT *RESTRICT BandOffsets;
+
+ /* number of transmitted spectral coefficients */
+ BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo,
+ pSamplingRateInfo);
+ lg = BandOffsets[GetScaleFactorBandsTransmitted(
+ &pAacDecoderChannelInfo->icsInfo)];
+
+ numWin = GetWindowsPerFrame(&pAacDecoderChannelInfo->icsInfo);
+ winLen = (IsLongBlock(&pAacDecoderChannelInfo->icsInfo))
+ ? (int)frame_length
+ : (int)frame_length / numWin;
+
+ if (flags & AC_INDEP) {
+ arith_reset_flag = 1;
+ } else {
+ arith_reset_flag = (USHORT)FDKreadBits(hBs, 1);
+ }
+
+ for (win = 0; win < numWin; win++) {
+ error =
+ CArco_DecodeArithData(pAacDecoderStaticChannelInfo->hArCo, hBs,
+ SPEC(pAacDecoderChannelInfo->pSpectralCoefficient,
+ win, pAacDecoderChannelInfo->granuleLength),
+ lg, winLen, arith_reset_flag && (win == 0));
+ if (error != ARITH_CODER_OK) {
+ goto bail;
+ }
+ }
+
+bail:
+ if (error == ARITH_CODER_ERROR) {
+ errorAAC = AAC_DEC_PARSE_ERROR;
+ }
+
+ return errorAAC;
+}
+
+void ApplyTools(CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
+ const SamplingRateInfo *pSamplingRateInfo, const UINT flags,
+ const UINT elFlags, const int channel,
+ const int common_window) {
+ if (!(flags & (AC_USAC | AC_RSVD50 | AC_MPEGD_RES | AC_RSV603DA))) {
+ CPns_Apply(&pAacDecoderChannelInfo[channel]->data.aac.PnsData,
+ &pAacDecoderChannelInfo[channel]->icsInfo,
+ pAacDecoderChannelInfo[channel]->pSpectralCoefficient,
+ pAacDecoderChannelInfo[channel]->specScale,
+ pAacDecoderChannelInfo[channel]->pDynData->aScaleFactor,
+ pSamplingRateInfo,
+ pAacDecoderChannelInfo[channel]->granuleLength, channel);
+ }
+
+ UCHAR nbands =
+ GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[channel]->icsInfo);
+
+ CTns_Apply(&pAacDecoderChannelInfo[channel]->pDynData->TnsData,
+ &pAacDecoderChannelInfo[channel]->icsInfo,
+ pAacDecoderChannelInfo[channel]->pSpectralCoefficient,
+ pSamplingRateInfo, pAacDecoderChannelInfo[channel]->granuleLength,
+ nbands, (elFlags & AC_EL_ENHANCED_NOISE) ? 1 : 0, flags);
+}
+
+static int getWindow2Nr(int length, int shape) {
+ int nr = 0;
+
+ if (shape == 2) {
+ /* Low Overlap, 3/4 zeroed */
+ nr = (length * 3) >> 2;
+ }
+
+ return nr;
+}
+
+FIXP_DBL get_gain(const FIXP_DBL *x, const FIXP_DBL *y, int n) {
+ FIXP_DBL corr = (FIXP_DBL)0;
+ FIXP_DBL ener = (FIXP_DBL)1;
+
+ int headroom_x = getScalefactor(x, n);
+ int headroom_y = getScalefactor(y, n);
+
+ /*Calculate the normalization necessary due to addition*/
+ /* Check for power of two /special case */
+ INT width_shift = (INT)(fNormz((FIXP_DBL)n));
+ /* Get the number of bits necessary minus one, because we need one sign bit
+ * only */
+ width_shift = 31 - width_shift;
+
+ for (int i = 0; i < n; i++) {
+ corr +=
+ fMultDiv2((x[i] << headroom_x), (y[i] << headroom_y)) >> width_shift;
+ ener += fPow2Div2((y[i] << headroom_y)) >> width_shift;
+ }
+
+ int exp_corr = (17 - headroom_x) + (17 - headroom_y) + width_shift + 1;
+ int exp_ener = ((17 - headroom_y) << 1) + width_shift + 1;
+
+ int temp_exp = 0;
+ FIXP_DBL output = fDivNormSigned(corr, ener, &temp_exp);
+
+ int output_exp = (exp_corr - exp_ener) + temp_exp;
+
+ INT output_shift = 17 - output_exp;
+ output_shift = fMin(output_shift, 31);
+
+ output = scaleValue(output, -output_shift);
+
+ return output;
+}
+
+void CBlock_FrequencyToTime(
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[],
+ const SHORT frameLen, const int frameOk, FIXP_DBL *pWorkBuffer1,
+ UINT elFlags, INT elCh) {
+ int fr, fl, tl, nSpec;
+
+#if defined(FDK_ASSERT_ENABLE)
+ LONG nSamples;
+#endif
+
+ /* Determine left slope length (fl), right slope length (fr) and transform
+ length (tl). USAC: The slope length may mismatch with the previous frame in
+ case of LPD / FD transitions. The adjustment is handled by the imdct
+ implementation.
+ */
+ tl = frameLen;
+ nSpec = 1;
+
+ switch (pAacDecoderChannelInfo->icsInfo.WindowSequence) {
+ default:
+ case BLOCK_LONG:
+ fl = frameLen;
+ fr = frameLen -
+ getWindow2Nr(frameLen,
+ GetWindowShape(&pAacDecoderChannelInfo->icsInfo));
+ /* New startup needs differentiation between sine shape and low overlap
+ shape. This is a special case for the LD-AAC transformation windows,
+ because the slope length can be different while using the same window
+ sequence. */
+ if (pAacDecoderStaticChannelInfo->IMdct.prev_tl == 0) {
+ fl = fr;
+ }
+ break;
+ case BLOCK_STOP:
+ fl = frameLen >> 3;
+ fr = frameLen;
+ break;
+ case BLOCK_START: /* or StopStartSequence */
+ fl = frameLen;
+ fr = frameLen >> 3;
+ break;
+ case BLOCK_SHORT:
+ fl = fr = frameLen >> 3;
+ tl >>= 3;
+ nSpec = 8;
+ break;
+ }
+
+ {
+ int last_frame_lost = pAacDecoderStaticChannelInfo->last_lpc_lost;
+
+ if (pAacDecoderStaticChannelInfo->last_core_mode == LPD) {
+ INT fac_FB = 1;
+ if (elFlags & AC_EL_FULLBANDLPD) {
+ fac_FB = 2;
+ }
+
+ FIXP_DBL *synth;
+
+ /* Keep some free space at the beginning of the buffer. To be used for
+ * past data */
+ if (!(elFlags & AC_EL_LPDSTEREOIDX)) {
+ synth = pWorkBuffer1 + ((PIT_MAX_MAX - (1 * L_SUBFR)) * fac_FB);
+ } else {
+ synth = pWorkBuffer1 + PIT_MAX_MAX * fac_FB;
+ }
+
+ int fac_length =
+ (pAacDecoderChannelInfo->icsInfo.WindowSequence == BLOCK_SHORT)
+ ? (frameLen >> 4)
+ : (frameLen >> 3);
+
+ INT pitch[NB_SUBFR_SUPERFR + SYN_SFD];
+ FIXP_DBL pit_gain[NB_SUBFR_SUPERFR + SYN_SFD];
+
+ int nbDiv = (elFlags & AC_EL_FULLBANDLPD) ? 2 : 4;
+ int lFrame = (elFlags & AC_EL_FULLBANDLPD) ? frameLen / 2 : frameLen;
+ int nbSubfr =
+ lFrame / (nbDiv * L_SUBFR); /* number of subframes per division */
+ int LpdSfd = (nbDiv * nbSubfr) >> 1;
+ int SynSfd = LpdSfd - BPF_SFD;
+
+ FDKmemclear(
+ pitch,
+ sizeof(
+ pitch)); // added to prevent ferret errors in bass_pf_1sf_delay
+ FDKmemclear(pit_gain, sizeof(pit_gain));
+
+ /* FAC case */
+ if (pAacDecoderStaticChannelInfo->last_lpd_mode == 0 ||
+ pAacDecoderStaticChannelInfo->last_lpd_mode == 4) {
+ FIXP_DBL fac_buf[LFAC];
+ FIXP_LPC *A = pAacDecoderChannelInfo->data.usac.lp_coeff[0];
+
+ if (!frameOk || last_frame_lost ||
+ (pAacDecoderChannelInfo->data.usac.fac_data[0] == NULL)) {
+ FDKmemclear(fac_buf,
+ pAacDecoderChannelInfo->granuleLength * sizeof(FIXP_DBL));
+ pAacDecoderChannelInfo->data.usac.fac_data[0] = fac_buf;
+ pAacDecoderChannelInfo->data.usac.fac_data_e[0] = 0;
+ }
+
+ INT A_exp; /* linear prediction coefficients exponent */
+ {
+ for (int i = 0; i < M_LP_FILTER_ORDER; i++) {
+ A[i] = FX_DBL2FX_LPC(fixp_cos(
+ fMult(pAacDecoderStaticChannelInfo->lpc4_lsf[i],
+ FL2FXCONST_SGL((1 << LSPARG_SCALE) * M_PI / 6400.0)),
+ LSF_SCALE - LSPARG_SCALE));
+ }
+
+ E_LPC_f_lsp_a_conversion(A, A, &A_exp);
+ }
+
+#if defined(FDK_ASSERT_ENABLE)
+ nSamples =
+#endif
+ CLpd_FAC_Acelp2Mdct(
+ &pAacDecoderStaticChannelInfo->IMdct, synth,
+ SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient),
+ pAacDecoderChannelInfo->specScale, nSpec,
+ pAacDecoderChannelInfo->data.usac.fac_data[0],
+ pAacDecoderChannelInfo->data.usac.fac_data_e[0], fac_length,
+ frameLen, tl,
+ FDKgetWindowSlope(
+ fr, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)),
+ fr, A, A_exp, &pAacDecoderStaticChannelInfo->acelp,
+ (FIXP_DBL)0, /* FAC gain has already been applied. */
+ (last_frame_lost || !frameOk), 1,
+ pAacDecoderStaticChannelInfo->last_lpd_mode, 0,
+ pAacDecoderChannelInfo->currAliasingSymmetry);
+
+ } else {
+#if defined(FDK_ASSERT_ENABLE)
+ nSamples =
+#endif
+ imlt_block(
+ &pAacDecoderStaticChannelInfo->IMdct, synth,
+ SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient),
+ pAacDecoderChannelInfo->specScale, nSpec, frameLen, tl,
+ FDKgetWindowSlope(
+ fl, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)),
+ fl,
+ FDKgetWindowSlope(
+ fr, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)),
+ fr, (FIXP_DBL)0,
+ pAacDecoderChannelInfo->currAliasingSymmetry
+ ? MLT_FLAG_CURR_ALIAS_SYMMETRY
+ : 0);
+ }
+ FDK_ASSERT(nSamples == frameLen);
+
+ /* The "if" clause is entered both for fullbandLpd mono and
+ * non-fullbandLpd*. The "else"-> just for fullbandLpd stereo*/
+ if (!(elFlags & AC_EL_LPDSTEREOIDX)) {
+ FDKmemcpy(pitch, pAacDecoderStaticChannelInfo->old_T_pf,
+ SynSfd * sizeof(INT));
+ FDKmemcpy(pit_gain, pAacDecoderStaticChannelInfo->old_gain_pf,
+ SynSfd * sizeof(FIXP_DBL));
+
+ for (int i = SynSfd; i < LpdSfd + 3; i++) {
+ pitch[i] = L_SUBFR;
+ pit_gain[i] = (FIXP_DBL)0;
+ }
+
+ if (pAacDecoderStaticChannelInfo->last_lpd_mode == 0) {
+ pitch[SynSfd] = pitch[SynSfd - 1];
+ pit_gain[SynSfd] = pit_gain[SynSfd - 1];
+ if (IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) {
+ pitch[SynSfd + 1] = pitch[SynSfd];
+ pit_gain[SynSfd + 1] = pit_gain[SynSfd];
+ }
+ }
+
+ /* Copy old data to the beginning of the buffer */
+ {
+ FDKmemcpy(
+ pWorkBuffer1, pAacDecoderStaticChannelInfo->old_synth,
+ ((PIT_MAX_MAX - (1 * L_SUBFR)) * fac_FB) * sizeof(FIXP_DBL));
+ }
+
+ FIXP_DBL *p2_synth = pWorkBuffer1 + (PIT_MAX_MAX * fac_FB);
+
+ /* recalculate pitch gain to allow postfilering on FAC area */
+ for (int i = 0; i < SynSfd + 2; i++) {
+ int T = pitch[i];
+ FIXP_DBL gain = pit_gain[i];
+
+ if (gain > (FIXP_DBL)0) {
+ gain = get_gain(&p2_synth[i * L_SUBFR * fac_FB],
+ &p2_synth[(i * L_SUBFR * fac_FB) - fac_FB * T],
+ L_SUBFR * fac_FB);
+ pit_gain[i] = gain;
+ }
+ }
+
+ bass_pf_1sf_delay(p2_synth, pitch, pit_gain, frameLen,
+ (LpdSfd + 2) * L_SUBFR + BPF_SFD * L_SUBFR,
+ frameLen - (LpdSfd + 4) * L_SUBFR, outSamples,
+ pAacDecoderStaticChannelInfo->mem_bpf);
+ }
+
+ } else /* last_core_mode was not LPD */
+ {
+ FIXP_DBL *tmp =
+ pAacDecoderChannelInfo->pComStaticData->pWorkBufferCore1->mdctOutTemp;
+#if defined(FDK_ASSERT_ENABLE)
+ nSamples =
+#endif
+ imlt_block(&pAacDecoderStaticChannelInfo->IMdct, tmp,
+ SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient),
+ pAacDecoderChannelInfo->specScale, nSpec, frameLen, tl,
+ FDKgetWindowSlope(
+ fl, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)),
+ fl,
+ FDKgetWindowSlope(
+ fr, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)),
+ fr, (FIXP_DBL)0,
+ pAacDecoderChannelInfo->currAliasingSymmetry
+ ? MLT_FLAG_CURR_ALIAS_SYMMETRY
+ : 0);
+
+ scaleValuesSaturate(outSamples, tmp, frameLen, MDCT_OUT_HEADROOM);
+ }
+ }
+
+ FDK_ASSERT(nSamples == frameLen);
+
+ pAacDecoderStaticChannelInfo->last_core_mode =
+ (pAacDecoderChannelInfo->icsInfo.WindowSequence == BLOCK_SHORT) ? FD_SHORT
+ : FD_LONG;
+ pAacDecoderStaticChannelInfo->last_lpd_mode = 255;
+}
+
+#include "ldfiltbank.h"
+void CBlock_FrequencyToTimeLowDelay(
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[],
+ const short frameLen) {
+ InvMdctTransformLowDelay_fdk(
+ SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient),
+ pAacDecoderChannelInfo->specScale[0], outSamples,
+ pAacDecoderStaticChannelInfo->pOverlapBuffer, frameLen);
+}