diff options
Diffstat (limited to 'libSBRdec/src/sbr_dec.cpp')
-rw-r--r-- | libSBRdec/src/sbr_dec.cpp | 1854 |
1 files changed, 1118 insertions, 736 deletions
diff --git a/libSBRdec/src/sbr_dec.cpp b/libSBRdec/src/sbr_dec.cpp index 0864348..2e18e6c 100644 --- a/libSBRdec/src/sbr_dec.cpp +++ b/libSBRdec/src/sbr_dec.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,19 +90,28 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Sbr decoder - This module provides the actual decoder implementation. The SBR data (side information) is already - decoded. Only three functions are provided: + \brief Sbr decoder + This module provides the actual decoder implementation. The SBR data (side + information) is already decoded. Only three functions are provided: \li 1.) createSbrDec(): One time initialization - \li 2.) resetSbrDec(): Called by sbr_Apply() when the information contained in an SBR_HEADER_ELEMENT requires a reset - and recalculation of important SBR structures. - \li 3.) sbr_dec(): The actual decoder. Calls the different tools such as filterbanks, lppTransposer(), and calculateSbrEnvelope() - [the envelope adjuster]. + \li 2.) resetSbrDec(): Called by sbr_Apply() when the information contained in + an SBR_HEADER_ELEMENT requires a reset and recalculation of important SBR + structures. \li 3.) sbr_dec(): The actual decoder. Calls the different tools + such as filterbanks, lppTransposer(), and calculateSbrEnvelope() [the envelope + adjuster]. \sa sbr_dec(), \ref documentationOverview */ @@ -102,178 +122,90 @@ amm-info@iis.fraunhofer.de #include "env_extr.h" #include "env_calc.h" #include "scale.h" +#include "FDK_matrixCalloc.h" +#include "hbe.h" #include "genericStds.h" #include "sbrdec_drc.h" +static void copyHarmonicSpectrum(int *xOverQmf, FIXP_DBL **qmfReal, + FIXP_DBL **qmfImag, int noCols, int overlap, + KEEP_STATES_SYNCED_MODE keepStatesSynced) { + int patchBands; + int patch, band, col, target, sourceBands, i; + int numPatches = 0; + int slotOffset = 0; + FIXP_DBL **ppqmfReal = qmfReal + overlap; + FIXP_DBL **ppqmfImag = qmfImag + overlap; -static void assignLcTimeSlots( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ - FIXP_DBL **QmfBufferReal, - int noCols ) -{ - int slot, i; - FIXP_DBL *ptr; - - /* Number of QMF timeslots in the overlap buffer: */ - ptr = hSbrDec->pSbrOverlapBuffer; - for(slot=0; slot<hSbrDec->LppTrans.pSettings->overlap; slot++) { - QmfBufferReal[slot] = ptr; ptr += (64); - } - - /* Assign timeslots to Workbuffer1 */ - ptr = hSbrDec->WorkBuffer1; - for(i=0; i<noCols; i++) { - QmfBufferReal[slot] = ptr; ptr += (64); - slot++; - } -} - - -static void assignHqTimeSlots( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ - FIXP_DBL **QmfBufferReal, - FIXP_DBL **QmfBufferImag, - int noCols ) -{ - FIXP_DBL *ptr; - int slot; - - /* Number of QMF timeslots in one half of a frame (size of Workbuffer1 or 2): */ - int halflen = (noCols >> 1) + hSbrDec->LppTrans.pSettings->overlap; - int totCols = noCols + hSbrDec->LppTrans.pSettings->overlap; - - /* Number of QMF timeslots in the overlap buffer: */ - ptr = hSbrDec->pSbrOverlapBuffer; - for(slot=0; slot<hSbrDec->LppTrans.pSettings->overlap; slot++) { - QmfBufferReal[slot] = ptr; ptr += (64); - QmfBufferImag[slot] = ptr; ptr += (64); - } - - /* Assign first half of timeslots to Workbuffer1 */ - ptr = hSbrDec->WorkBuffer1; - for(; slot<halflen; slot++) { - QmfBufferReal[slot] = ptr; ptr += (64); - QmfBufferImag[slot] = ptr; ptr += (64); - } - - /* Assign second half of timeslots to Workbuffer2 */ - ptr = hSbrDec->WorkBuffer2; - for(; slot<totCols; slot++) { - QmfBufferReal[slot] = ptr; ptr += (64); - QmfBufferImag[slot] = ptr; ptr += (64); + if (keepStatesSynced == KEEP_STATES_SYNCED_NORMAL) { + slotOffset = noCols - overlap - LPC_ORDER; } -} - -static void assignTimeSlots( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ - int noCols, - int useLP ) -{ - /* assign qmf time slots */ - hSbrDec->useLP = useLP; - if (useLP) { - hSbrDec->SynthesisQMF.flags |= QMF_FLAG_LP; - hSbrDec->AnalysiscQMF.flags |= QMF_FLAG_LP; - } else { - hSbrDec->SynthesisQMF.flags &= ~QMF_FLAG_LP; - hSbrDec->AnalysiscQMF.flags &= ~QMF_FLAG_LP; - } - if (!useLP) - assignHqTimeSlots( hSbrDec, hSbrDec->QmfBufferReal, hSbrDec->QmfBufferImag, noCols ); - else - { - assignLcTimeSlots( hSbrDec, hSbrDec->QmfBufferReal, noCols ); + if (keepStatesSynced == KEEP_STATES_SYNCED_OUTDIFF) { + ppqmfReal = qmfReal; + ppqmfImag = qmfImag; } -} -static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ - int useLdTimeAlign ) -{ - UINT synQmfFlags = hSbrDec->SynthesisQMF.flags; - UINT anaQmfFlags = hSbrDec->AnalysiscQMF.flags; - int resetSynQmf = 0; - int resetAnaQmf = 0; - - /* assign qmf type */ - if (useLdTimeAlign) { - if (synQmfFlags & QMF_FLAG_CLDFB) { - /* change the type to MPSLD */ - synQmfFlags &= ~QMF_FLAG_CLDFB; - synQmfFlags |= QMF_FLAG_MPSLDFB; - resetSynQmf = 1; - } - if (anaQmfFlags & QMF_FLAG_CLDFB) { - /* change the type to MPSLD */ - anaQmfFlags &= ~QMF_FLAG_CLDFB; - anaQmfFlags |= QMF_FLAG_MPSLDFB; - resetAnaQmf = 1; - } - } else { - if (synQmfFlags & QMF_FLAG_MPSLDFB) { - /* change the type to CLDFB */ - synQmfFlags &= ~QMF_FLAG_MPSLDFB; - synQmfFlags |= QMF_FLAG_CLDFB; - resetSynQmf = 1; - } - if (anaQmfFlags & QMF_FLAG_MPSLDFB) { - /* change the type to CLDFB */ - anaQmfFlags &= ~QMF_FLAG_MPSLDFB; - anaQmfFlags |= QMF_FLAG_CLDFB; - resetAnaQmf = 1; + for (i = 1; i < MAX_NUM_PATCHES; i++) { + if (xOverQmf[i] != 0) { + numPatches++; } } - if (resetAnaQmf) { - QMF_FILTER_BANK prvAnaQmf; - int qmfErr; - - /* Store current configuration */ - FDKmemcpy(&prvAnaQmf, &hSbrDec->AnalysiscQMF, sizeof(QMF_FILTER_BANK)); - - /* Reset analysis QMF */ - qmfErr = qmfInitAnalysisFilterBank ( - &hSbrDec->AnalysiscQMF, - hSbrDec->anaQmfStates, - hSbrDec->AnalysiscQMF.no_col, - hSbrDec->AnalysiscQMF.lsb, - hSbrDec->AnalysiscQMF.usb, - hSbrDec->AnalysiscQMF.no_channels, - anaQmfFlags | QMF_FLAG_KEEP_STATES - ); - - if (qmfErr != 0) { - /* Restore old configuration of analysis QMF */ - FDKmemcpy(&hSbrDec->AnalysiscQMF, &prvAnaQmf, sizeof(QMF_FILTER_BANK)); - } - } + for (patch = (MAX_STRETCH_HBE - 1); patch < numPatches; patch++) { + patchBands = xOverQmf[patch + 1] - xOverQmf[patch]; + target = xOverQmf[patch]; + sourceBands = xOverQmf[MAX_STRETCH_HBE - 1] - xOverQmf[MAX_STRETCH_HBE - 2]; - if (resetSynQmf) { - QMF_FILTER_BANK prvSynQmf; - int qmfErr; - - /* Store current configuration */ - FDKmemcpy(&prvSynQmf, &hSbrDec->SynthesisQMF, sizeof(QMF_FILTER_BANK)); - - /* Reset synthesis QMF */ - qmfErr = qmfInitSynthesisFilterBank ( - &hSbrDec->SynthesisQMF, - hSbrDec->pSynQmfStates, - hSbrDec->SynthesisQMF.no_col, - hSbrDec->SynthesisQMF.lsb, - hSbrDec->SynthesisQMF.usb, - hSbrDec->SynthesisQMF.no_channels, - synQmfFlags | QMF_FLAG_KEEP_STATES - ); - - if (qmfErr != 0) { - /* Restore old configuration of synthesis QMF */ - FDKmemcpy(&hSbrDec->SynthesisQMF, &prvSynQmf, sizeof(QMF_FILTER_BANK)); + while (patchBands > 0) { + int numBands = sourceBands; + int startBand = xOverQmf[MAX_STRETCH_HBE - 1] - 1; + if (target + numBands >= xOverQmf[patch + 1]) { + numBands = xOverQmf[patch + 1] - target; + } + if ((((target + numBands - 1) % 2) + + ((xOverQmf[MAX_STRETCH_HBE - 1] - 1) % 2)) % + 2) { + if (numBands == sourceBands) { + numBands--; + } else { + startBand--; + } + } + if (keepStatesSynced == KEEP_STATES_SYNCED_OUTDIFF) { + for (col = slotOffset; col < overlap + LPC_ORDER; col++) { + i = 0; + for (band = numBands; band > 0; band--) { + if ((target + band - 1 < 64) && + (target + band - 1 < xOverQmf[patch + 1])) { + ppqmfReal[col][target + band - 1] = ppqmfReal[col][startBand - i]; + ppqmfImag[col][target + band - 1] = ppqmfImag[col][startBand - i]; + i++; + } + } + } + } else { + for (col = slotOffset; col < noCols; col++) { + i = 0; + for (band = numBands; band > 0; band--) { + if ((target + band - 1 < 64) && + (target + band - 1 < xOverQmf[patch + 1])) { + ppqmfReal[col][target + band - 1] = ppqmfReal[col][startBand - i]; + ppqmfImag[col][target + band - 1] = ppqmfImag[col][startBand - i]; + i++; + } + } + } + } + target += numBands; + patchBands -= numBands; } } } - /*! \brief SBR decoder core function for one channel @@ -283,26 +215,26 @@ static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< hand the LPP-Transposer, processing is mainly based on four buffers: #timeIn, #timeOut, #WorkBuffer2 and #OverlapBuffer. The #WorkBuffer2 is reused for all channels and might be used by the core decoder, a - static overlap buffer is required for each channel. Du to in-place + static overlap buffer is required for each channel. Due to in-place processing, #timeIn and #timeOut point to identical locations. - The spectral data is organized in so-called slots, each slot - containing 64 bands of complex data. The number of slots per frame is - dependend on the frame size. For mp3PRO, there are 18 slots per frame + The spectral data is organized in so-called slots. Each slot + contains 64 bands of complex data. The number of slots per frame + depends on the frame size. For mp3PRO, there are 18 slots per frame and 6 slots per #OverlapBuffer. It is not necessary to have the slots in located consecutive address ranges. To optimize memory usage and to minimize the number of memory - accesses, the memory management is organized as follows (Slot numbers + accesses, the memory management is organized as follows (slot numbers based on mp3PRO): - 1.) Input time domain signal is located in #timeIn, the last slots + 1.) Input time domain signal is located in #timeIn. The last slots (0..5) of the spectral data of the previous frame are located in the #OverlapBuffer. In addition, #frameData of the current frame resides in the upper part of #timeIn. - 2.) During the cplxAnalysisQmfFiltering(), 32 samples from #timeIn are transformed - into a slot of up to 32 complex spectral low band values at a + 2.) During the cplxAnalysisQmfFiltering(), 32 samples from #timeIn are + transformed into a slot of up to 32 complex spectral low band values at a time. The first spectral slot -- nr. 6 -- is written at slot number zero of #WorkBuffer2. #WorkBuffer2 will be completely filled with spectral data. @@ -325,73 +257,77 @@ static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< hand */ -void -sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ - INT_PCM *timeIn, /*!< pointer to input time signal */ - INT_PCM *timeOut, /*!< pointer to output time signal */ - HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ - INT_PCM *timeOutRight, /*!< pointer to output time signal */ - const int strideIn, /*!< Time data traversal strideIn */ - const int strideOut, /*!< Time data traversal strideOut */ - HANDLE_SBR_HEADER_DATA hHeaderData,/*!< Static control data */ - HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ - HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */ - const int applyProcessing, /*!< Flag for SBR operation */ - HANDLE_PS_DEC h_ps_d, - const UINT flags, - const int codecFrameSize - ) -{ +void sbr_dec( + HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ + INT_PCM *timeIn, /*!< pointer to input time signal */ + INT_PCM *timeOut, /*!< pointer to output time signal */ + HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ + INT_PCM *timeOutRight, /*!< pointer to output time signal */ + const int strideOut, /*!< Time data traversal strideOut */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ + HANDLE_SBR_PREV_FRAME_DATA + hPrevFrameData, /*!< Some control data of last frame */ + const int applyProcessing, /*!< Flag for SBR operation */ + HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize) { int i, slot, reserve; int saveLbScale; - int ov_len; int lastSlotOffs; FIXP_DBL maxVal; - /* 1+1/3 frames of spectral data: */ - FIXP_DBL **QmfBufferReal = hSbrDec->QmfBufferReal; - FIXP_DBL **QmfBufferImag = hSbrDec->QmfBufferImag; + /* temporary pointer / variable for QMF; + required as we want to use temporary buffer + creating one frame delay for HBE in LP mode */ + INT_PCM *pTimeInQmf = timeIn; - /* Number of QMF timeslots in the overlap buffer: */ - ov_len = hSbrDec->LppTrans.pSettings->overlap; + /* Number of QMF timeslots in the overlap buffer: */ + int ov_len = hSbrDec->LppTrans.pSettings->overlap; - /* Number of QMF slots per frame */ + /* Number of QMF slots per frame */ int noCols = hHeaderData->numberTimeSlots * hHeaderData->timeStep; - /* assign qmf time slots */ - if ( ((flags & SBRDEC_LOW_POWER ) ? 1 : 0) != ((hSbrDec->SynthesisQMF.flags & QMF_FLAG_LP) ? 1 : 0) ) { - assignTimeSlots( hSbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, flags & SBRDEC_LOW_POWER); + /* create pointer array for data to use for HBE and legacy sbr */ + FIXP_DBL *pLowBandReal[(3 * 4) + 2 * ((1024) / (32) * (4) / 2)]; + FIXP_DBL *pLowBandImag[(3 * 4) + 2 * ((1024) / (32) * (4) / 2)]; + + /* set pReal to where QMF analysis writes in case of legacy SBR */ + FIXP_DBL **pReal = pLowBandReal + ov_len; + FIXP_DBL **pImag = pLowBandImag + ov_len; + + /* map QMF buffer to pointer array (Overlap + Frame)*/ + for (i = 0; i < noCols + ov_len; i++) { + pLowBandReal[i] = hSbrDec->qmfDomainInCh->hQmfSlotsReal[i]; + pLowBandImag[i] = hSbrDec->qmfDomainInCh->hQmfSlotsImag[i]; } - if (flags & SBRDEC_ELD_GRID) { - /* Choose the right low delay filter bank */ - changeQmfType( hSbrDec, (flags & SBRDEC_LD_MPS_QMF) ? 1 : 0 ); + if ((flags & SBRDEC_USAC_HARMONICSBR)) { + /* in case of harmonic SBR and no HBE_LP map additional buffer for + one more frame to pointer arry */ + for (i = 0; i < noCols; i++) { + pLowBandReal[i + noCols + ov_len] = hSbrDec->hQmfHBESlotsReal[i]; + pLowBandImag[i + noCols + ov_len] = hSbrDec->hQmfHBESlotsImag[i]; + } - /* If the LD-MPS QMF is not available delay the signal by (96-48*ldSbrSamplingRate) - * samples according to ISO/IEC 14496-3:2009/FDAM 2:2010(E) chapter 4.5.2.13. */ - if ( (flags & SBRDEC_LD_MPS_QMF) - && (hSbrDec->AnalysiscQMF.flags & QMF_FLAG_CLDFB) ) - { - INT_PCM *pDlyBuf = hSbrDec->coreDelayBuf; /* DLYBUF */ - int smpl, delay = 96 >> (!(flags & SBRDEC_DOWNSAMPLE) ? 1 : 0); - /* Create TMPBUF */ - C_AALLOC_SCRATCH_START(pcmTemp, INT_PCM, (96)); - /* Copy delay samples from INBUF to TMPBUF */ - for (smpl = 0; smpl < delay; smpl += 1) { - pcmTemp[smpl] = timeIn[(codecFrameSize-delay+smpl)*strideIn]; - } - /* Move input signal remainder to the very end of INBUF */ - for (smpl = (codecFrameSize-delay-1)*strideIn; smpl >= 0; smpl -= strideIn) { - timeIn[smpl+delay] = timeIn[smpl]; - } - /* Copy delayed samples from last frame from DLYBUF to the very beginning of INBUF */ - for (smpl = 0; smpl < delay; smpl += 1) { - timeIn[smpl*strideIn] = pDlyBuf[smpl]; + /* shift scale values according to buffer */ + hSbrDec->scale_ov = hSbrDec->scale_lb; + hSbrDec->scale_lb = hSbrDec->scale_hbe; + + /* set pReal to where QMF analysis writes in case of HBE */ + pReal += noCols; + pImag += noCols; + if (flags & SBRDEC_SKIP_QMF_ANA) { + /* stereoCfgIndex3 with HBE */ + FDK_QmfDomain_QmfData2HBE(hSbrDec->qmfDomainInCh, + hSbrDec->hQmfHBESlotsReal, + hSbrDec->hQmfHBESlotsImag); + } else { + /* We have to move old hbe frame data to lb area of buffer */ + for (i = 0; i < noCols; i++) { + FDKmemcpy(pLowBandReal[ov_len + i], hSbrDec->hQmfHBESlotsReal[i], + hHeaderData->numberOfAnalysisBands * sizeof(FIXP_DBL)); + FDKmemcpy(pLowBandImag[ov_len + i], hSbrDec->hQmfHBESlotsImag[i], + hHeaderData->numberOfAnalysisBands * sizeof(FIXP_DBL)); } - /* Copy TMPBUF to DLYBUF */ - FDKmemcpy(pDlyBuf, pcmTemp, delay*sizeof(INT_PCM)); - /* Destory TMPBUF */ - C_AALLOC_SCRATCH_END(pcmTemp, INT_PCM, (96)); } } @@ -399,234 +335,437 @@ sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ low band codec signal subband filtering */ - { - C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2*(64)); - - qmfAnalysisFiltering( &hSbrDec->AnalysiscQMF, - QmfBufferReal + ov_len, - QmfBufferImag + ov_len, - &hSbrDec->sbrScaleFactor, - timeIn, - strideIn, - qmfTemp - ); - - C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2*(64)); + if (flags & SBRDEC_SKIP_QMF_ANA) { + if (!(flags & SBRDEC_USAC_HARMONICSBR)) /* stereoCfgIndex3 w/o HBE */ + FDK_QmfDomain_WorkBuffer2ProcChannel(hSbrDec->qmfDomainInCh); + } else { + C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2 * (64)); + qmfAnalysisFiltering(&hSbrDec->qmfDomainInCh->fb, pReal, pImag, + &hSbrDec->qmfDomainInCh->scaling, pTimeInQmf, 0, 1, + qmfTemp); + + C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2 * (64)); } /* Clear upper half of spectrum */ - { + if (!((flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode == 0))) { int nAnalysisBands = hHeaderData->numberOfAnalysisBands; - if (! (flags & SBRDEC_LOW_POWER)) { - for (slot = ov_len; slot < noCols+ov_len; slot++) { - FDKmemclear(&QmfBufferReal[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL)); - FDKmemclear(&QmfBufferImag[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL)); + if (!(flags & SBRDEC_LOW_POWER)) { + for (slot = ov_len; slot < noCols + ov_len; slot++) { + FDKmemclear(&pLowBandReal[slot][nAnalysisBands], + ((64) - nAnalysisBands) * sizeof(FIXP_DBL)); + FDKmemclear(&pLowBandImag[slot][nAnalysisBands], + ((64) - nAnalysisBands) * sizeof(FIXP_DBL)); + } + } else { + for (slot = ov_len; slot < noCols + ov_len; slot++) { + FDKmemclear(&pLowBandReal[slot][nAnalysisBands], + ((64) - nAnalysisBands) * sizeof(FIXP_DBL)); } - } else - for (slot = ov_len; slot < noCols+ov_len; slot++) { - FDKmemclear(&QmfBufferReal[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL)); } } - - /* Shift spectral data left to gain accuracy in transposer and adjustor */ - maxVal = maxSubbandSample( QmfBufferReal, - (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, - 0, - hSbrDec->AnalysiscQMF.lsb, - ov_len, - noCols+ov_len ); + /* Range was increased from lsb to no_channels because in some cases (e.g. + USAC conf eSbr_4_Pvc.mp4 and some HBE cases) it could be observed that the + signal between lsb and no_channels is used for the patching process. + */ + maxVal = maxSubbandSample(pReal, (flags & SBRDEC_LOW_POWER) ? NULL : pImag, 0, + hSbrDec->qmfDomainInCh->fb.no_channels, 0, noCols); - reserve = fixMax(0,CntLeadingZeros(maxVal)-1) ; - reserve = fixMin(reserve,DFRACT_BITS-1-hSbrDec->sbrScaleFactor.lb_scale); + reserve = fixMax(0, CntLeadingZeros(maxVal) - 1); + reserve = fixMin(reserve, + DFRACT_BITS - 1 - hSbrDec->qmfDomainInCh->scaling.lb_scale); /* If all data is zero, lb_scale could become too large */ - rescaleSubbandSamples( QmfBufferReal, - (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, - 0, - hSbrDec->AnalysiscQMF.lsb, - ov_len, - noCols+ov_len, - reserve); + rescaleSubbandSamples(pReal, (flags & SBRDEC_LOW_POWER) ? NULL : pImag, 0, + hSbrDec->qmfDomainInCh->fb.no_channels, 0, noCols, + reserve); - hSbrDec->sbrScaleFactor.lb_scale += reserve; + hSbrDec->qmfDomainInCh->scaling.lb_scale += reserve; + if ((flags & SBRDEC_USAC_HARMONICSBR)) { + /* actually this is our hbe_scale */ + hSbrDec->scale_hbe = hSbrDec->qmfDomainInCh->scaling.lb_scale; + /* the real lb_scale is stored in scale_lb from sbr */ + hSbrDec->qmfDomainInCh->scaling.lb_scale = hSbrDec->scale_lb; + } /* save low band scale, wavecoding or parametric stereo may modify it */ - saveLbScale = hSbrDec->sbrScaleFactor.lb_scale; + saveLbScale = hSbrDec->qmfDomainInCh->scaling.lb_scale; - - if (applyProcessing) - { - UCHAR * borders = hFrameData->frameInfo.borders; - lastSlotOffs = borders[hFrameData->frameInfo.nEnvelopes] - hHeaderData->numberTimeSlots; + if (applyProcessing) { + UCHAR *borders = hFrameData->frameInfo.borders; + lastSlotOffs = borders[hFrameData->frameInfo.nEnvelopes] - + hHeaderData->numberTimeSlots; FIXP_DBL degreeAlias[(64)]; + PVC_DYNAMIC_DATA pvcDynamicData; + pvcInitFrame( + &hSbrDec->PvcStaticData, &pvcDynamicData, + (hHeaderData->frameErrorFlag ? 0 : hHeaderData->bs_info.pvc_mode), + hFrameData->ns, hHeaderData->timeStep, + hHeaderData->freqBandData.lowSubband, + hFrameData->frameInfo.pvcBorders[0], hFrameData->pvcID); + + if (!hHeaderData->frameErrorFlag && (hHeaderData->bs_info.pvc_mode > 0)) { + pvcDecodeFrame(&hSbrDec->PvcStaticData, &pvcDynamicData, pLowBandReal, + pLowBandImag, ov_len, + SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale), + SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.lb_scale)); + } + pvcEndFrame(&hSbrDec->PvcStaticData, &pvcDynamicData); /* The transposer will override most values in degreeAlias[]. - The array needs to be cleared at least from lowSubband to highSubband before. */ + The array needs to be cleared at least from lowSubband to highSubband + before. */ if (flags & SBRDEC_LOW_POWER) - FDKmemclear(°reeAlias[hHeaderData->freqBandData.lowSubband], (hHeaderData->freqBandData.highSubband-hHeaderData->freqBandData.lowSubband)*sizeof(FIXP_DBL)); + FDKmemclear(°reeAlias[hHeaderData->freqBandData.lowSubband], + (hHeaderData->freqBandData.highSubband - + hHeaderData->freqBandData.lowSubband) * + sizeof(FIXP_DBL)); /* - Inverse filtering of lowband and transposition into the SBR-frequency range + Inverse filtering of lowband and transposition into the SBR-frequency + range */ - lppTransposer ( &hSbrDec->LppTrans, - &hSbrDec->sbrScaleFactor, - QmfBufferReal, - degreeAlias, // only used if useLP = 1 - QmfBufferImag, - flags & SBRDEC_LOW_POWER, - hHeaderData->timeStep, - borders[0], - lastSlotOffs, - hHeaderData->freqBandData.nInvfBands, - hFrameData->sbr_invf_mode, - hPrevFrameData->sbr_invf_mode ); + { + KEEP_STATES_SYNCED_MODE keepStatesSyncedMode = + ((flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode != 0)) + ? KEEP_STATES_SYNCED_NORMAL + : KEEP_STATES_SYNCED_OFF; + + if (flags & SBRDEC_USAC_HARMONICSBR) { + if (flags & SBRDEC_QUAD_RATE) { + pReal -= 32; + pImag -= 32; + } + + if ((hSbrDec->savedStates == 0) && (hFrameData->sbrPatchingMode == 1)) { + /* copy saved states from previous frame to legacy SBR lpc filterstate + * buffer */ + for (i = 0; i < LPC_ORDER + ov_len; i++) { + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + hSbrDec->codecQMFBufferReal[noCols - LPC_ORDER - ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], + hSbrDec->codecQMFBufferImag[noCols - LPC_ORDER - ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + } + } + + /* saving unmodified QMF states in case we are switching from legacy SBR + * to HBE */ + for (i = 0; i < hSbrDec->hHBE->noCols; i++) { + FDKmemcpy(hSbrDec->codecQMFBufferReal[i], pLowBandReal[ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->codecQMFBufferImag[i], pLowBandImag[ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + } + + QmfTransposerApply( + hSbrDec->hHBE, pReal, pImag, noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + hFrameData->sbrPitchInBins, hSbrDec->scale_lb, hSbrDec->scale_hbe, + &hSbrDec->qmfDomainInCh->scaling.hb_scale, hHeaderData->timeStep, + borders[0], ov_len, keepStatesSyncedMode); + + if (flags & SBRDEC_QUAD_RATE) { + int *xOverQmf = GetxOverBandQmfTransposer(hSbrDec->hHBE); + + copyHarmonicSpectrum(xOverQmf, pLowBandReal, pLowBandImag, noCols, + ov_len, keepStatesSyncedMode); + } + } + } + if ((flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode == 0)) { + hSbrDec->prev_frame_lSbr = 0; + hSbrDec->prev_frame_hbeSbr = 1; + lppTransposerHBE( + &hSbrDec->LppTrans, hSbrDec->hHBE, &hSbrDec->qmfDomainInCh->scaling, + pLowBandReal, pLowBandImag, hHeaderData->timeStep, borders[0], + lastSlotOffs, hHeaderData->freqBandData.nInvfBands, + hFrameData->sbr_invf_mode, hPrevFrameData->sbr_invf_mode); + } else { + if (flags & SBRDEC_USAC_HARMONICSBR) { + for (i = 0; i < LPC_ORDER + hSbrDec->LppTrans.pSettings->overlap; i++) { + /* + Store the unmodified qmf Slots values for upper part of spectrum + (required for LPC filtering) required if next frame is a HBE frame + */ + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealHBE[i], + hSbrDec->qmfDomainInCh + ->hQmfSlotsReal[hSbrDec->hHBE->noCols - LPC_ORDER + i], + (64) * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImagHBE[i], + hSbrDec->qmfDomainInCh + ->hQmfSlotsImag[hSbrDec->hHBE->noCols - LPC_ORDER + i], + (64) * sizeof(FIXP_DBL)); + } + } + { + hSbrDec->prev_frame_lSbr = 1; + hSbrDec->prev_frame_hbeSbr = 0; + } + lppTransposer( + &hSbrDec->LppTrans, &hSbrDec->qmfDomainInCh->scaling, pLowBandReal, + degreeAlias, // only used if useLP = 1 + pLowBandImag, flags & SBRDEC_LOW_POWER, + hHeaderData->bs_info.sbr_preprocessing, + hHeaderData->freqBandData.v_k_master[0], hHeaderData->timeStep, + borders[0], lastSlotOffs, hHeaderData->freqBandData.nInvfBands, + hFrameData->sbr_invf_mode, hPrevFrameData->sbr_invf_mode); + } /* Adjust envelope of current frame. */ - calculateSbrEnvelope (&hSbrDec->sbrScaleFactor, - &hSbrDec->SbrCalculateEnvelope, - hHeaderData, - hFrameData, - QmfBufferReal, - QmfBufferImag, - flags & SBRDEC_LOW_POWER, + if ((hFrameData->sbrPatchingMode != + hSbrDec->SbrCalculateEnvelope.sbrPatchingMode)) { + ResetLimiterBands(hHeaderData->freqBandData.limiterBandTable, + &hHeaderData->freqBandData.noLimiterBands, + hHeaderData->freqBandData.freqBandTable[0], + hHeaderData->freqBandData.nSfb[0], + hSbrDec->LppTrans.pSettings->patchParam, + hSbrDec->LppTrans.pSettings->noOfPatches, + hHeaderData->bs_data.limiterBands, + hFrameData->sbrPatchingMode, + (flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode == 0) + ? GetxOverBandQmfTransposer(hSbrDec->hHBE) + : NULL, + Get41SbrQmfTransposer(hSbrDec->hHBE)); + + hSbrDec->SbrCalculateEnvelope.sbrPatchingMode = + hFrameData->sbrPatchingMode; + } + + calculateSbrEnvelope( + &hSbrDec->qmfDomainInCh->scaling, &hSbrDec->SbrCalculateEnvelope, + hHeaderData, hFrameData, &pvcDynamicData, pLowBandReal, pLowBandImag, + flags & SBRDEC_LOW_POWER, - degreeAlias, - flags, - (hHeaderData->frameErrorFlag || hPrevFrameData->frameErrorFlag)); + degreeAlias, flags, + (hHeaderData->frameErrorFlag || hPrevFrameData->frameErrorFlag)); +#if (SBRDEC_MAX_HB_FADE_FRAMES > 0) + /* Avoid hard onsets of high band */ + if (hHeaderData->frameErrorFlag) { + if (hSbrDec->highBandFadeCnt < SBRDEC_MAX_HB_FADE_FRAMES) { + hSbrDec->highBandFadeCnt += 1; + } + } else { + if (hSbrDec->highBandFadeCnt > + 0) { /* Manipulate high band scale factor to get a smooth fade-in */ + hSbrDec->qmfDomainInCh->scaling.hb_scale += hSbrDec->highBandFadeCnt; + hSbrDec->qmfDomainInCh->scaling.hb_scale = + fMin(hSbrDec->qmfDomainInCh->scaling.hb_scale, DFRACT_BITS - 1); + hSbrDec->highBandFadeCnt -= 1; + } + } +#endif /* Update hPrevFrameData (to be used in the next frame) */ - for (i=0; i<hHeaderData->freqBandData.nInvfBands; i++) { + for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) { hPrevFrameData->sbr_invf_mode[i] = hFrameData->sbr_invf_mode[i]; } hPrevFrameData->coupling = hFrameData->coupling; hPrevFrameData->stopPos = borders[hFrameData->frameInfo.nEnvelopes]; hPrevFrameData->ampRes = hFrameData->ampResolutionCurrentFrame; - } - else { - /* Reset hb_scale if no highband is present, because hb_scale is considered in the QMF-synthesis */ - hSbrDec->sbrScaleFactor.hb_scale = saveLbScale; + hPrevFrameData->prevSbrPitchInBins = hFrameData->sbrPitchInBins; + /* could be done in extractFrameInfo_pvc() but hPrevFrameData is not + * available there */ + FDKmemcpy(&hPrevFrameData->prevFrameInfo, &hFrameData->frameInfo, + sizeof(FRAME_INFO)); + } else { + /* rescale from lsb to nAnalysisBands in order to compensate scaling with + * hb_scale in this area, done by synthesisFiltering*/ + int rescale; + int lsb; + int length; + + /* Reset hb_scale if no highband is present, because hb_scale is considered + * in the QMF-synthesis */ + hSbrDec->qmfDomainInCh->scaling.hb_scale = saveLbScale; + + rescale = hSbrDec->qmfDomainInCh->scaling.hb_scale - + hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + lsb = hSbrDec->qmfDomainOutCh->fb.lsb; + length = (hSbrDec->qmfDomainInCh->fb.no_channels - lsb); + + if ((rescale < 0) && (length > 0)) { + if (!(flags & SBRDEC_LOW_POWER)) { + for (i = 0; i < ov_len; i++) { + scaleValues(&pLowBandReal[i][lsb], length, rescale); + scaleValues(&pLowBandImag[i][lsb], length, rescale); + } + } else { + for (i = 0; i < ov_len; i++) { + scaleValues(&pLowBandReal[i][lsb], length, rescale); + } + } + } } + if (!(flags & SBRDEC_USAC_HARMONICSBR)) { + int length = hSbrDec->qmfDomainInCh->fb.lsb; + if (flags & SBRDEC_SYNTAX_USAC) { + length = hSbrDec->qmfDomainInCh->fb.no_channels; + } - for (i=0; i<LPC_ORDER; i++){ - /* - Store the unmodified qmf Slots values (required for LPC filtering) - */ - if (! (flags & SBRDEC_LOW_POWER)) { - FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesReal[i], QmfBufferReal[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL)); - FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImag[i], QmfBufferImag[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL)); - } else - FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesReal[i], QmfBufferReal[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL)); + /* in case of legacy sbr saving of filter states here */ + for (i = 0; i < LPC_ORDER + ov_len; i++) { + /* + Store the unmodified qmf Slots values (required for LPC filtering) + */ + if (!(flags & SBRDEC_LOW_POWER)) { + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + pLowBandReal[noCols - LPC_ORDER + i], + length * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], + pLowBandImag[noCols - LPC_ORDER + i], + length * sizeof(FIXP_DBL)); + } else + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + pLowBandReal[noCols - LPC_ORDER + i], + length * sizeof(FIXP_DBL)); + } } /* Synthesis subband filtering. */ - if ( ! (flags & SBRDEC_PS_DECODED) ) { - - { + if (!(flags & SBRDEC_PS_DECODED)) { + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { int outScalefactor = 0; if (h_ps_d != NULL) { - h_ps_d->procFrameBased = 1; /* we here do frame based processing */ + h_ps_d->procFrameBased = 1; /* we here do frame based processing */ } + sbrDecoder_drcApply(&hSbrDec->sbrDrcChannel, pLowBandReal, + (flags & SBRDEC_LOW_POWER) ? NULL : pLowBandImag, + hSbrDec->qmfDomainOutCh->fb.no_col, &outScalefactor); - sbrDecoder_drcApply(&hSbrDec->sbrDrcChannel, - QmfBufferReal, - (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, - hSbrDec->SynthesisQMF.no_col, - &outScalefactor - ); - - - - qmfChangeOutScalefactor(&hSbrDec->SynthesisQMF, outScalefactor ); + qmfChangeOutScalefactor(&hSbrDec->qmfDomainOutCh->fb, outScalefactor); { - C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2*(64)); - - qmfSynthesisFiltering( &hSbrDec->SynthesisQMF, - QmfBufferReal, - (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, - &hSbrDec->sbrScaleFactor, - hSbrDec->LppTrans.pSettings->overlap, - timeOut, - strideOut, - qmfTemp); - - C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2*(64)); + HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + int save_usb = hSbrDec->qmfDomainOutCh->fb.usb; + +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_START(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif + if (hSbrDec->qmfDomainOutCh->fb.usb < hFreq->ov_highSubband) { + /* we need to patch usb for this frame as overlap may contain higher + frequency range if headerchange occured; fb. usb is always limited + to maximum fb.no_channels; In case of wrongly decoded headers it + might be that ov_highSubband is higher than the number of synthesis + channels (fb.no_channels), which is forbidden, therefore we need to + limit ov_highSubband with fMin function to avoid not allowed usb in + synthesis filterbank. */ + hSbrDec->qmfDomainOutCh->fb.usb = + fMin((UINT)hFreq->ov_highSubband, + (UINT)hSbrDec->qmfDomainOutCh->fb.no_channels); + } + { + qmfSynthesisFiltering( + &hSbrDec->qmfDomainOutCh->fb, pLowBandReal, + (flags & SBRDEC_LOW_POWER) ? NULL : pLowBandImag, + &hSbrDec->qmfDomainInCh->scaling, + hSbrDec->LppTrans.pSettings->overlap, timeOut, strideOut, + qmfTemp); + } + /* restore saved value */ + hSbrDec->qmfDomainOutCh->fb.usb = save_usb; + hFreq->ov_highSubband = save_usb; +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_END(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif } - } } else { /* (flags & SBRDEC_PS_DECODED) */ - INT i, sdiff, outScalefactor, scaleFactorLowBand, scaleFactorHighBand; - SCHAR scaleFactorLowBand_ov, scaleFactorLowBand_no_ov; + INT sdiff; + INT scaleFactorHighBand, scaleFactorLowBand_ov, scaleFactorLowBand_no_ov; - HANDLE_QMF_FILTER_BANK synQmf = &hSbrDec->SynthesisQMF; - HANDLE_QMF_FILTER_BANK synQmfRight = &hSbrDecRight->SynthesisQMF; + HANDLE_QMF_FILTER_BANK synQmf = &hSbrDec->qmfDomainOutCh->fb; + HANDLE_QMF_FILTER_BANK synQmfRight = &hSbrDecRight->qmfDomainOutCh->fb; /* adapt scaling */ - sdiff = hSbrDec->sbrScaleFactor.lb_scale - reserve; /* Scaling difference */ - scaleFactorHighBand = sdiff - hSbrDec->sbrScaleFactor.hb_scale; /* Scale of current high band */ - scaleFactorLowBand_ov = sdiff - hSbrDec->sbrScaleFactor.ov_lb_scale; /* Scale of low band overlapping QMF data */ - scaleFactorLowBand_no_ov = sdiff - hSbrDec->sbrScaleFactor.lb_scale; /* Scale of low band current QMF data */ - outScalefactor = 0; /* Initial output scale */ - - if (h_ps_d->procFrameBased == 1) /* If we have switched from frame to slot based processing copy filter states */ - { /* procFrameBased will be unset later */ + sdiff = hSbrDec->qmfDomainInCh->scaling.lb_scale - + reserve; /* Scaling difference */ + scaleFactorHighBand = sdiff - hSbrDec->qmfDomainInCh->scaling.hb_scale; + scaleFactorLowBand_ov = sdiff - hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + scaleFactorLowBand_no_ov = sdiff - hSbrDec->qmfDomainInCh->scaling.lb_scale; + + /* Scale of low band overlapping QMF data */ + scaleFactorLowBand_ov = + fMin(DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorLowBand_ov)); + /* Scale of low band current QMF data */ + scaleFactorLowBand_no_ov = fMin( + DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorLowBand_no_ov)); + /* Scale of current high band */ + scaleFactorHighBand = + fMin(DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorHighBand)); + + if (h_ps_d->procFrameBased == 1) /* If we have switched from frame to slot + based processing copy filter states */ + { /* procFrameBased will be unset later */ /* copy filter states from left to right */ - FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates, ((640)-(64))*sizeof(FIXP_QSS)); + /* was ((640)-(64))*sizeof(FIXP_QSS) + flexible amount of synthesis bands needed for QMF based resampling + */ + FDK_ASSERT(hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis <= + QMF_MAX_SYNTHESIS_BANDS); + FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates, + 9 * hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis * + sizeof(FIXP_QSS)); } - /* scale ALL qmf vales ( real and imag ) of mono / left channel to the - same scale factor ( ov_lb_sf, lb_sf and hq_sf ) */ - scalFilterBankValues( h_ps_d, /* parametric stereo decoder handle */ - QmfBufferReal, /* qmf filterbank values */ - QmfBufferImag, /* qmf filterbank values */ - synQmf->lsb, /* sbr start subband */ - hSbrDec->sbrScaleFactor.ov_lb_scale, - hSbrDec->sbrScaleFactor.lb_scale, - &scaleFactorLowBand_ov, /* adapt scaling values */ - &scaleFactorLowBand_no_ov, /* adapt scaling values */ - hSbrDec->sbrScaleFactor.hb_scale, /* current frame ( highband ) */ - &scaleFactorHighBand, - synQmf->no_col); + /* Feed delaylines when parametric stereo is switched on. */ + PreparePsProcessing(h_ps_d, pLowBandReal, pLowBandImag, + scaleFactorLowBand_ov); /* use the same synthese qmf values for left and right channel */ synQmfRight->no_col = synQmf->no_col; - synQmfRight->lsb = synQmf->lsb; - synQmfRight->usb = synQmf->usb; + synQmfRight->lsb = synQmf->lsb; + synQmfRight->usb = synQmf->usb; - int env=0; - - outScalefactor += (SCAL_HEADROOM+1); /* psDiffScale! */ + int env = 0; { - C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, 2*(64)); +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, + 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_START(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif int maxShift = 0; @@ -642,99 +781,80 @@ sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ } } - /* copy DRC data to right channel (with PS both channels use the same DRC gains) */ - FDKmemcpy(&hSbrDecRight->sbrDrcChannel, &hSbrDec->sbrDrcChannel, sizeof(SBRDEC_DRC_CHANNEL)); + /* copy DRC data to right channel (with PS both channels use the same DRC + * gains) */ + FDKmemcpy(&hSbrDecRight->sbrDrcChannel, &hSbrDec->sbrDrcChannel, + sizeof(SBRDEC_DRC_CHANNEL)); - for (i = 0; i < synQmf->no_col; i++) { /* ----- no_col loop ----- */ + for (i = 0; i < synQmf->no_col; i++) { /* ----- no_col loop ----- */ INT outScalefactorR, outScalefactorL; - outScalefactorR = outScalefactorL = outScalefactor; /* qmf timeslot of right channel */ - FIXP_DBL* rQmfReal = pWorkBuffer; - FIXP_DBL* rQmfImag = pWorkBuffer + 64; - + FIXP_DBL *rQmfReal = pWorkBuffer; + FIXP_DBL *rQmfImag = pWorkBuffer + synQmf->no_channels; { - if ( i == h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env] ) { - initSlotBasedRotation( h_ps_d, env, hHeaderData->freqBandData.highSubband ); + if (i == + h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env]) { + initSlotBasedRotation(h_ps_d, env, + hHeaderData->freqBandData.highSubband); env++; } - ApplyPsSlot( h_ps_d, /* parametric stereo decoder handle */ - (QmfBufferReal + i), /* one timeslot of left/mono channel */ - (QmfBufferImag + i), /* one timeslot of left/mono channel */ - rQmfReal, /* one timeslot or right channel */ - rQmfImag); /* one timeslot or right channel */ + ApplyPsSlot( + h_ps_d, /* parametric stereo decoder handle */ + (pLowBandReal + i), /* one timeslot of left/mono channel */ + (pLowBandImag + i), /* one timeslot of left/mono channel */ + rQmfReal, /* one timeslot or right channel */ + rQmfImag, /* one timeslot or right channel */ + scaleFactorLowBand_no_ov, + (i < hSbrDec->LppTrans.pSettings->overlap) + ? scaleFactorLowBand_ov + : scaleFactorLowBand_no_ov, + scaleFactorHighBand, synQmf->lsb, synQmf->usb); + + outScalefactorL = outScalefactorR = 1; /* psDiffScale! (MPEG-PS) */ } - - scaleFactorLowBand = (i<(6)) ? scaleFactorLowBand_ov : scaleFactorLowBand_no_ov; - - - sbrDecoder_drcApplySlot ( /* right channel */ - &hSbrDecRight->sbrDrcChannel, - rQmfReal, - rQmfImag, - i, - synQmfRight->no_col, - maxShift - ); + sbrDecoder_drcApplySlot(/* right channel */ + &hSbrDecRight->sbrDrcChannel, rQmfReal, + rQmfImag, i, synQmfRight->no_col, maxShift); outScalefactorR += maxShift; - sbrDecoder_drcApplySlot ( /* left channel */ - &hSbrDec->sbrDrcChannel, - *(QmfBufferReal + i), - *(QmfBufferImag + i), - i, - synQmf->no_col, - maxShift - ); + sbrDecoder_drcApplySlot(/* left channel */ + &hSbrDec->sbrDrcChannel, *(pLowBandReal + i), + *(pLowBandImag + i), i, synQmf->no_col, + maxShift); outScalefactorL += maxShift; - - /* scale filter states for left and right channel */ - qmfChangeOutScalefactor( synQmf, outScalefactorL ); - qmfChangeOutScalefactor( synQmfRight, outScalefactorR ); - - { - - qmfSynthesisFilteringSlot( synQmfRight, - rQmfReal, /* QMF real buffer */ - rQmfImag, /* QMF imag buffer */ - scaleFactorLowBand, - scaleFactorHighBand, - timeOutRight+(i*synQmf->no_channels*strideOut), - strideOut, - pWorkBuffer); - - qmfSynthesisFilteringSlot( synQmf, - *(QmfBufferReal + i), /* QMF real buffer */ - *(QmfBufferImag + i), /* QMF imag buffer */ - scaleFactorLowBand, - scaleFactorHighBand, - timeOut+(i*synQmf->no_channels*strideOut), - strideOut, - pWorkBuffer); - + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { + qmfSynthesisFilteringSlot( + synQmfRight, rQmfReal, /* QMF real buffer */ + rQmfImag, /* QMF imag buffer */ + outScalefactorL, outScalefactorL, + timeOutRight + (i * synQmf->no_channels * strideOut), strideOut, + pWorkBuffer); + + qmfSynthesisFilteringSlot( + synQmf, *(pLowBandReal + i), /* QMF real buffer */ + *(pLowBandImag + i), /* QMF imag buffer */ + outScalefactorR, outScalefactorR, + timeOut + (i * synQmf->no_channels * strideOut), strideOut, + pWorkBuffer); } } /* no_col loop i */ - - /* scale back (6) timeslots look ahead for hybrid filterbank to original value */ - rescalFilterBankValues( h_ps_d, - QmfBufferReal, - QmfBufferImag, - synQmf->lsb, - synQmf->no_col ); - - C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 2*(64)); +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_END(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif } } - sbrDecoder_drcUpdateChannel( &hSbrDec->sbrDrcChannel ); - + sbrDecoder_drcUpdateChannel(&hSbrDec->sbrDrcChannel); /* Update overlap buffer @@ -742,150 +862,127 @@ sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ the stop frequency raises. */ - if (hSbrDec->LppTrans.pSettings->overlap > 0) - { - if (! (flags & SBRDEC_LOW_POWER)) { - for ( i=0; i<hSbrDec->LppTrans.pSettings->overlap; i++ ) { - FDKmemcpy(QmfBufferReal[i], QmfBufferReal[i+noCols], (64)*sizeof(FIXP_DBL)); - FDKmemcpy(QmfBufferImag[i], QmfBufferImag[i+noCols], (64)*sizeof(FIXP_DBL)); - } - } else - for ( i=0; i<hSbrDec->LppTrans.pSettings->overlap; i++ ) { - FDKmemcpy(QmfBufferReal[i], QmfBufferReal[i+noCols], (64)*sizeof(FIXP_DBL)); - } + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { + { + FDK_QmfDomain_SaveOverlap(hSbrDec->qmfDomainInCh, 0); + FDK_ASSERT(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale == saveLbScale); + } } - hSbrDec->sbrScaleFactor.ov_lb_scale = saveLbScale; + hSbrDec->savedStates = 0; /* Save current frame status */ hPrevFrameData->frameErrorFlag = hHeaderData->frameErrorFlag; + hSbrDec->applySbrProc_old = applyProcessing; -} // sbr_dec() - +} /* sbr_dec() */ /*! \brief Creates sbr decoder structure \return errorCode, 0 if successful */ SBR_ERROR -createSbrDec (SBR_CHANNEL * hSbrChannel, - HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - TRANSPOSER_SETTINGS *pSettings, - const int downsampleFac, /*!< Downsampling factor */ - const UINT qmfFlags, /*!< flags -> 1: HQ/LP selector, 2: CLDFB */ - const UINT flags, - const int overlap, - int chan) /*!< Channel for which to assign buffers etc. */ +createSbrDec(SBR_CHANNEL *hSbrChannel, + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + TRANSPOSER_SETTINGS *pSettings, + const int downsampleFac, /*!< Downsampling factor */ + const UINT qmfFlags, /*!< flags -> 1: HQ/LP selector, 2: CLDFB */ + const UINT flags, const int overlap, + int chan, /*!< Channel for which to assign buffers etc. */ + int codecFrameSize) { SBR_ERROR err = SBRDEC_OK; - int timeSlots = hHeaderData->numberTimeSlots; /* Number of SBR slots per frame */ - int noCols = timeSlots * hHeaderData->timeStep; /* Number of QMF slots per frame */ + int timeSlots = + hHeaderData->numberTimeSlots; /* Number of SBR slots per frame */ + int noCols = + timeSlots * hHeaderData->timeStep; /* Number of QMF slots per frame */ HANDLE_SBR_DEC hs = &(hSbrChannel->SbrDec); - /* Initialize scale factors */ - hs->sbrScaleFactor.ov_lb_scale = 0; - hs->sbrScaleFactor.ov_hb_scale = 0; - hs->sbrScaleFactor.hb_scale = 0; +#if (SBRDEC_MAX_HB_FADE_FRAMES > 0) + hs->highBandFadeCnt = SBRDEC_MAX_HB_FADE_FRAMES; + +#endif + hs->scale_hbe = 15; + hs->scale_lb = 15; + hs->scale_ov = 15; + hs->prev_frame_lSbr = 0; + hs->prev_frame_hbeSbr = 0; + + hs->codecFrameSize = codecFrameSize; /* create envelope calculator */ - err = createSbrEnvelopeCalc (&hs->SbrCalculateEnvelope, - hHeaderData, - chan, - flags); + err = createSbrEnvelopeCalc(&hs->SbrCalculateEnvelope, hHeaderData, chan, + flags); if (err != SBRDEC_OK) { return err; } - /* - create QMF filter banks - */ - { - int qmfErr; - /* Adapted QMF analysis post-twiddles for down-sampled HQ SBR */ - const UINT downSampledFlag = (flags & SBRDEC_DOWNSAMPLE) ? QMF_FLAG_DOWNSAMPLED : 0; - - qmfErr = qmfInitAnalysisFilterBank ( - &hs->AnalysiscQMF, - hs->anaQmfStates, - noCols, - hHeaderData->freqBandData.lowSubband, - hHeaderData->freqBandData.highSubband, - hHeaderData->numberOfAnalysisBands, - (qmfFlags & (~QMF_FLAG_KEEP_STATES)) | downSampledFlag - ); - if (qmfErr != 0) { - return SBRDEC_UNSUPPORTED_CONFIG; - } - } - if (hs->pSynQmfStates == NULL) { - hs->pSynQmfStates = GetRam_sbr_QmfStatesSynthesis(chan); - if (hs->pSynQmfStates == NULL) - return SBRDEC_MEM_ALLOC_FAILED; - } - - { - int qmfErr; - - qmfErr = qmfInitSynthesisFilterBank ( - &hs->SynthesisQMF, - hs->pSynQmfStates, - noCols, - hHeaderData->freqBandData.lowSubband, - hHeaderData->freqBandData.highSubband, - (64) / downsampleFac, - qmfFlags & (~QMF_FLAG_KEEP_STATES) - ); - - if (qmfErr != 0) { - return SBRDEC_UNSUPPORTED_CONFIG; - } - } - initSbrPrevFrameData (&hSbrChannel->prevFrameData, timeSlots); + initSbrPrevFrameData(&hSbrChannel->prevFrameData, timeSlots); /* create transposer */ - err = createLppTransposer (&hs->LppTrans, - pSettings, - hHeaderData->freqBandData.lowSubband, - hHeaderData->freqBandData.v_k_master, - hHeaderData->freqBandData.numMaster, - hs->SynthesisQMF.usb, - timeSlots, - hs->AnalysiscQMF.no_col, - hHeaderData->freqBandData.freqBandTableNoise, - hHeaderData->freqBandData.nNfb, - hHeaderData->sbrProcSmplRate, - chan, - overlap ); + err = createLppTransposer( + &hs->LppTrans, pSettings, hHeaderData->freqBandData.lowSubband, + hHeaderData->freqBandData.v_k_master, hHeaderData->freqBandData.numMaster, + hHeaderData->freqBandData.highSubband, timeSlots, noCols, + hHeaderData->freqBandData.freqBandTableNoise, + hHeaderData->freqBandData.nNfb, hHeaderData->sbrProcSmplRate, chan, + overlap); if (err != SBRDEC_OK) { return err; } - /* The CLDFB does not have overlap */ - if ((qmfFlags & QMF_FLAG_CLDFB) == 0) { - if (hs->pSbrOverlapBuffer == NULL) { - hs->pSbrOverlapBuffer = GetRam_sbr_OverlapBuffer(chan); - if (hs->pSbrOverlapBuffer == NULL) { - return SBRDEC_MEM_ALLOC_FAILED; - } - } else { - /* Clear overlap buffer */ - FDKmemclear( hs->pSbrOverlapBuffer, - sizeof(FIXP_DBL) * 2 * (6) * (64) - ); + if (flags & SBRDEC_USAC_HARMONICSBR) { + int noChannels, bSbr41 = flags & SBRDEC_QUAD_RATE ? 1 : 0; + + noChannels = + QMF_SYNTH_CHANNELS / + ((bSbr41 + 1) * 2); /* 32 for (32:64 and 24:64) and 16 for 16:64 */ + + /* shared memory between hbeLightTimeDelayBuffer and hQmfHBESlotsReal if + * SBRDEC_HBE_ENABLE */ + hSbrChannel->SbrDec.tmp_memory = (FIXP_DBL **)fdkCallocMatrix2D_aligned( + noCols, noChannels, sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.tmp_memory == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; } - } - /* Clear input delay line */ - FDKmemclear(hs->coreDelayBuf, (96)*sizeof(INT_PCM)); + hSbrChannel->SbrDec.hQmfHBESlotsReal = hSbrChannel->SbrDec.tmp_memory; + hSbrChannel->SbrDec.hQmfHBESlotsImag = + (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels, + sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.hQmfHBESlotsImag == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } - /* assign qmf time slots */ - assignTimeSlots( &hSbrChannel->SbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, qmfFlags & QMF_FLAG_LP); + /* buffers containing unmodified qmf data; required when switching from + * legacy SBR to HBE */ + /* buffer can be used as LPCFilterstates buffer because legacy SBR needs + * exactly these values for LPC filtering */ + hSbrChannel->SbrDec.codecQMFBufferReal = + (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels, + sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.codecQMFBufferReal == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + hSbrChannel->SbrDec.codecQMFBufferImag = + (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels, + sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.codecQMFBufferImag == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + err = QmfTransposerCreate(&hs->hHBE, codecFrameSize, 0, bSbr41); + if (err != SBRDEC_OK) { + return err; + } + } return err; } @@ -894,65 +991,88 @@ createSbrDec (SBR_CHANNEL * hSbrChannel, \brief Delete sbr decoder structure \return errorCode, 0 if successful */ -int -deleteSbrDec (SBR_CHANNEL * hSbrChannel) -{ +int deleteSbrDec(SBR_CHANNEL *hSbrChannel) { HANDLE_SBR_DEC hs = &hSbrChannel->SbrDec; - deleteSbrEnvelopeCalc (&hs->SbrCalculateEnvelope); + deleteSbrEnvelopeCalc(&hs->SbrCalculateEnvelope); - /* delete QMF filter states */ - if (hs->pSynQmfStates != NULL) { - FreeRam_sbr_QmfStatesSynthesis(&hs->pSynQmfStates); + if (hs->tmp_memory != NULL) { + FDK_FREE_MEMORY_2D_ALIGNED(hs->tmp_memory); } + /* modify here */ + FDK_FREE_MEMORY_2D_ALIGNED(hs->hQmfHBESlotsImag); + + if (hs->hHBE != NULL) QmfTransposerClose(hs->hHBE); + + if (hs->codecQMFBufferReal != NULL) { + FDK_FREE_MEMORY_2D_ALIGNED(hs->codecQMFBufferReal); + } - if (hs->pSbrOverlapBuffer != NULL) { - FreeRam_sbr_OverlapBuffer(&hs->pSbrOverlapBuffer); + if (hs->codecQMFBufferImag != NULL) { + FDK_FREE_MEMORY_2D_ALIGNED(hs->codecQMFBufferImag); } return 0; } - /*! \brief resets sbr decoder structure \return errorCode, 0 if successful */ SBR_ERROR -resetSbrDec (HANDLE_SBR_DEC hSbrDec, - HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, - const int useLP, - const int downsampleFac - ) -{ +resetSbrDec(HANDLE_SBR_DEC hSbrDec, HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, const int downsampleFac, + const UINT flags, HANDLE_SBR_FRAME_DATA hFrameData) { SBR_ERROR sbrError = SBRDEC_OK; - - int old_lsb = hSbrDec->SynthesisQMF.lsb; + int i; + FIXP_DBL *pLowBandReal[128]; + FIXP_DBL *pLowBandImag[128]; + int useLP = flags & SBRDEC_LOW_POWER; + + int old_lsb = hSbrDec->qmfDomainInCh->fb.lsb; + int old_usb = hSbrDec->qmfDomainInCh->fb.usb; int new_lsb = hHeaderData->freqBandData.lowSubband; + /* int new_usb = hHeaderData->freqBandData.highSubband; */ int l, startBand, stopBand, startSlot, size; - int source_scale, target_scale, delta_scale, target_lsb, target_usb, reserve; - FIXP_DBL maxVal; - - /* overlapBuffer point to first (6) slots */ - FIXP_DBL **OverlapBufferReal = hSbrDec->QmfBufferReal; - FIXP_DBL **OverlapBufferImag = hSbrDec->QmfBufferImag; - - /* assign qmf time slots */ - assignTimeSlots( hSbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, useLP); - - + FIXP_DBL **OverlapBufferReal = hSbrDec->qmfDomainInCh->hQmfSlotsReal; + FIXP_DBL **OverlapBufferImag = hSbrDec->qmfDomainInCh->hQmfSlotsImag; - resetSbrEnvelopeCalc (&hSbrDec->SbrCalculateEnvelope); - - hSbrDec->SynthesisQMF.lsb = hHeaderData->freqBandData.lowSubband; - hSbrDec->SynthesisQMF.usb = fixMin((INT)hSbrDec->SynthesisQMF.no_channels, (INT)hHeaderData->freqBandData.highSubband); + /* in case the previous frame was not active in terms of SBR processing, the + full band from 0 to no_channels was rescaled and not overwritten. Thats why + the scaling factor lb_scale can be seen as assigned to all bands from 0 to + no_channels in the previous frame. The same states for the current frame if + the current frame is not active in terms of SBR processing + */ + int applySbrProc = (hHeaderData->syncState == SBR_ACTIVE || + (hHeaderData->frameErrorFlag == 0 && + hHeaderData->syncState == SBR_HEADER)); + int applySbrProc_old = hSbrDec->applySbrProc_old; - hSbrDec->AnalysiscQMF.lsb = hSbrDec->SynthesisQMF.lsb; - hSbrDec->AnalysiscQMF.usb = hSbrDec->SynthesisQMF.usb; + if (!applySbrProc) { + new_lsb = (hSbrDec->qmfDomainInCh->fb).no_channels; + } + if (!applySbrProc_old) { + old_lsb = (hSbrDec->qmfDomainInCh->fb).no_channels; + old_usb = old_lsb; + } + resetSbrEnvelopeCalc(&hSbrDec->SbrCalculateEnvelope); + + /* Change lsb and usb */ + /* Synthesis */ + FDK_ASSERT(hSbrDec->qmfDomainOutCh != NULL); + hSbrDec->qmfDomainOutCh->fb.lsb = + fixMin((INT)hSbrDec->qmfDomainOutCh->fb.no_channels, + (INT)hHeaderData->freqBandData.lowSubband); + hSbrDec->qmfDomainOutCh->fb.usb = + fixMin((INT)hSbrDec->qmfDomainOutCh->fb.no_channels, + (INT)hHeaderData->freqBandData.highSubband); + /* Analysis */ + FDK_ASSERT(hSbrDec->qmfDomainInCh != NULL); + hSbrDec->qmfDomainInCh->fb.lsb = hSbrDec->qmfDomainOutCh->fb.lsb; + hSbrDec->qmfDomainInCh->fb.usb = hSbrDec->qmfDomainOutCh->fb.usb; /* The following initialization of spectral data in the overlap buffer @@ -964,135 +1084,397 @@ resetSbrDec (HANDLE_SBR_DEC hSbrDec, must be cleared because the whitening would be affected */ startBand = old_lsb; - stopBand = new_lsb; - startSlot = hHeaderData->timeStep * (hPrevFrameData->stopPos - hHeaderData->numberTimeSlots); - size = fixMax(0,stopBand-startBand); - - /* keep already adjusted data in the x-over-area */ - if (!useLP) { - for (l=startSlot; l<hSbrDec->LppTrans.pSettings->overlap; l++) { - FDKmemclear(&OverlapBufferReal[l][startBand], size*sizeof(FIXP_DBL)); - FDKmemclear(&OverlapBufferImag[l][startBand], size*sizeof(FIXP_DBL)); + stopBand = new_lsb; + startSlot = fMax(0, hHeaderData->timeStep * (hPrevFrameData->stopPos - + hHeaderData->numberTimeSlots)); + size = fMax(0, stopBand - startBand); + + /* in case of USAC we don't want to zero out the memory, as this can lead to + holes in the spectrum; fix shall only be applied for USAC not for MPEG-4 + SBR, in this case setting zero remains */ + if (!(flags & SBRDEC_SYNTAX_USAC)) { + /* keep already adjusted data in the x-over-area */ + if (!useLP) { + for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) { + FDKmemclear(&OverlapBufferReal[l][startBand], size * sizeof(FIXP_DBL)); + FDKmemclear(&OverlapBufferImag[l][startBand], size * sizeof(FIXP_DBL)); + } + } else { + for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) { + FDKmemclear(&OverlapBufferReal[l][startBand], size * sizeof(FIXP_DBL)); + } } - } else - for (l=startSlot; l<hSbrDec->LppTrans.pSettings->overlap ; l++) { - FDKmemclear(&OverlapBufferReal[l][startBand], size*sizeof(FIXP_DBL)); - } - - /* + /* reset LPC filter states - */ - startBand = fixMin(old_lsb,new_lsb); - stopBand = fixMax(old_lsb,new_lsb); - size = fixMax(0,stopBand-startBand); - - FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesReal[0][startBand], size*sizeof(FIXP_DBL)); - FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesReal[1][startBand], size*sizeof(FIXP_DBL)); - if (!useLP) { - FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImag[0][startBand], size*sizeof(FIXP_DBL)); - FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImag[1][startBand], size*sizeof(FIXP_DBL)); + */ + startBand = fixMin(old_lsb, new_lsb); + stopBand = fixMax(old_lsb, new_lsb); + size = fixMax(0, stopBand - startBand); + + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[0][startBand], + size * sizeof(FIXP_DBL)); + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[1][startBand], + size * sizeof(FIXP_DBL)); + if (!useLP) { + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[0][startBand], + size * sizeof(FIXP_DBL)); + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[1][startBand], + size * sizeof(FIXP_DBL)); + } } + if (startSlot != 0) { + int source_exp, target_exp, delta_exp, target_lsb, target_usb, reserve; + FIXP_DBL maxVal; - /* - Rescale already processed spectral data between old and new x-over frequency. - This must be done because of the separate scalefactors for lowband and highband. - */ - startBand = fixMin(old_lsb,new_lsb); - stopBand = fixMax(old_lsb,new_lsb); - - if (new_lsb > old_lsb) { - /* The x-over-area was part of the highband before and will now belong to the lowband */ - source_scale = hSbrDec->sbrScaleFactor.ov_hb_scale; - target_scale = hSbrDec->sbrScaleFactor.ov_lb_scale; - target_lsb = 0; - target_usb = old_lsb; - } - else { - /* The x-over-area was part of the lowband before and will now belong to the highband */ - source_scale = hSbrDec->sbrScaleFactor.ov_lb_scale; - target_scale = hSbrDec->sbrScaleFactor.ov_hb_scale; - /* jdr: The values old_lsb and old_usb might be wrong because the previous frame might have been "upsamling". */ - target_lsb = hSbrDec->SynthesisQMF.lsb; - target_usb = hSbrDec->SynthesisQMF.usb; - } + /* + Rescale already processed spectral data between old and new x-over + frequency. This must be done because of the separate scalefactors for + lowband and highband. + */ + + /* We have four relevant transitions to cover: + 1. old_usb is lower than new_lsb; old SBR area is completely below new SBR + area. + -> entire old area was highband and belongs to lowband now + and has to be rescaled. + 2. old_lsb is higher than new_usb; new SBR area is completely below old SBR + area. + -> old area between new_lsb and old_lsb was lowband and belongs to + highband now and has to be rescaled to match new highband scale. + 3. old_lsb is lower and old_usb is higher than new_lsb; old and new SBR + areas overlap. + -> old area between old_lsb and new_lsb was highband and belongs to + lowband now and has to be rescaled to match new lowband scale. + 4. new_lsb is lower and new_usb_is higher than old_lsb; old and new SBR + areas overlap. + -> old area between new_lsb and old_usb was lowband and belongs to + highband now and has to be rescaled to match new highband scale. + */ - /* Shift left all samples of the x-over-area as much as possible - An unnecessary coarse scale could cause ov_lb_scale or ov_hb_scale to be - adapted and the accuracy in the next frame would seriously suffer! */ + if (new_lsb > old_lsb) { + /* case 1 and 3 */ + source_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_hb_scale); + target_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale); + + startBand = old_lsb; + + if (new_lsb >= old_usb) { + /* case 1 */ + stopBand = old_usb; + } else { + /* case 3 */ + stopBand = new_lsb; + } - maxVal = maxSubbandSample( OverlapBufferReal, - (useLP) ? NULL : OverlapBufferImag, - startBand, - stopBand, - 0, - startSlot); + target_lsb = 0; + target_usb = old_lsb; + } else { + /* case 2 and 4 */ + source_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale); + target_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_hb_scale); - reserve = CntLeadingZeros(maxVal)-1; - reserve = fixMin(reserve,DFRACT_BITS-1-source_scale); + startBand = new_lsb; + stopBand = old_lsb; - rescaleSubbandSamples( OverlapBufferReal, - (useLP) ? NULL : OverlapBufferImag, - startBand, - stopBand, - 0, - startSlot, - reserve); - source_scale += reserve; + target_lsb = old_lsb; + target_usb = old_usb; + } - delta_scale = target_scale - source_scale; + maxVal = + maxSubbandSample(OverlapBufferReal, (useLP) ? NULL : OverlapBufferImag, + startBand, stopBand, 0, startSlot); - if (delta_scale > 0) { /* x-over-area is dominant */ - delta_scale = -delta_scale; - startBand = target_lsb; - stopBand = target_usb; + reserve = ((LONG)maxVal != 0 ? CntLeadingZeros(maxVal) - 1 : 0); + reserve = fixMin( + reserve, + DFRACT_BITS - 1 - + EXP2SCALE( + source_exp)); /* what is this line for, why do we need it? */ - if (new_lsb > old_lsb) { - /* The lowband has to be rescaled */ - hSbrDec->sbrScaleFactor.ov_lb_scale = source_scale; - } - else { - /* The highband has be be rescaled */ - hSbrDec->sbrScaleFactor.ov_hb_scale = source_scale; + /* process only if x-over-area is not dominant after rescale; + otherwise I'm not sure if all buffers are scaled correctly; + */ + if (target_exp - (source_exp - reserve) >= 0) { + rescaleSubbandSamples(OverlapBufferReal, + (useLP) ? NULL : OverlapBufferImag, startBand, + stopBand, 0, startSlot, reserve); + source_exp -= reserve; } - } - FDK_ASSERT(startBand <= stopBand); + delta_exp = target_exp - source_exp; + + if (delta_exp < 0) { /* x-over-area is dominant */ + startBand = target_lsb; + stopBand = target_usb; + delta_exp = -delta_exp; - if (!useLP) { - for (l=0; l<startSlot; l++) { - scaleValues( OverlapBufferReal[l] + startBand, stopBand-startBand, delta_scale ); - scaleValues( OverlapBufferImag[l] + startBand, stopBand-startBand, delta_scale ); + if (new_lsb > old_lsb) { + /* The lowband has to be rescaled */ + hSbrDec->qmfDomainInCh->scaling.ov_lb_scale = EXP2SCALE(source_exp); + } else { + /* The highband has to be rescaled */ + hSbrDec->qmfDomainInCh->scaling.ov_hb_scale = EXP2SCALE(source_exp); + } } - } else - for (l=0; l<startSlot; l++) { - scaleValues( OverlapBufferReal[l] + startBand, stopBand-startBand, delta_scale ); - } + FDK_ASSERT(startBand <= stopBand); + + if (!useLP) { + for (l = 0; l < startSlot; l++) { + scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand, + -delta_exp); + scaleValues(OverlapBufferImag[l] + startBand, stopBand - startBand, + -delta_exp); + } + } else + for (l = 0; l < startSlot; l++) { + scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand, + -delta_exp); + } + } /* startSlot != 0 */ /* Initialize transposer and limiter */ - sbrError = resetLppTransposer (&hSbrDec->LppTrans, - hHeaderData->freqBandData.lowSubband, - hHeaderData->freqBandData.v_k_master, - hHeaderData->freqBandData.numMaster, - hHeaderData->freqBandData.freqBandTableNoise, - hHeaderData->freqBandData.nNfb, - hHeaderData->freqBandData.highSubband, - hHeaderData->sbrProcSmplRate); - if (sbrError != SBRDEC_OK) - return sbrError; - - sbrError = ResetLimiterBands ( hHeaderData->freqBandData.limiterBandTable, - &hHeaderData->freqBandData.noLimiterBands, - hHeaderData->freqBandData.freqBandTable[0], - hHeaderData->freqBandData.nSfb[0], - hSbrDec->LppTrans.pSettings->patchParam, - hSbrDec->LppTrans.pSettings->noOfPatches, - hHeaderData->bs_data.limiterBands); + sbrError = resetLppTransposer( + &hSbrDec->LppTrans, hHeaderData->freqBandData.lowSubband, + hHeaderData->freqBandData.v_k_master, hHeaderData->freqBandData.numMaster, + hHeaderData->freqBandData.freqBandTableNoise, + hHeaderData->freqBandData.nNfb, hHeaderData->freqBandData.highSubband, + hHeaderData->sbrProcSmplRate); + if (sbrError != SBRDEC_OK) return sbrError; + + hSbrDec->savedStates = 0; + + if (flags & SBRDEC_USAC_HARMONICSBR) { + sbrError = QmfTransposerReInit(hSbrDec->hHBE, + hHeaderData->freqBandData.freqBandTable, + hHeaderData->freqBandData.nSfb); + if (sbrError != SBRDEC_OK) return sbrError; + + /* copy saved states from previous frame to legacy SBR lpc filterstate + * buffer */ + for (i = 0; i < LPC_ORDER + hSbrDec->LppTrans.pSettings->overlap; i++) { + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + hSbrDec->codecQMFBufferReal[hSbrDec->hHBE->noCols - LPC_ORDER - + hSbrDec->LppTrans.pSettings->overlap + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], + hSbrDec->codecQMFBufferImag[hSbrDec->hHBE->noCols - LPC_ORDER - + hSbrDec->LppTrans.pSettings->overlap + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + } + hSbrDec->savedStates = 1; + + { + /* map QMF buffer to pointer array (Overlap + Frame)*/ + for (i = 0; i < hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER; i++) { + pLowBandReal[i] = hSbrDec->LppTrans.lpcFilterStatesRealHBE[i]; + pLowBandImag[i] = hSbrDec->LppTrans.lpcFilterStatesImagHBE[i]; + } + + /* map QMF buffer to pointer array (Overlap + Frame)*/ + for (i = 0; i < hSbrDec->hHBE->noCols; i++) { + pLowBandReal[i + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->codecQMFBufferReal[i]; + pLowBandImag[i + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->codecQMFBufferImag[i]; + } + + if (flags & SBRDEC_QUAD_RATE) { + if (hFrameData->sbrPatchingMode == 0) { + int *xOverQmf = GetxOverBandQmfTransposer(hSbrDec->hHBE); + + /* in case of harmonic SBR and no HBE_LP map additional buffer for + one more frame to pointer arry */ + for (i = 0; i < hSbrDec->hHBE->noCols / 2; i++) { + pLowBandReal[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsReal[i]; + pLowBandImag[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsImag[i]; + } + + QmfTransposerApply( + hSbrDec->hHBE, + pLowBandReal + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols / 2 + LPC_ORDER, + pLowBandImag + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols / 2 + LPC_ORDER, + hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + hPrevFrameData->prevSbrPitchInBins, hSbrDec->scale_lb, + hSbrDec->scale_hbe, &hSbrDec->qmfDomainInCh->scaling.hb_scale, + hHeaderData->timeStep, hFrameData->frameInfo.borders[0], + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF); + + copyHarmonicSpectrum( + xOverQmf, pLowBandReal, pLowBandImag, hSbrDec->hHBE->noCols, + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF); + } + } else { + /* in case of harmonic SBR and no HBE_LP map additional buffer for + one more frame to pointer arry */ + for (i = 0; i < hSbrDec->hHBE->noCols; i++) { + pLowBandReal[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsReal[i]; + pLowBandImag[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsImag[i]; + } + + if (hFrameData->sbrPatchingMode == 0) { + QmfTransposerApply( + hSbrDec->hHBE, + pLowBandReal + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER, + pLowBandImag + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER, + hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + 0 /* not required for keeping states updated in this frame*/, + hSbrDec->scale_lb, hSbrDec->scale_lb, + &hSbrDec->qmfDomainInCh->scaling.hb_scale, hHeaderData->timeStep, + hFrameData->frameInfo.borders[0], + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_NOOUT); + } + + QmfTransposerApply( + hSbrDec->hHBE, + pLowBandReal + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols + LPC_ORDER, + pLowBandImag + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols + LPC_ORDER, + hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + hPrevFrameData->prevSbrPitchInBins, hSbrDec->scale_lb, + hSbrDec->scale_hbe, &hSbrDec->qmfDomainInCh->scaling.hb_scale, + hHeaderData->timeStep, hFrameData->frameInfo.borders[0], + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF); + } + + if (hFrameData->sbrPatchingMode == 0) { + for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) { + /* + Store the unmodified qmf Slots values for upper part of spectrum + (required for LPC filtering) required if next frame is a HBE frame + */ + FDKmemcpy(hSbrDec->qmfDomainInCh->hQmfSlotsReal[i], + hSbrDec->LppTrans.lpcFilterStatesRealHBE[i + LPC_ORDER], + (64) * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->qmfDomainInCh->hQmfSlotsImag[i], + hSbrDec->LppTrans.lpcFilterStatesImagHBE[i + LPC_ORDER], + (64) * sizeof(FIXP_DBL)); + } + + for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) { + /* + Store the unmodified qmf Slots values for upper part of spectrum + (required for LPC filtering) required if next frame is a HBE frame + */ + FDKmemcpy( + hSbrDec->qmfDomainInCh->hQmfSlotsReal[i], + hSbrDec->codecQMFBufferReal[hSbrDec->hHBE->noCols - + hSbrDec->LppTrans.pSettings->overlap + + i], + new_lsb * sizeof(FIXP_DBL)); + FDKmemcpy( + hSbrDec->qmfDomainInCh->hQmfSlotsImag[i], + hSbrDec->codecQMFBufferImag[hSbrDec->hHBE->noCols - + hSbrDec->LppTrans.pSettings->overlap + + i], + new_lsb * sizeof(FIXP_DBL)); + } + } + } + } + + { + int adapt_lb = 0, diff = 0, + new_scale = hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + + if ((hSbrDec->qmfDomainInCh->scaling.ov_lb_scale != + hSbrDec->qmfDomainInCh->scaling.lb_scale) && + startSlot != 0) { + /* we need to adapt spectrum to have equal scale factor, always larger + * than zero */ + diff = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale) - + SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.lb_scale); + + if (diff > 0) { + adapt_lb = 1; + diff = -diff; + new_scale = hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + } + + stopBand = new_lsb; + } + + if (hFrameData->sbrPatchingMode == 1) { + /* scale states from LegSBR filterstates buffer */ + for (i = 0; i < hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER; i++) { + scaleValues(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], new_lsb, + diff); + if (!useLP) { + scaleValues(hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], new_lsb, + diff); + } + } + + if (flags & SBRDEC_SYNTAX_USAC) { + /* get missing states between old and new x_over from LegSBR + * filterstates buffer */ + /* in case of legacy SBR we leave these values zeroed out */ + for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) { + FDKmemcpy(&OverlapBufferReal[i][old_lsb], + &hSbrDec->LppTrans + .lpcFilterStatesRealLegSBR[LPC_ORDER + i][old_lsb], + fMax(new_lsb - old_lsb, 0) * sizeof(FIXP_DBL)); + if (!useLP) { + FDKmemcpy(&OverlapBufferImag[i][old_lsb], + &hSbrDec->LppTrans + .lpcFilterStatesImagLegSBR[LPC_ORDER + i][old_lsb], + fMax(new_lsb - old_lsb, 0) * sizeof(FIXP_DBL)); + } + } + } + + if (new_lsb > old_lsb) { + stopBand = old_lsb; + } + } + if ((adapt_lb == 1) && (stopBand > startBand)) { + for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) { + scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand, + diff); + if (!useLP) { + scaleValues(OverlapBufferImag[l] + startBand, stopBand - startBand, + diff); + } + } + } + hSbrDec->qmfDomainInCh->scaling.ov_lb_scale = new_scale; + } + sbrError = ResetLimiterBands(hHeaderData->freqBandData.limiterBandTable, + &hHeaderData->freqBandData.noLimiterBands, + hHeaderData->freqBandData.freqBandTable[0], + hHeaderData->freqBandData.nSfb[0], + hSbrDec->LppTrans.pSettings->patchParam, + hSbrDec->LppTrans.pSettings->noOfPatches, + hHeaderData->bs_data.limiterBands, + hFrameData->sbrPatchingMode, + GetxOverBandQmfTransposer(hSbrDec->hHBE), + Get41SbrQmfTransposer(hSbrDec->hHBE)); + + hSbrDec->SbrCalculateEnvelope.sbrPatchingMode = hFrameData->sbrPatchingMode; return sbrError; } |