| /* ----------------------------------------------------------------------------- |
| 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 31 bits to prevent endless loops. |
| If it strikes, 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 < 32; i++) { |
| if (FDKreadBit(bs) == 0) break; |
| } |
| |
| if (i == 32) 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); |
| } |