aboutsummaryrefslogtreecommitdiffstats
path: root/libSBRdec/src/lpp_tran.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libSBRdec/src/lpp_tran.cpp')
-rw-r--r--libSBRdec/src/lpp_tran.cpp1431
1 files changed, 946 insertions, 485 deletions
diff --git a/libSBRdec/src/lpp_tran.cpp b/libSBRdec/src/lpp_tran.cpp
index 343aec3..aa1fd5d 100644
--- a/libSBRdec/src/lpp_tran.cpp
+++ b/libSBRdec/src/lpp_tran.cpp
@@ -1,74 +1,85 @@
-
-/* -----------------------------------------------------------------------------------------------------------
+/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2013 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,30 @@ Am Wolfsmantel 33
www.iis.fraunhofer.de/amm
amm-info@iis.fraunhofer.de
------------------------------------------------------------------------------------------------------------ */
+----------------------------------------------------------------------------- */
+
+/**************************** SBR decoder library ******************************
+
+ Author(s):
+
+ Description:
+
+*******************************************************************************/
/*!
\file
- \brief Low Power Profile Transposer,
- This module provides the transposer. The main entry point is lppTransposer(). The function generates
- high frequency content by copying data from the low band (provided by core codec) into the high band.
- This process is also referred to as "patching". The function also implements spectral whitening by means of
- inverse filtering based on LPC coefficients.
-
- Together with the QMF filterbank the transposer can be tested using a supplied test program. See main_audio.cpp for details.
- This module does use fractional arithmetic and the accuracy of the computations has an impact on the overall sound quality.
- The module also needs to take into account the different scaling of spectral data.
+ \brief Low Power Profile Transposer
+ This module provides the transposer. The main entry point is lppTransposer().
+ The function generates high frequency content by copying data from the low
+ band (provided by core codec) into the high band. This process is also
+ referred to as "patching". The function also implements spectral whitening by
+ means of inverse filtering based on LPC coefficients.
+
+ Together with the QMF filterbank the transposer can be tested using a supplied
+ test program. See main_audio.cpp for details. This module does use fractional
+ arithmetic and the accuracy of the computations has an impact on the overall
+ sound quality. The module also needs to take into account the different
+ scaling of spectral data.
\sa lppTransposer(), main_audio.cpp, sbr_scale.h, \ref documentationOverview
*/
@@ -104,16 +126,13 @@ amm-info@iis.fraunhofer.de
#include "genericStds.h"
#include "autocorr2nd.h"
-
+#include "HFgen_preFlat.h"
#if defined(__arm__)
#include "arm/lpp_tran_arm.cpp"
#endif
-
-
-#define LPC_SCALE_FACTOR 2
-
+#define LPC_SCALE_FACTOR 2
/*!
*
@@ -125,33 +144,28 @@ amm-info@iis.fraunhofer.de
* level is being inserted to achieve a smooth transition.
*/
-#ifndef FUNCTION_mapInvfMode
-static FIXP_DBL
-mapInvfMode (INVF_MODE mode,
- INVF_MODE prevMode,
- WHITENING_FACTORS whFactors)
-{
+static FIXP_DBL mapInvfMode(INVF_MODE mode, INVF_MODE prevMode,
+ WHITENING_FACTORS whFactors) {
switch (mode) {
- case INVF_LOW_LEVEL:
- if(prevMode == INVF_OFF)
- return whFactors.transitionLevel;
- else
- return whFactors.lowLevel;
-
- case INVF_MID_LEVEL:
- return whFactors.midLevel;
-
- case INVF_HIGH_LEVEL:
- return whFactors.highLevel;
-
- default:
- if(prevMode == INVF_LOW_LEVEL)
- return whFactors.transitionLevel;
- else
- return whFactors.off;
+ case INVF_LOW_LEVEL:
+ if (prevMode == INVF_OFF)
+ return whFactors.transitionLevel;
+ else
+ return whFactors.lowLevel;
+
+ case INVF_MID_LEVEL:
+ return whFactors.midLevel;
+
+ case INVF_HIGH_LEVEL:
+ return whFactors.highLevel;
+
+ default:
+ if (prevMode == INVF_LOW_LEVEL)
+ return whFactors.transitionLevel;
+ else
+ return whFactors.off;
}
}
-#endif /* #ifndef FUNCTION_mapInvfMode */
/*!
*
@@ -161,124 +175,148 @@ mapInvfMode (INVF_MODE mode,
*
*/
-#ifndef FUNCTION_inverseFilteringLevelEmphasis
-static void
-inverseFilteringLevelEmphasis(HANDLE_SBR_LPP_TRANS hLppTrans,/*!< Handle of lpp transposer */
- UCHAR nInvfBands, /*!< Number of bands for inverse filtering */
- INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */
- INVF_MODE *sbr_invf_mode_prev, /*!< Previous inverse filtering modes */
- FIXP_DBL * bwVector /*!< Resulting filtering levels */
- )
-{
- for(int i = 0; i < nInvfBands; i++) {
+static void inverseFilteringLevelEmphasis(
+ HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */
+ UCHAR nInvfBands, /*!< Number of bands for inverse filtering */
+ INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */
+ INVF_MODE *sbr_invf_mode_prev, /*!< Previous inverse filtering modes */
+ FIXP_DBL *bwVector /*!< Resulting filtering levels */
+) {
+ for (int i = 0; i < nInvfBands; i++) {
FIXP_DBL accu;
- FIXP_DBL bwTmp = mapInvfMode (sbr_invf_mode[i],
- sbr_invf_mode_prev[i],
- hLppTrans->pSettings->whFactors);
-
- if(bwTmp < hLppTrans->bwVectorOld[i]) {
- accu = fMultDiv2(FL2FXCONST_DBL(0.75f),bwTmp) +
- fMultDiv2(FL2FXCONST_DBL(0.25f),hLppTrans->bwVectorOld[i]);
- }
- else {
- accu = fMultDiv2(FL2FXCONST_DBL(0.90625f),bwTmp) +
- fMultDiv2(FL2FXCONST_DBL(0.09375f),hLppTrans->bwVectorOld[i]);
+ FIXP_DBL bwTmp = mapInvfMode(sbr_invf_mode[i], sbr_invf_mode_prev[i],
+ hLppTrans->pSettings->whFactors);
+
+ if (bwTmp < hLppTrans->bwVectorOld[i]) {
+ accu = fMultDiv2(FL2FXCONST_DBL(0.75f), bwTmp) +
+ fMultDiv2(FL2FXCONST_DBL(0.25f), hLppTrans->bwVectorOld[i]);
+ } else {
+ accu = fMultDiv2(FL2FXCONST_DBL(0.90625f), bwTmp) +
+ fMultDiv2(FL2FXCONST_DBL(0.09375f), hLppTrans->bwVectorOld[i]);
}
- if (accu < FL2FXCONST_DBL(0.015625f)>>1)
+ if (accu<FL2FXCONST_DBL(0.015625f)>> 1) {
bwVector[i] = FL2FXCONST_DBL(0.0f);
- else
- bwVector[i] = fixMin(accu<<1,FL2FXCONST_DBL(0.99609375f));
+ } else {
+ bwVector[i] = fixMin(accu << 1, FL2FXCONST_DBL(0.99609375f));
+ }
}
}
-#endif /* #ifndef FUNCTION_inverseFilteringLevelEmphasis */
/* Resulting autocorrelation determinant exponent */
-#define ACDET_EXP (2*(DFRACT_BITS+sbrScaleFactor->lb_scale+10-ac.det_scale))
-#define AC_EXP (-sbrScaleFactor->lb_scale+LPC_SCALE_FACTOR)
-#define ALPHA_EXP (-sbrScaleFactor->lb_scale+LPC_SCALE_FACTOR+1)
-/* Resulting transposed QMF values exponent 16 bit normalized samplebits assumed. */
-#define QMFOUT_EXP ((SAMPLE_BITS-15)-sbrScaleFactor->lb_scale)
+#define ACDET_EXP \
+ (2 * (DFRACT_BITS + sbrScaleFactor->lb_scale + 10 - ac.det_scale))
+#define AC_EXP (-sbrScaleFactor->lb_scale + LPC_SCALE_FACTOR)
+#define ALPHA_EXP (-sbrScaleFactor->lb_scale + LPC_SCALE_FACTOR + 1)
+/* Resulting transposed QMF values exponent 16 bit normalized samplebits
+ * assumed. */
+#define QMFOUT_EXP ((SAMPLE_BITS - 15) - sbrScaleFactor->lb_scale)
+
+static inline void calc_qmfBufferReal(FIXP_DBL **qmfBufferReal,
+ const FIXP_DBL *const lowBandReal,
+ const int startSample,
+ const int stopSample, const UCHAR hiBand,
+ const int dynamicScale, const int descale,
+ const FIXP_SGL a0r, const FIXP_SGL a1r) {
+ FIXP_DBL accu1, accu2;
+ int i;
+
+ for (i = 0; i < stopSample - startSample; i++) {
+ accu1 = fMultDiv2(a1r, lowBandReal[i]);
+ accu1 = (fMultDiv2(a0r, lowBandReal[i + 1]) + accu1);
+ accu1 = accu1 >> dynamicScale;
+
+ accu1 <<= 1;
+ accu2 = (lowBandReal[i + 2] >> descale);
+ qmfBufferReal[i + startSample][hiBand] = accu1 + accu2;
+ }
+}
/*!
*
* \brief Perform transposition by patching of subband samples.
- * This function serves as the main entry point into the module. The function determines the areas for the
- * patching process (these are the source range as well as the target range) and implements spectral whitening
- * by means of inverse filtering. The function autoCorrelation2nd() is an auxiliary function for calculating the
- * LPC coefficients for the filtering. The actual calculation of the LPC coefficients and the implementation
- * of the filtering are done as part of lppTransposer().
+ * This function serves as the main entry point into the module. The function
+ * determines the areas for the patching process (these are the source range as
+ * well as the target range) and implements spectral whitening by means of
+ * inverse filtering. The function autoCorrelation2nd() is an auxiliary function
+ * for calculating the LPC coefficients for the filtering. The actual
+ * calculation of the LPC coefficients and the implementation of the filtering
+ * are done as part of lppTransposer().
*
- * Note that the filtering is done on all available QMF subsamples, whereas the patching is only done on those QMF
- * subsamples that will be used in the next QMF synthesis. The filtering is also implemented before the patching
- * includes further dependencies on parameters from the SBR data.
+ * Note that the filtering is done on all available QMF subsamples, whereas the
+ * patching is only done on those QMF subsamples that will be used in the next
+ * QMF synthesis. The filtering is also implemented before the patching includes
+ * further dependencies on parameters from the SBR data.
*
*/
-void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */
- QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */
- FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband samples (source) */
-
- FIXP_DBL *degreeAlias, /*!< Vector for results of aliasing estimation */
- FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of subband samples (source) */
- const int useLP,
- const int timeStep, /*!< Time step of envelope */
- const int firstSlotOffs, /*!< Start position in time */
- const int lastSlotOffs, /*!< Number of overlap-slots into next frame */
- const int nInvfBands, /*!< Number of bands for inverse filtering */
- INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */
- INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */
- )
-{
- INT bwIndex[MAX_NUM_PATCHES];
- FIXP_DBL bwVector[MAX_NUM_PATCHES]; /*!< pole moving factors */
-
- int i;
- int loBand, start, stop;
+void lppTransposer(
+ HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */
+ QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */
+ FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband
+ samples (source) */
+
+ FIXP_DBL *degreeAlias, /*!< Vector for results of aliasing estimation */
+ FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of
+ subband samples (source) */
+ const int useLP, const int fPreWhitening, const int v_k_master0,
+ const int timeStep, /*!< Time step of envelope */
+ const int firstSlotOffs, /*!< Start position in time */
+ const int lastSlotOffs, /*!< Number of overlap-slots into next frame */
+ const int nInvfBands, /*!< Number of bands for inverse filtering */
+ INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */
+ INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */
+) {
+ INT bwIndex[MAX_NUM_PATCHES];
+ FIXP_DBL bwVector[MAX_NUM_PATCHES]; /*!< pole moving factors */
+ FIXP_DBL preWhiteningGains[(64) / 2];
+ int preWhiteningGains_exp[(64) / 2];
+
+ int i;
+ int loBand, start, stop;
TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings;
PATCH_PARAM *patchParam = pSettings->patchParam;
- int patch;
+ int patch;
- FIXP_SGL alphar[LPC_ORDER], a0r, a1r;
- FIXP_SGL alphai[LPC_ORDER], a0i=0, a1i=0;
- FIXP_SGL bw = FL2FXCONST_SGL(0.0f);
+ FIXP_SGL alphar[LPC_ORDER], a0r, a1r;
+ FIXP_SGL alphai[LPC_ORDER], a0i = 0, a1i = 0;
+ FIXP_SGL bw = FL2FXCONST_SGL(0.0f);
- int autoCorrLength;
+ int autoCorrLength;
- FIXP_DBL k1, k1_below=0, k1_below2=0;
+ FIXP_DBL k1, k1_below = 0, k1_below2 = 0;
ACORR_COEFS ac;
- int startSample;
- int stopSample;
- int stopSampleClear;
+ int startSample;
+ int stopSample;
+ int stopSampleClear;
int comLowBandScale;
int ovLowBandShift;
int lowBandShift;
-/* int ovHighBandShift;*/
+ /* int ovHighBandShift;*/
int targetStopBand;
-
alphai[0] = FL2FXCONST_SGL(0.0f);
alphai[1] = FL2FXCONST_SGL(0.0f);
-
startSample = firstSlotOffs * timeStep;
- stopSample = pSettings->nCols + lastSlotOffs * timeStep;
+ stopSample = pSettings->nCols + lastSlotOffs * timeStep;
+ FDK_ASSERT((lastSlotOffs * timeStep) <= pSettings->overlap);
-
- inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode, sbr_invf_mode_prev, bwVector);
+ inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode,
+ sbr_invf_mode_prev, bwVector);
stopSampleClear = stopSample;
autoCorrLength = pSettings->nCols + pSettings->overlap;
/* Set upper subbands to zero:
- This is required in case that the patches do not cover the complete highband
- (because the last patch would be too short).
- Possible optimization: Clearing bands up to usb would be sufficient here. */
- targetStopBand = patchParam[pSettings->noOfPatches-1].targetStartBand
- + patchParam[pSettings->noOfPatches-1].numBandsInPatch;
+ This is required in case that the patches do not cover the complete
+ highband (because the last patch would be too short). Possible
+ optimization: Clearing bands up to usb would be sufficient here. */
+ targetStopBand = patchParam[pSettings->noOfPatches - 1].targetStartBand +
+ patchParam[pSettings->noOfPatches - 1].numBandsInPatch;
int memSize = ((64) - targetStopBand) * sizeof(FIXP_DBL);
@@ -287,67 +325,84 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp
FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize);
FDKmemclear(&qmfBufferImag[i][targetStopBand], memSize);
}
- } else
- for (i = startSample; i < stopSampleClear; i++) {
- FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize);
+ } else {
+ for (i = startSample; i < stopSampleClear; i++) {
+ FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize);
+ }
}
/* init bwIndex for each patch */
- FDKmemclear(bwIndex, MAX_NUM_PATCHES*sizeof(INT));
+ FDKmemclear(bwIndex, sizeof(bwIndex));
/*
Calc common low band scale factor
*/
- comLowBandScale = fixMin(sbrScaleFactor->ov_lb_scale,sbrScaleFactor->lb_scale);
+ comLowBandScale =
+ fixMin(sbrScaleFactor->ov_lb_scale, sbrScaleFactor->lb_scale);
- ovLowBandShift = sbrScaleFactor->ov_lb_scale - comLowBandScale;
- lowBandShift = sbrScaleFactor->lb_scale - comLowBandScale;
+ ovLowBandShift = sbrScaleFactor->ov_lb_scale - comLowBandScale;
+ lowBandShift = sbrScaleFactor->lb_scale - comLowBandScale;
/* ovHighBandShift = firstSlotOffs == 0 ? ovLowBandShift:0;*/
+ if (fPreWhitening) {
+ sbrDecoder_calculateGainVec(
+ qmfBufferReal, qmfBufferImag,
+ DFRACT_BITS - 1 - 16 -
+ sbrScaleFactor->ov_lb_scale, /* convert scale to exponent */
+ DFRACT_BITS - 1 - 16 -
+ sbrScaleFactor->lb_scale, /* convert scale to exponent */
+ pSettings->overlap, preWhiteningGains, preWhiteningGains_exp,
+ v_k_master0, startSample, stopSample);
+ }
+
/* outer loop over bands to do analysis only once for each band */
if (!useLP) {
start = pSettings->lbStartPatching;
stop = pSettings->lbStopPatching;
- } else
- {
+ } else {
start = fixMax(1, pSettings->lbStartPatching - 2);
stop = patchParam[0].targetStartBand;
}
-
- for ( loBand = start; loBand < stop; loBand++ ) {
-
- FIXP_DBL lowBandReal[(((1024)/(32))+(6))+LPC_ORDER];
+ for (loBand = start; loBand < stop; loBand++) {
+ FIXP_DBL lowBandReal[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER];
FIXP_DBL *plowBandReal = lowBandReal;
- FIXP_DBL **pqmfBufferReal = qmfBufferReal;
- FIXP_DBL lowBandImag[(((1024)/(32))+(6))+LPC_ORDER];
+ FIXP_DBL **pqmfBufferReal =
+ qmfBufferReal + firstSlotOffs * timeStep /* + pSettings->overlap */;
+ FIXP_DBL lowBandImag[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER];
FIXP_DBL *plowBandImag = lowBandImag;
- FIXP_DBL **pqmfBufferImag = qmfBufferImag;
- int resetLPCCoeffs=0;
- int dynamicScale = DFRACT_BITS-1-LPC_SCALE_FACTOR;
+ FIXP_DBL **pqmfBufferImag =
+ qmfBufferImag + firstSlotOffs * timeStep /* + pSettings->overlap */;
+ int resetLPCCoeffs = 0;
+ int dynamicScale = DFRACT_BITS - 1 - LPC_SCALE_FACTOR;
int acDetScale = 0; /* scaling of autocorrelation determinant */
- for(i=0;i<LPC_ORDER;i++){
- *plowBandReal++ = hLppTrans->lpcFilterStatesReal[i][loBand];
+ for (i = 0;
+ i < LPC_ORDER + firstSlotOffs * timeStep /*+pSettings->overlap*/;
+ i++) {
+ *plowBandReal++ = hLppTrans->lpcFilterStatesRealLegSBR[i][loBand];
if (!useLP)
- *plowBandImag++ = hLppTrans->lpcFilterStatesImag[i][loBand];
+ *plowBandImag++ = hLppTrans->lpcFilterStatesImagLegSBR[i][loBand];
}
/*
Take old slope length qmf slot source values out of (overlap)qmf buffer
*/
if (!useLP) {
- for(i=0;i<pSettings->nCols+pSettings->overlap;i++){
+ for (i = 0;
+ i < pSettings->nCols + pSettings->overlap - firstSlotOffs * timeStep;
+ i++) {
*plowBandReal++ = (*pqmfBufferReal++)[loBand];
*plowBandImag++ = (*pqmfBufferImag++)[loBand];
}
- } else
- {
+ } else {
/* pSettings->overlap is always even */
FDK_ASSERT((pSettings->overlap & 1) == 0);
-
- for(i=0;i<((pSettings->overlap+pSettings->nCols)>>1);i++) {
+ for (i = 0; i < ((pSettings->nCols + pSettings->overlap -
+ firstSlotOffs * timeStep) >>
+ 1);
+ i++) {
*plowBandReal++ = (*pqmfBufferReal++)[loBand];
*plowBandReal++ = (*pqmfBufferReal++)[loBand];
}
@@ -359,61 +414,77 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp
/*
Determine dynamic scaling value.
*/
- dynamicScale = fixMin(dynamicScale, getScalefactor(lowBandReal, LPC_ORDER+pSettings->overlap) + ovLowBandShift);
- dynamicScale = fixMin(dynamicScale, getScalefactor(&lowBandReal[LPC_ORDER+pSettings->overlap], pSettings->nCols) + lowBandShift);
+ dynamicScale =
+ fixMin(dynamicScale,
+ getScalefactor(lowBandReal, LPC_ORDER + pSettings->overlap) +
+ ovLowBandShift);
+ dynamicScale =
+ fixMin(dynamicScale,
+ getScalefactor(&lowBandReal[LPC_ORDER + pSettings->overlap],
+ pSettings->nCols) +
+ lowBandShift);
if (!useLP) {
- dynamicScale = fixMin(dynamicScale, getScalefactor(lowBandImag, LPC_ORDER+pSettings->overlap) + ovLowBandShift);
- dynamicScale = fixMin(dynamicScale, getScalefactor(&lowBandImag[LPC_ORDER+pSettings->overlap], pSettings->nCols) + lowBandShift);
+ dynamicScale =
+ fixMin(dynamicScale,
+ getScalefactor(lowBandImag, LPC_ORDER + pSettings->overlap) +
+ ovLowBandShift);
+ dynamicScale =
+ fixMin(dynamicScale,
+ getScalefactor(&lowBandImag[LPC_ORDER + pSettings->overlap],
+ pSettings->nCols) +
+ lowBandShift);
}
- dynamicScale = fixMax(0, dynamicScale-1); /* one additional bit headroom to prevent -1.0 */
+ dynamicScale = fixMax(
+ 0, dynamicScale - 1); /* one additional bit headroom to prevent -1.0 */
/*
Scale temporal QMF buffer.
*/
- scaleValues(&lowBandReal[0], LPC_ORDER+pSettings->overlap, dynamicScale-ovLowBandShift);
- scaleValues(&lowBandReal[LPC_ORDER+pSettings->overlap], pSettings->nCols, dynamicScale-lowBandShift);
+ scaleValues(&lowBandReal[0], LPC_ORDER + pSettings->overlap,
+ dynamicScale - ovLowBandShift);
+ scaleValues(&lowBandReal[LPC_ORDER + pSettings->overlap], pSettings->nCols,
+ dynamicScale - lowBandShift);
if (!useLP) {
- scaleValues(&lowBandImag[0], LPC_ORDER+pSettings->overlap, dynamicScale-ovLowBandShift);
- scaleValues(&lowBandImag[LPC_ORDER+pSettings->overlap], pSettings->nCols, dynamicScale-lowBandShift);
+ scaleValues(&lowBandImag[0], LPC_ORDER + pSettings->overlap,
+ dynamicScale - ovLowBandShift);
+ scaleValues(&lowBandImag[LPC_ORDER + pSettings->overlap],
+ pSettings->nCols, dynamicScale - lowBandShift);
}
+ if (!useLP) {
+ acDetScale += autoCorr2nd_cplx(&ac, lowBandReal + LPC_ORDER,
+ lowBandImag + LPC_ORDER, autoCorrLength);
+ } else {
+ acDetScale +=
+ autoCorr2nd_real(&ac, lowBandReal + LPC_ORDER, autoCorrLength);
+ }
- if (!useLP) {
- acDetScale += autoCorr2nd_cplx(&ac, lowBandReal+LPC_ORDER, lowBandImag+LPC_ORDER, autoCorrLength);
- }
- else
- {
- acDetScale += autoCorr2nd_real(&ac, lowBandReal+LPC_ORDER, autoCorrLength);
- }
-
- /* Examine dynamic of determinant in autocorrelation. */
- acDetScale += 2*(comLowBandScale + dynamicScale);
- acDetScale *= 2; /* two times reflection coefficent scaling */
- acDetScale += ac.det_scale; /* ac scaling of determinant */
-
- /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */
- if (acDetScale>126 ) {
- resetLPCCoeffs = 1;
- }
+ /* Examine dynamic of determinant in autocorrelation. */
+ acDetScale += 2 * (comLowBandScale + dynamicScale);
+ acDetScale *= 2; /* two times reflection coefficent scaling */
+ acDetScale += ac.det_scale; /* ac scaling of determinant */
+ /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */
+ if (acDetScale > 126) {
+ resetLPCCoeffs = 1;
+ }
alphar[1] = FL2FXCONST_SGL(0.0f);
- if (!useLP)
- alphai[1] = FL2FXCONST_SGL(0.0f);
+ if (!useLP) alphai[1] = FL2FXCONST_SGL(0.0f);
if (ac.det != FL2FXCONST_DBL(0.0f)) {
- FIXP_DBL tmp,absTmp,absDet;
+ FIXP_DBL tmp, absTmp, absDet;
absDet = fixp_abs(ac.det);
if (!useLP) {
- tmp = ( fMultDiv2(ac.r01r,ac.r12r) >> (LPC_SCALE_FACTOR-1) ) -
- ( (fMultDiv2(ac.r01i,ac.r12i) + fMultDiv2(ac.r02r,ac.r11r)) >> (LPC_SCALE_FACTOR-1) );
- } else
- {
- tmp = ( fMultDiv2(ac.r01r,ac.r12r) >> (LPC_SCALE_FACTOR-1) ) -
- ( fMultDiv2(ac.r02r,ac.r11r) >> (LPC_SCALE_FACTOR-1) );
+ tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) -
+ ((fMultDiv2(ac.r01i, ac.r12i) + fMultDiv2(ac.r02r, ac.r11r)) >>
+ (LPC_SCALE_FACTOR - 1));
+ } else {
+ tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) -
+ (fMultDiv2(ac.r02r, ac.r11r) >> (LPC_SCALE_FACTOR - 1));
}
absTmp = fixp_abs(tmp);
@@ -423,23 +494,23 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp
{
INT scale;
FIXP_DBL result = fDivNorm(absTmp, absDet, &scale);
- scale = scale+ac.det_scale;
+ scale = scale + ac.det_scale;
- if ( (scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL>>scale) ) {
+ if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) {
resetLPCCoeffs = 1;
- }
- else {
- alphar[1] = FX_DBL2FX_SGL(scaleValue(result,scale));
- if((tmp<FL2FX_DBL(0.0f)) ^ (ac.det<FL2FX_DBL(0.0f))) {
+ } else {
+ alphar[1] = FX_DBL2FX_SGL(scaleValue(result, scale));
+ if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
alphar[1] = -alphar[1];
}
}
}
- if (!useLP)
- {
- tmp = ( fMultDiv2(ac.r01i,ac.r12r) >> (LPC_SCALE_FACTOR-1) ) +
- ( (fMultDiv2(ac.r01r,ac.r12i) - (FIXP_DBL)fMultDiv2(ac.r02i,ac.r11r)) >> (LPC_SCALE_FACTOR-1) ) ;
+ if (!useLP) {
+ tmp = (fMultDiv2(ac.r01i, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) +
+ ((fMultDiv2(ac.r01r, ac.r12i) -
+ (FIXP_DBL)fMultDiv2(ac.r02i, ac.r11r)) >>
+ (LPC_SCALE_FACTOR - 1));
absTmp = fixp_abs(tmp);
@@ -449,14 +520,15 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp
{
INT scale;
FIXP_DBL result = fDivNorm(absTmp, absDet, &scale);
- scale = scale+ac.det_scale;
+ scale = scale + ac.det_scale;
- if ( (scale > 0) && (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL>>scale) ) {
+ if ((scale > 0) &&
+ (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL >>
+ scale)) {
resetLPCCoeffs = 1;
- }
- else {
- alphai[1] = FX_DBL2FX_SGL(scaleValue(result,scale));
- if((tmp<FL2FX_DBL(0.0f)) ^ (ac.det<FL2FX_DBL(0.0f))) {
+ } else {
+ alphai[1] = FX_DBL2FX_SGL(scaleValue(result, scale));
+ if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
alphai[1] = -alphai[1];
}
}
@@ -464,24 +536,23 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp
}
}
- alphar[0] = FL2FXCONST_SGL(0.0f);
- if (!useLP)
- alphai[0] = FL2FXCONST_SGL(0.0f);
-
- if ( ac.r11r != FL2FXCONST_DBL(0.0f) ) {
+ alphar[0] = FL2FXCONST_SGL(0.0f);
+ if (!useLP) alphai[0] = FL2FXCONST_SGL(0.0f);
+ if (ac.r11r != FL2FXCONST_DBL(0.0f)) {
/* ac.r11r is always >=0 */
- FIXP_DBL tmp,absTmp;
+ FIXP_DBL tmp, absTmp;
if (!useLP) {
- tmp = (ac.r01r>>(LPC_SCALE_FACTOR+1)) +
- (fMultDiv2(alphar[1],ac.r12r) + fMultDiv2(alphai[1],ac.r12i));
- } else
- {
- if(ac.r01r>=FL2FXCONST_DBL(0.0f))
- tmp = (ac.r01r>>(LPC_SCALE_FACTOR+1)) + fMultDiv2(alphar[1],ac.r12r);
+ tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) +
+ (fMultDiv2(alphar[1], ac.r12r) + fMultDiv2(alphai[1], ac.r12i));
+ } else {
+ if (ac.r01r >= FL2FXCONST_DBL(0.0f))
+ tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) +
+ fMultDiv2(alphar[1], ac.r12r);
else
- tmp = -((-ac.r01r)>>(LPC_SCALE_FACTOR+1)) + fMultDiv2(alphar[1],ac.r12r);
+ tmp = -((-ac.r01r) >> (LPC_SCALE_FACTOR + 1)) +
+ fMultDiv2(alphar[1], ac.r12r);
}
absTmp = fixp_abs(tmp);
@@ -490,111 +561,108 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp
Quick check: is first filter coeff >= 1(4)
*/
- if (absTmp >= (ac.r11r>>1)) {
- resetLPCCoeffs=1;
- }
- else {
+ if (absTmp >= (ac.r11r >> 1)) {
+ resetLPCCoeffs = 1;
+ } else {
INT scale;
FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
- alphar[0] = FX_DBL2FX_SGL(scaleValue(result,scale+1));
+ alphar[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1));
- if((tmp>FL2FX_DBL(0.0f)) ^ (ac.r11r<FL2FX_DBL(0.0f)))
+ if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))
alphar[0] = -alphar[0];
}
- if (!useLP)
- {
- tmp = (ac.r01i>>(LPC_SCALE_FACTOR+1)) +
- (fMultDiv2(alphai[1],ac.r12r) - fMultDiv2(alphar[1],ac.r12i));
+ if (!useLP) {
+ tmp = (ac.r01i >> (LPC_SCALE_FACTOR + 1)) +
+ (fMultDiv2(alphai[1], ac.r12r) - fMultDiv2(alphar[1], ac.r12i));
absTmp = fixp_abs(tmp);
/*
Quick check: is second filter coeff >= 1(4)
*/
- if (absTmp >= (ac.r11r>>1)) {
- resetLPCCoeffs=1;
- }
- else {
+ if (absTmp >= (ac.r11r >> 1)) {
+ resetLPCCoeffs = 1;
+ } else {
INT scale;
FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
- alphai[0] = FX_DBL2FX_SGL(scaleValue(result,scale+1));
- if((tmp>FL2FX_DBL(0.0f)) ^ (ac.r11r<FL2FX_DBL(0.0f)))
+ alphai[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1));
+ if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))
alphai[0] = -alphai[0];
}
}
}
-
- if (!useLP)
- {
+ if (!useLP) {
/* Now check the quadratic criteria */
- if( (fMultDiv2(alphar[0],alphar[0]) + fMultDiv2(alphai[0],alphai[0])) >= FL2FXCONST_DBL(0.5f) )
- resetLPCCoeffs=1;
- if( (fMultDiv2(alphar[1],alphar[1]) + fMultDiv2(alphai[1],alphai[1])) >= FL2FXCONST_DBL(0.5f) )
- resetLPCCoeffs=1;
+ if ((fMultDiv2(alphar[0], alphar[0]) + fMultDiv2(alphai[0], alphai[0])) >=
+ FL2FXCONST_DBL(0.5f))
+ resetLPCCoeffs = 1;
+ if ((fMultDiv2(alphar[1], alphar[1]) + fMultDiv2(alphai[1], alphai[1])) >=
+ FL2FXCONST_DBL(0.5f))
+ resetLPCCoeffs = 1;
}
- if(resetLPCCoeffs){
+ if (resetLPCCoeffs) {
alphar[0] = FL2FXCONST_SGL(0.0f);
alphar[1] = FL2FXCONST_SGL(0.0f);
- if (!useLP)
- {
+ if (!useLP) {
alphai[0] = FL2FXCONST_SGL(0.0f);
alphai[1] = FL2FXCONST_SGL(0.0f);
}
}
- if (useLP)
- {
-
+ if (useLP) {
/* Aliasing detection */
- if(ac.r11r==FL2FXCONST_DBL(0.0f)) {
+ if (ac.r11r == FL2FXCONST_DBL(0.0f)) {
k1 = FL2FXCONST_DBL(0.0f);
- }
- else {
- if ( fixp_abs(ac.r01r) >= fixp_abs(ac.r11r) ) {
- if ( fMultDiv2(ac.r01r,ac.r11r) < FL2FX_DBL(0.0f)) {
+ } else {
+ if (fixp_abs(ac.r01r) >= fixp_abs(ac.r11r)) {
+ if (fMultDiv2(ac.r01r, ac.r11r) < FL2FX_DBL(0.0f)) {
k1 = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_SGL(1.0f)*/;
- }else {
- /* Since this value is squared later, it must not ever become -1.0f. */
- k1 = (FIXP_DBL)(MINVAL_DBL+1) /*FL2FXCONST_SGL(-1.0f)*/;
+ } else {
+ /* Since this value is squared later, it must not ever become -1.0f.
+ */
+ k1 = (FIXP_DBL)(MINVAL_DBL + 1) /*FL2FXCONST_SGL(-1.0f)*/;
}
- }
- else {
+ } else {
INT scale;
- FIXP_DBL result = fDivNorm(fixp_abs(ac.r01r), fixp_abs(ac.r11r), &scale);
- k1 = scaleValue(result,scale);
+ FIXP_DBL result =
+ fDivNorm(fixp_abs(ac.r01r), fixp_abs(ac.r11r), &scale);
+ k1 = scaleValue(result, scale);
- if(!((ac.r01r<FL2FX_DBL(0.0f)) ^ (ac.r11r<FL2FX_DBL(0.0f)))) {
+ if (!((ac.r01r < FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))) {
k1 = -k1;
}
}
}
- if(loBand > 1){
+ if ((loBand > 1) && (loBand < v_k_master0)) {
/* Check if the gain should be locked */
- FIXP_DBL deg = /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - fPow2(k1_below);
+ FIXP_DBL deg =
+ /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - fPow2(k1_below);
degreeAlias[loBand] = FL2FXCONST_DBL(0.0f);
- if (((loBand & 1) == 0) && (k1 < FL2FXCONST_DBL(0.0f))){
- if (k1_below < FL2FXCONST_DBL(0.0f)) { /* 2-Ch Aliasing Detection */
+ if (((loBand & 1) == 0) && (k1 < FL2FXCONST_DBL(0.0f))) {
+ if (k1_below < FL2FXCONST_DBL(0.0f)) { /* 2-Ch Aliasing Detection */
degreeAlias[loBand] = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/;
- if ( k1_below2 > FL2FXCONST_DBL(0.0f) ) { /* 3-Ch Aliasing Detection */
- degreeAlias[loBand-1] = deg;
+ if (k1_below2 >
+ FL2FXCONST_DBL(0.0f)) { /* 3-Ch Aliasing Detection */
+ degreeAlias[loBand - 1] = deg;
}
- }
- else if ( k1_below2 > FL2FXCONST_DBL(0.0f) ) { /* 3-Ch Aliasing Detection */
- degreeAlias[loBand] = deg;
+ } else if (k1_below2 >
+ FL2FXCONST_DBL(0.0f)) { /* 3-Ch Aliasing Detection */
+ degreeAlias[loBand] = deg;
}
}
- if (((loBand & 1) == 1) && (k1 > FL2FXCONST_DBL(0.0f))){
- if (k1_below > FL2FXCONST_DBL(0.0f)) { /* 2-CH Aliasing Detection */
+ if (((loBand & 1) == 1) && (k1 > FL2FXCONST_DBL(0.0f))) {
+ if (k1_below > FL2FXCONST_DBL(0.0f)) { /* 2-CH Aliasing Detection */
degreeAlias[loBand] = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/;
- if ( k1_below2 < FL2FXCONST_DBL(0.0f) ) { /* 3-CH Aliasing Detection */
- degreeAlias[loBand-1] = deg;
+ if (k1_below2 <
+ FL2FXCONST_DBL(0.0f)) { /* 3-CH Aliasing Detection */
+ degreeAlias[loBand - 1] = deg;
}
- }
- else if ( k1_below2 < FL2FXCONST_DBL(0.0f) ) { /* 3-CH Aliasing Detection */
- degreeAlias[loBand] = deg;
+ } else if (k1_below2 <
+ FL2FXCONST_DBL(0.0f)) { /* 3-CH Aliasing Detection */
+ degreeAlias[loBand] = deg;
}
}
}
@@ -605,23 +673,25 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp
patch = 0;
- while ( patch < pSettings->noOfPatches ) { /* inner loop over every patch */
+ while (patch < pSettings->noOfPatches) { /* inner loop over every patch */
int hiBand = loBand + patchParam[patch].targetBandOffs;
- if ( loBand < patchParam[patch].sourceStartBand
- || loBand >= patchParam[patch].sourceStopBand
- //|| hiBand >= hLppTrans->pSettings->noChannels
- ) {
+ if (loBand < patchParam[patch].sourceStartBand ||
+ loBand >= patchParam[patch].sourceStopBand
+ //|| hiBand >= hLppTrans->pSettings->noChannels
+ ) {
/* Lowband not in current patch - proceed */
patch++;
continue;
}
- FDK_ASSERT( hiBand < (64) );
+ FDK_ASSERT(hiBand < (64));
- /* bwIndex[patch] is already initialized with value from previous band inside this patch */
- while (hiBand >= pSettings->bwBorders[bwIndex[patch]] && bwIndex[patch] < MAX_NUM_PATCHES-1) {
+ /* bwIndex[patch] is already initialized with value from previous band
+ * inside this patch */
+ while (hiBand >= pSettings->bwBorders[bwIndex[patch]] &&
+ bwIndex[patch] < MAX_NUM_PATCHES - 1) {
bwIndex[patch]++;
}
@@ -631,121 +701,498 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp
*/
bw = FX_DBL2FX_SGL(bwVector[bwIndex[patch]]);
- a0r = FX_DBL2FX_SGL(fMult(bw,alphar[0])); /* Apply current bandwidth expansion factor */
-
-
- if (!useLP)
- a0i = FX_DBL2FX_SGL(fMult(bw,alphai[0]));
- bw = FX_DBL2FX_SGL(fPow2(bw));
- a1r = FX_DBL2FX_SGL(fMult(bw,alphar[1]));
- if (!useLP)
- a1i = FX_DBL2FX_SGL(fMult(bw,alphai[1]));
-
+ a0r = FX_DBL2FX_SGL(
+ fMult(bw, alphar[0])); /* Apply current bandwidth expansion factor */
+ if (!useLP) a0i = FX_DBL2FX_SGL(fMult(bw, alphai[0]));
+ bw = FX_DBL2FX_SGL(fPow2(bw));
+ a1r = FX_DBL2FX_SGL(fMult(bw, alphar[1]));
+ if (!useLP) a1i = FX_DBL2FX_SGL(fMult(bw, alphai[1]));
/*
Filter Step 3: insert the middle part which won't be windowed
*/
-
- if ( bw <= FL2FXCONST_SGL(0.0f) ) {
+ if (bw <= FL2FXCONST_SGL(0.0f)) {
if (!useLP) {
- int descale = fixMin(DFRACT_BITS-1, (LPC_SCALE_FACTOR+dynamicScale));
- for(i = startSample; i < stopSample; i++ ) {
- qmfBufferReal[i][hiBand] = lowBandReal[LPC_ORDER+i]>>descale;
- qmfBufferImag[i][hiBand] = lowBandImag[LPC_ORDER+i]>>descale;
+ int descale =
+ fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale));
+ for (i = startSample; i < stopSample; i++) {
+ FIXP_DBL accu1, accu2;
+ accu1 = lowBandReal[LPC_ORDER + i] >> descale;
+ accu2 = lowBandImag[LPC_ORDER + i] >> descale;
+ if (fPreWhitening) {
+ accu1 = scaleValueSaturate(
+ fMultDiv2(accu1, preWhiteningGains[loBand]),
+ preWhiteningGains_exp[loBand] + 1);
+ accu2 = scaleValueSaturate(
+ fMultDiv2(accu2, preWhiteningGains[loBand]),
+ preWhiteningGains_exp[loBand] + 1);
+ }
+ qmfBufferReal[i][hiBand] = accu1;
+ qmfBufferImag[i][hiBand] = accu2;
}
- } else
- {
- int descale = fixMin(DFRACT_BITS-1, (LPC_SCALE_FACTOR+dynamicScale));
- for(i = startSample; i < stopSample; i++ ) {
- qmfBufferReal[i][hiBand] = lowBandReal[LPC_ORDER+i]>>descale;
+ } else {
+ int descale =
+ fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale));
+ for (i = startSample; i < stopSample; i++) {
+ qmfBufferReal[i][hiBand] = lowBandReal[LPC_ORDER + i] >> descale;
}
}
- }
- else { /* bw <= 0 */
+ } else { /* bw <= 0 */
if (!useLP) {
- int descale = fixMin(DFRACT_BITS-1, (LPC_SCALE_FACTOR+dynamicScale));
+ int descale =
+ fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale));
#ifdef FUNCTION_LPPTRANSPOSER_func1
- lppTransposer_func1(lowBandReal+LPC_ORDER+startSample,lowBandImag+LPC_ORDER+startSample,
- qmfBufferReal+startSample,qmfBufferImag+startSample,
- stopSample-startSample, (int) hiBand,
- dynamicScale,descale,
- a0r, a0i, a1r, a1i);
+ lppTransposer_func1(
+ lowBandReal + LPC_ORDER + startSample,
+ lowBandImag + LPC_ORDER + startSample,
+ qmfBufferReal + startSample, qmfBufferImag + startSample,
+ stopSample - startSample, (int)hiBand, dynamicScale, descale, a0r,
+ a0i, a1r, a1i, fPreWhitening, preWhiteningGains[loBand],
+ preWhiteningGains_exp[loBand] + 1);
#else
- for(i = startSample; i < stopSample; i++ ) {
+ for (i = startSample; i < stopSample; i++) {
FIXP_DBL accu1, accu2;
- accu1 = (fMultDiv2(a0r,lowBandReal[LPC_ORDER+i-1]) - fMultDiv2(a0i,lowBandImag[LPC_ORDER+i-1]) +
- fMultDiv2(a1r,lowBandReal[LPC_ORDER+i-2]) - fMultDiv2(a1i,lowBandImag[LPC_ORDER+i-2]))>>dynamicScale;
- accu2 = (fMultDiv2(a0i,lowBandReal[LPC_ORDER+i-1]) + fMultDiv2(a0r,lowBandImag[LPC_ORDER+i-1]) +
- fMultDiv2(a1i,lowBandReal[LPC_ORDER+i-2]) + fMultDiv2(a1r,lowBandImag[LPC_ORDER+i-2]))>>dynamicScale;
-
- qmfBufferReal[i][hiBand] = (lowBandReal[LPC_ORDER+i]>>descale) + (accu1<<1);
- qmfBufferImag[i][hiBand] = (lowBandImag[LPC_ORDER+i]>>descale) + (accu2<<1);
+ accu1 = (fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) -
+ fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1]) +
+ fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) -
+ fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >>
+ dynamicScale;
+ accu2 = (fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) +
+ fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1]) +
+ fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) +
+ fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >>
+ dynamicScale;
+
+ accu1 = (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 << 1);
+ accu2 = (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 << 1);
+ if (fPreWhitening) {
+ accu1 = scaleValueSaturate(
+ fMultDiv2(accu1, preWhiteningGains[loBand]),
+ preWhiteningGains_exp[loBand] + 1);
+ accu2 = scaleValueSaturate(
+ fMultDiv2(accu2, preWhiteningGains[loBand]),
+ preWhiteningGains_exp[loBand] + 1);
+ }
+ qmfBufferReal[i][hiBand] = accu1;
+ qmfBufferImag[i][hiBand] = accu2;
}
#endif
- } else
- {
- int descale = fixMin(DFRACT_BITS-1, (LPC_SCALE_FACTOR+dynamicScale));
-
+ } else {
FDK_ASSERT(dynamicScale >= 0);
- for(i = startSample; i < stopSample; i++ ) {
- FIXP_DBL accu1;
-
- accu1 = (fMultDiv2(a0r,lowBandReal[LPC_ORDER+i-1]) + fMultDiv2(a1r,lowBandReal[LPC_ORDER+i-2]))>>dynamicScale;
-
- qmfBufferReal[i][hiBand] = (lowBandReal[LPC_ORDER+i]>>descale) + (accu1<<1);
- }
+ calc_qmfBufferReal(
+ qmfBufferReal, &(lowBandReal[LPC_ORDER + startSample - 2]),
+ startSample, stopSample, hiBand, dynamicScale,
+ fMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)), a0r,
+ a1r);
}
} /* bw <= 0 */
patch++;
- } /* inner loop over patches */
+ } /* inner loop over patches */
- /*
+ /*
* store the unmodified filter coefficients if there is
* an overlapping envelope
*****************************************************************/
+ } /* outer loop over bands (loBand) */
- } /* outer loop over bands (loBand) */
-
- if (useLP)
- {
- for ( loBand = pSettings->lbStartPatching; loBand < pSettings->lbStopPatching; loBand++ ) {
+ if (useLP) {
+ for (loBand = pSettings->lbStartPatching;
+ loBand < pSettings->lbStopPatching; loBand++) {
patch = 0;
- while ( patch < pSettings->noOfPatches ) {
-
+ while (patch < pSettings->noOfPatches) {
UCHAR hiBand = loBand + patchParam[patch].targetBandOffs;
- if ( loBand < patchParam[patch].sourceStartBand
- || loBand >= patchParam[patch].sourceStopBand
- || hiBand >= (64) /* Highband out of range (biterror) */
- ) {
- /* Lowband not in current patch or highband out of range (might be caused by biterrors)- proceed */
+ if (loBand < patchParam[patch].sourceStartBand ||
+ loBand >= patchParam[patch].sourceStopBand ||
+ hiBand >= (64) /* Highband out of range (biterror) */
+ ) {
+ /* Lowband not in current patch or highband out of range (might be
+ * caused by biterrors)- proceed */
patch++;
continue;
}
- if(hiBand != patchParam[patch].targetStartBand)
+ if (hiBand != patchParam[patch].targetStartBand)
degreeAlias[hiBand] = degreeAlias[loBand];
patch++;
}
- }/* end for loop */
+ } /* end for loop */
}
- for (i = 0; i < nInvfBands; i++ ) {
- hLppTrans->bwVectorOld[i] = bwVector[i];
- }
+ for (i = 0; i < nInvfBands; i++) {
+ hLppTrans->bwVectorOld[i] = bwVector[i];
+ }
/*
set high band scale factor
*/
- sbrScaleFactor->hb_scale = comLowBandScale-(LPC_SCALE_FACTOR);
+ sbrScaleFactor->hb_scale = comLowBandScale - (LPC_SCALE_FACTOR);
+}
+
+void lppTransposerHBE(
+ HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */
+ HANDLE_HBE_TRANSPOSER hQmfTransposer,
+ QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */
+ FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband
+ samples (source) */
+ FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of
+ subband samples (source) */
+ const int timeStep, /*!< Time step of envelope */
+ const int firstSlotOffs, /*!< Start position in time */
+ const int lastSlotOffs, /*!< Number of overlap-slots into next frame */
+ const int nInvfBands, /*!< Number of bands for inverse filtering */
+ INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */
+ INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */
+) {
+ INT bwIndex;
+ FIXP_DBL bwVector[MAX_NUM_PATCHES_HBE]; /*!< pole moving factors */
+
+ int i;
+ int loBand, start, stop;
+ TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings;
+ PATCH_PARAM *patchParam = pSettings->patchParam;
+
+ FIXP_SGL alphar[LPC_ORDER], a0r, a1r;
+ FIXP_SGL alphai[LPC_ORDER], a0i = 0, a1i = 0;
+ FIXP_SGL bw = FL2FXCONST_SGL(0.0f);
+
+ int autoCorrLength;
+
+ ACORR_COEFS ac;
+ int startSample;
+ int stopSample;
+ int stopSampleClear;
+
+ int comBandScale;
+ int ovLowBandShift;
+ int lowBandShift;
+ /* int ovHighBandShift;*/
+ int targetStopBand;
+
+ alphai[0] = FL2FXCONST_SGL(0.0f);
+ alphai[1] = FL2FXCONST_SGL(0.0f);
+
+ startSample = firstSlotOffs * timeStep;
+ stopSample = pSettings->nCols + lastSlotOffs * timeStep;
+
+ inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode,
+ sbr_invf_mode_prev, bwVector);
+
+ stopSampleClear = stopSample;
+
+ autoCorrLength = pSettings->nCols + pSettings->overlap;
+
+ /* Set upper subbands to zero:
+ This is required in case that the patches do not cover the complete
+ highband (because the last patch would be too short). Possible
+ optimization: Clearing bands up to usb would be sufficient here. */
+ targetStopBand = patchParam[pSettings->noOfPatches - 1].targetStartBand +
+ patchParam[pSettings->noOfPatches - 1].numBandsInPatch;
+
+ int memSize = ((64) - targetStopBand) * sizeof(FIXP_DBL);
+
+ for (i = startSample; i < stopSampleClear; i++) {
+ FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize);
+ FDKmemclear(&qmfBufferImag[i][targetStopBand], memSize);
+ }
+
+ /*
+ Calc common low band scale factor
+ */
+ comBandScale = sbrScaleFactor->hb_scale;
+
+ ovLowBandShift = sbrScaleFactor->hb_scale - comBandScale;
+ lowBandShift = sbrScaleFactor->hb_scale - comBandScale;
+ /* ovHighBandShift = firstSlotOffs == 0 ? ovLowBandShift:0;*/
+
+ /* outer loop over bands to do analysis only once for each band */
+
+ start = hQmfTransposer->startBand;
+ stop = hQmfTransposer->stopBand;
+
+ for (loBand = start; loBand < stop; loBand++) {
+ bwIndex = 0;
+
+ FIXP_DBL lowBandReal[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER];
+ FIXP_DBL lowBandImag[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER];
+
+ int resetLPCCoeffs = 0;
+ int dynamicScale = DFRACT_BITS - 1 - LPC_SCALE_FACTOR;
+ int acDetScale = 0; /* scaling of autocorrelation determinant */
+
+ for (i = 0; i < LPC_ORDER; i++) {
+ lowBandReal[i] = hLppTrans->lpcFilterStatesRealHBE[i][loBand];
+ lowBandImag[i] = hLppTrans->lpcFilterStatesImagHBE[i][loBand];
+ }
+
+ for (; i < LPC_ORDER + firstSlotOffs * timeStep; i++) {
+ lowBandReal[i] = hLppTrans->lpcFilterStatesRealHBE[i][loBand];
+ lowBandImag[i] = hLppTrans->lpcFilterStatesImagHBE[i][loBand];
+ }
+
+ /*
+ Take old slope length qmf slot source values out of (overlap)qmf buffer
+ */
+ for (i = firstSlotOffs * timeStep;
+ i < pSettings->nCols + pSettings->overlap; i++) {
+ lowBandReal[i + LPC_ORDER] = qmfBufferReal[i][loBand];
+ lowBandImag[i + LPC_ORDER] = qmfBufferImag[i][loBand];
+ }
+
+ /* store unmodified values to buffer */
+ for (i = 0; i < LPC_ORDER + pSettings->overlap; i++) {
+ hLppTrans->lpcFilterStatesRealHBE[i][loBand] =
+ qmfBufferReal[pSettings->nCols - LPC_ORDER + i][loBand];
+ hLppTrans->lpcFilterStatesImagHBE[i][loBand] =
+ qmfBufferImag[pSettings->nCols - LPC_ORDER + i][loBand];
+ }
+
+ /*
+ Determine dynamic scaling value.
+ */
+ dynamicScale =
+ fixMin(dynamicScale,
+ getScalefactor(lowBandReal, LPC_ORDER + pSettings->overlap) +
+ ovLowBandShift);
+ dynamicScale =
+ fixMin(dynamicScale,
+ getScalefactor(&lowBandReal[LPC_ORDER + pSettings->overlap],
+ pSettings->nCols) +
+ lowBandShift);
+ dynamicScale =
+ fixMin(dynamicScale,
+ getScalefactor(lowBandImag, LPC_ORDER + pSettings->overlap) +
+ ovLowBandShift);
+ dynamicScale =
+ fixMin(dynamicScale,
+ getScalefactor(&lowBandImag[LPC_ORDER + pSettings->overlap],
+ pSettings->nCols) +
+ lowBandShift);
+
+ dynamicScale = fixMax(
+ 0, dynamicScale - 1); /* one additional bit headroom to prevent -1.0 */
+
+ /*
+ Scale temporal QMF buffer.
+ */
+ scaleValues(&lowBandReal[0], LPC_ORDER + pSettings->overlap,
+ dynamicScale - ovLowBandShift);
+ scaleValues(&lowBandReal[LPC_ORDER + pSettings->overlap], pSettings->nCols,
+ dynamicScale - lowBandShift);
+ scaleValues(&lowBandImag[0], LPC_ORDER + pSettings->overlap,
+ dynamicScale - ovLowBandShift);
+ scaleValues(&lowBandImag[LPC_ORDER + pSettings->overlap], pSettings->nCols,
+ dynamicScale - lowBandShift);
+
+ acDetScale += autoCorr2nd_cplx(&ac, lowBandReal + LPC_ORDER,
+ lowBandImag + LPC_ORDER, autoCorrLength);
+
+ /* Examine dynamic of determinant in autocorrelation. */
+ acDetScale += 2 * (comBandScale + dynamicScale);
+ acDetScale *= 2; /* two times reflection coefficent scaling */
+ acDetScale += ac.det_scale; /* ac scaling of determinant */
+
+ /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */
+ if (acDetScale > 126) {
+ resetLPCCoeffs = 1;
+ }
+
+ alphar[1] = FL2FXCONST_SGL(0.0f);
+ alphai[1] = FL2FXCONST_SGL(0.0f);
+
+ if (ac.det != FL2FXCONST_DBL(0.0f)) {
+ FIXP_DBL tmp, absTmp, absDet;
+
+ absDet = fixp_abs(ac.det);
+
+ tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) -
+ ((fMultDiv2(ac.r01i, ac.r12i) + fMultDiv2(ac.r02r, ac.r11r)) >>
+ (LPC_SCALE_FACTOR - 1));
+ absTmp = fixp_abs(tmp);
+
+ /*
+ Quick check: is first filter coeff >= 1(4)
+ */
+ {
+ INT scale;
+ FIXP_DBL result = fDivNorm(absTmp, absDet, &scale);
+ scale = scale + ac.det_scale;
+
+ if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) {
+ resetLPCCoeffs = 1;
+ } else {
+ alphar[1] = FX_DBL2FX_SGL(scaleValue(result, scale));
+ if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
+ alphar[1] = -alphar[1];
+ }
+ }
+ }
+
+ tmp = (fMultDiv2(ac.r01i, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) +
+ ((fMultDiv2(ac.r01r, ac.r12i) -
+ (FIXP_DBL)fMultDiv2(ac.r02i, ac.r11r)) >>
+ (LPC_SCALE_FACTOR - 1));
+
+ absTmp = fixp_abs(tmp);
+
+ /*
+ Quick check: is second filter coeff >= 1(4)
+ */
+ {
+ INT scale;
+ FIXP_DBL result = fDivNorm(absTmp, absDet, &scale);
+ scale = scale + ac.det_scale;
+
+ if ((scale > 0) &&
+ (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL >> scale)) {
+ resetLPCCoeffs = 1;
+ } else {
+ alphai[1] = FX_DBL2FX_SGL(scaleValue(result, scale));
+ if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
+ alphai[1] = -alphai[1];
+ }
+ }
+ }
+ }
+
+ alphar[0] = FL2FXCONST_SGL(0.0f);
+ alphai[0] = FL2FXCONST_SGL(0.0f);
+
+ if (ac.r11r != FL2FXCONST_DBL(0.0f)) {
+ /* ac.r11r is always >=0 */
+ FIXP_DBL tmp, absTmp;
+
+ tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) +
+ (fMultDiv2(alphar[1], ac.r12r) + fMultDiv2(alphai[1], ac.r12i));
+
+ absTmp = fixp_abs(tmp);
+
+ /*
+ Quick check: is first filter coeff >= 1(4)
+ */
+
+ if (absTmp >= (ac.r11r >> 1)) {
+ resetLPCCoeffs = 1;
+ } else {
+ INT scale;
+ FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
+ alphar[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1));
+
+ if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))
+ alphar[0] = -alphar[0];
+ }
+
+ tmp = (ac.r01i >> (LPC_SCALE_FACTOR + 1)) +
+ (fMultDiv2(alphai[1], ac.r12r) - fMultDiv2(alphar[1], ac.r12i));
+
+ absTmp = fixp_abs(tmp);
+
+ /*
+ Quick check: is second filter coeff >= 1(4)
+ */
+ if (absTmp >= (ac.r11r >> 1)) {
+ resetLPCCoeffs = 1;
+ } else {
+ INT scale;
+ FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
+ alphai[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1));
+ if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) {
+ alphai[0] = -alphai[0];
+ }
+ }
+ }
+ /* Now check the quadratic criteria */
+ if ((fMultDiv2(alphar[0], alphar[0]) + fMultDiv2(alphai[0], alphai[0])) >=
+ FL2FXCONST_DBL(0.5f)) {
+ resetLPCCoeffs = 1;
+ }
+ if ((fMultDiv2(alphar[1], alphar[1]) + fMultDiv2(alphai[1], alphai[1])) >=
+ FL2FXCONST_DBL(0.5f)) {
+ resetLPCCoeffs = 1;
+ }
+
+ if (resetLPCCoeffs) {
+ alphar[0] = FL2FXCONST_SGL(0.0f);
+ alphar[1] = FL2FXCONST_SGL(0.0f);
+ alphai[0] = FL2FXCONST_SGL(0.0f);
+ alphai[1] = FL2FXCONST_SGL(0.0f);
+ }
+
+ while (bwIndex < MAX_NUM_PATCHES - 1 &&
+ loBand >= pSettings->bwBorders[bwIndex]) {
+ bwIndex++;
+ }
+
+ /*
+ Filter Step 2: add the left slope with the current filter to the buffer
+ pure source values are already in there
+ */
+ bw = FX_DBL2FX_SGL(bwVector[bwIndex]);
+
+ a0r = FX_DBL2FX_SGL(
+ fMult(bw, alphar[0])); /* Apply current bandwidth expansion factor */
+ a0i = FX_DBL2FX_SGL(fMult(bw, alphai[0]));
+ bw = FX_DBL2FX_SGL(fPow2(bw));
+ a1r = FX_DBL2FX_SGL(fMult(bw, alphar[1]));
+ a1i = FX_DBL2FX_SGL(fMult(bw, alphai[1]));
+
+ /*
+ Filter Step 3: insert the middle part which won't be windowed
+ */
+ if (bw <= FL2FXCONST_SGL(0.0f)) {
+ int descale = fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale));
+ for (i = startSample; i < stopSample; i++) {
+ qmfBufferReal[i][loBand] = lowBandReal[LPC_ORDER + i] >> descale;
+ qmfBufferImag[i][loBand] = lowBandImag[LPC_ORDER + i] >> descale;
+ }
+ } else { /* bw <= 0 */
+
+ int descale = fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale));
+
+ for (i = startSample; i < stopSample; i++) {
+ FIXP_DBL accu1, accu2;
+
+ accu1 = (fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) -
+ fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1]) +
+ fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) -
+ fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >>
+ dynamicScale;
+ accu2 = (fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) +
+ fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1]) +
+ fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) +
+ fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >>
+ dynamicScale;
+
+ qmfBufferReal[i][loBand] =
+ (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 << 1);
+ qmfBufferImag[i][loBand] =
+ (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 << 1);
+ }
+ } /* bw <= 0 */
+
+ /*
+ * store the unmodified filter coefficients if there is
+ * an overlapping envelope
+ *****************************************************************/
+
+ } /* outer loop over bands (loBand) */
+
+ for (i = 0; i < nInvfBands; i++) {
+ hLppTrans->bwVectorOld[i] = bwVector[i];
+ }
+
+ /*
+ set high band scale factor
+ */
+ sbrScaleFactor->hb_scale = comBandScale - (LPC_SCALE_FACTOR);
}
/*!
@@ -755,21 +1202,20 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp
*
*/
SBR_ERROR
-createLppTransposer (HANDLE_SBR_LPP_TRANS hs, /*!< Handle of low power transposer */
- TRANSPOSER_SETTINGS *pSettings, /*!< Pointer to settings */
- const int highBandStartSb, /*!< ? */
- UCHAR *v_k_master, /*!< Master table */
- const int numMaster, /*!< Valid entries in master table */
- const int usb, /*!< Highband area stop subband */
- const int timeSlots, /*!< Number of time slots */
- const int nCols, /*!< Number of colums (codec qmf bank) */
- UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */
- const int noNoiseBands, /*!< Number of noise bands */
- UINT fs, /*!< Sample Frequency */
- const int chan, /*!< Channel number */
- const int overlap
- )
-{
+createLppTransposer(
+ HANDLE_SBR_LPP_TRANS hs, /*!< Handle of low power transposer */
+ TRANSPOSER_SETTINGS *pSettings, /*!< Pointer to settings */
+ const int highBandStartSb, /*!< ? */
+ UCHAR *v_k_master, /*!< Master table */
+ const int numMaster, /*!< Valid entries in master table */
+ const int usb, /*!< Highband area stop subband */
+ const int timeSlots, /*!< Number of time slots */
+ const int nCols, /*!< Number of colums (codec qmf bank) */
+ UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */
+ const int noNoiseBands, /*!< Number of noise bands */
+ UINT fs, /*!< Sample Frequency */
+ const int chan, /*!< Channel number */
+ const int overlap) {
/* FB inverse filtering settings */
hs->pSettings = pSettings;
@@ -777,50 +1223,40 @@ createLppTransposer (HANDLE_SBR_LPP_TRANS hs, /*!< Handle of low power transpose
pSettings->overlap = overlap;
switch (timeSlots) {
+ case 15:
+ case 16:
+ break;
- case 15:
- case 16:
- break;
-
- default:
- return SBRDEC_UNSUPPORTED_CONFIG; /* Unimplemented */
+ default:
+ return SBRDEC_UNSUPPORTED_CONFIG; /* Unimplemented */
}
- if (chan==0) {
+ if (chan == 0) {
/* Init common data only once */
hs->pSettings->nCols = nCols;
- return resetLppTransposer (hs,
- highBandStartSb,
- v_k_master,
- numMaster,
- noiseBandTable,
- noNoiseBands,
- usb,
- fs);
+ return resetLppTransposer(hs, highBandStartSb, v_k_master, numMaster,
+ noiseBandTable, noNoiseBands, usb, fs);
}
return SBRDEC_OK;
}
-
-static int findClosestEntry(UCHAR goalSb, UCHAR *v_k_master, UCHAR numMaster, UCHAR direction)
-{
+static int findClosestEntry(UCHAR goalSb, UCHAR *v_k_master, UCHAR numMaster,
+ UCHAR direction) {
int index;
- if( goalSb <= v_k_master[0] )
- return v_k_master[0];
+ if (goalSb <= v_k_master[0]) return v_k_master[0];
- if( goalSb >= v_k_master[numMaster] )
- return v_k_master[numMaster];
+ if (goalSb >= v_k_master[numMaster]) return v_k_master[numMaster];
- if(direction) {
+ if (direction) {
index = 0;
- while( v_k_master[index] < goalSb ) {
+ while (v_k_master[index] < goalSb) {
index++;
}
} else {
index = numMaster;
- while( v_k_master[index] > goalSb ) {
+ while (v_k_master[index] > goalSb) {
index--;
}
}
@@ -828,7 +1264,6 @@ static int findClosestEntry(UCHAR goalSb, UCHAR *v_k_master, UCHAR numMaster, UC
return v_k_master[index];
}
-
/*!
*
* \brief Reset memory for one lpp transposer instance
@@ -836,18 +1271,18 @@ static int findClosestEntry(UCHAR goalSb, UCHAR *v_k_master, UCHAR numMaster, UC
* \return SBRDEC_OK on success, SBRDEC_UNSUPPORTED_CONFIG on error
*/
SBR_ERROR
-resetLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */
- UCHAR highBandStartSb, /*!< High band area: start subband */
- UCHAR *v_k_master, /*!< Master table */
- UCHAR numMaster, /*!< Valid entries in master table */
- UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */
- UCHAR noNoiseBands, /*!< Number of noise bands */
- UCHAR usb, /*!< High band area: stop subband */
- UINT fs /*!< SBR output sampling frequency */
- )
-{
+resetLppTransposer(
+ HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */
+ UCHAR highBandStartSb, /*!< High band area: start subband */
+ UCHAR *v_k_master, /*!< Master table */
+ UCHAR numMaster, /*!< Valid entries in master table */
+ UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */
+ UCHAR noNoiseBands, /*!< Number of noise bands */
+ UCHAR usb, /*!< High band area: stop subband */
+ UINT fs /*!< SBR output sampling frequency */
+) {
TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings;
- PATCH_PARAM *patchParam = pSettings->patchParam;
+ PATCH_PARAM *patchParam = pSettings->patchParam;
int i, patch;
int targetStopBand;
@@ -855,43 +1290,52 @@ resetLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transpos
int patchDistance;
int numBandsInPatch;
- int lsb = v_k_master[0]; /* Start subband expressed in "non-critical" sampling terms*/
- int xoverOffset = highBandStartSb - lsb; /* Calculate distance in QMF bands between k0 and kx */
+ int lsb = v_k_master[0]; /* Start subband expressed in "non-critical" sampling
+ terms*/
+ int xoverOffset = highBandStartSb -
+ lsb; /* Calculate distance in QMF bands between k0 and kx */
int startFreqHz;
int desiredBorder;
- usb = fixMin(usb, v_k_master[numMaster]); /* Avoid endless loops (compare with float code). */
+ usb = fixMin(usb, v_k_master[numMaster]); /* Avoid endless loops (compare with
+ float code). */
/*
* Plausibility check
*/
- if ( lsb - SHIFT_START_SB < 4 ) {
+ if (pSettings->nCols == 64) {
+ if (lsb < 4) {
+ /* 4:1 SBR Requirement k0 >= 4 missed! */
+ return SBRDEC_UNSUPPORTED_CONFIG;
+ }
+ } else if (lsb - SHIFT_START_SB < 4) {
return SBRDEC_UNSUPPORTED_CONFIG;
}
-
/*
* Initialize the patching parameter
*/
/* ISO/IEC 14496-3 (Figure 4.48): goalSb = round( 2.048e6 / fs ) */
- desiredBorder = (((2048000*2) / fs) + 1) >> 1;
+ desiredBorder = (((2048000 * 2) / fs) + 1) >> 1;
- desiredBorder = findClosestEntry(desiredBorder, v_k_master, numMaster, 1); /* Adapt region to master-table */
+ desiredBorder = findClosestEntry(desiredBorder, v_k_master, numMaster,
+ 1); /* Adapt region to master-table */
/* First patch */
sourceStartBand = SHIFT_START_SB + xoverOffset;
targetStopBand = lsb + xoverOffset; /* upperBand */
- /* Even (odd) numbered channel must be patched to even (odd) numbered channel */
+ /* Even (odd) numbered channel must be patched to even (odd) numbered channel
+ */
patch = 0;
- while(targetStopBand < usb) {
-
+ while (targetStopBand < usb) {
/* Too many patches?
Allow MAX_NUM_PATCHES+1 patches here.
we need to check later again, since patch might be the highest patch
- AND contain less than 3 bands => actual number of patches will be reduced by 1.
+ AND contain less than 3 bands => actual number of patches will be reduced
+ by 1.
*/
if (patch > MAX_NUM_PATCHES) {
return SBRDEC_UNSUPPORTED_CONFIG;
@@ -900,26 +1344,42 @@ resetLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transpos
patchParam[patch].guardStartBand = targetStopBand;
patchParam[patch].targetStartBand = targetStopBand;
- numBandsInPatch = desiredBorder - targetStopBand; /* Get the desired range of the patch */
+ numBandsInPatch =
+ desiredBorder - targetStopBand; /* Get the desired range of the patch */
- if ( numBandsInPatch >= lsb - sourceStartBand ) {
+ if (numBandsInPatch >= lsb - sourceStartBand) {
/* Desired number bands are not available -> patch whole source range */
- patchDistance = targetStopBand - sourceStartBand; /* Get the targetOffset */
- patchDistance = patchDistance & ~1; /* Rounding off odd numbers and make all even */
- numBandsInPatch = lsb - (targetStopBand - patchDistance); /* Update number of bands to be patched */
- numBandsInPatch = findClosestEntry(targetStopBand + numBandsInPatch, v_k_master, numMaster, 0) -
- targetStopBand; /* Adapt region to master-table */
+ patchDistance =
+ targetStopBand - sourceStartBand; /* Get the targetOffset */
+ patchDistance =
+ patchDistance & ~1; /* Rounding off odd numbers and make all even */
+ numBandsInPatch =
+ lsb - (targetStopBand -
+ patchDistance); /* Update number of bands to be patched */
+ numBandsInPatch = findClosestEntry(targetStopBand + numBandsInPatch,
+ v_k_master, numMaster, 0) -
+ targetStopBand; /* Adapt region to master-table */
+ }
+
+ if (pSettings->nCols == 64) {
+ if (numBandsInPatch == 0 && sourceStartBand == SHIFT_START_SB) {
+ return SBRDEC_UNSUPPORTED_CONFIG;
+ }
}
- /* Desired number bands are available -> get the minimal even patching distance */
- patchDistance = numBandsInPatch + targetStopBand - lsb; /* Get minimal distance */
- patchDistance = (patchDistance + 1) & ~1; /* Rounding up odd numbers and make all even */
+ /* Desired number bands are available -> get the minimal even patching
+ * distance */
+ patchDistance =
+ numBandsInPatch + targetStopBand - lsb; /* Get minimal distance */
+ patchDistance = (patchDistance + 1) &
+ ~1; /* Rounding up odd numbers and make all even */
if (numBandsInPatch > 0) {
patchParam[patch].sourceStartBand = targetStopBand - patchDistance;
- patchParam[patch].targetBandOffs = patchDistance;
+ patchParam[patch].targetBandOffs = patchDistance;
patchParam[patch].numBandsInPatch = numBandsInPatch;
- patchParam[patch].sourceStopBand = patchParam[patch].sourceStartBand + numBandsInPatch;
+ patchParam[patch].sourceStopBand =
+ patchParam[patch].sourceStartBand + numBandsInPatch;
targetStopBand += patchParam[patch].numBandsInPatch;
patch++;
@@ -929,19 +1389,19 @@ resetLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transpos
sourceStartBand = SHIFT_START_SB;
/* Check if we are close to desiredBorder */
- if( desiredBorder - targetStopBand < 3) /* MPEG doc */
+ if (desiredBorder - targetStopBand < 3) /* MPEG doc */
{
desiredBorder = usb;
}
-
}
patch--;
/* If highest patch contains less than three subband: skip it */
- if ( (patch>0) && (patchParam[patch].numBandsInPatch < 3) ) {
+ if ((patch > 0) && (patchParam[patch].numBandsInPatch < 3)) {
patch--;
- targetStopBand = patchParam[patch].targetStartBand + patchParam[patch].numBandsInPatch;
+ targetStopBand =
+ patchParam[patch].targetStartBand + patchParam[patch].numBandsInPatch;
}
/* now check if we don't have one too many */
@@ -953,35 +1413,36 @@ resetLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transpos
/* Check lowest and highest source subband */
pSettings->lbStartPatching = targetStopBand;
- pSettings->lbStopPatching = 0;
- for ( patch = 0; patch < pSettings->noOfPatches; patch++ ) {
- pSettings->lbStartPatching = fixMin( pSettings->lbStartPatching, patchParam[patch].sourceStartBand );
- pSettings->lbStopPatching = fixMax( pSettings->lbStopPatching, patchParam[patch].sourceStopBand );
+ pSettings->lbStopPatching = 0;
+ for (patch = 0; patch < pSettings->noOfPatches; patch++) {
+ pSettings->lbStartPatching =
+ fixMin(pSettings->lbStartPatching, patchParam[patch].sourceStartBand);
+ pSettings->lbStopPatching =
+ fixMax(pSettings->lbStopPatching, patchParam[patch].sourceStopBand);
}
- for(i = 0 ; i < noNoiseBands; i++){
- pSettings->bwBorders[i] = noiseBandTable[i+1];
+ for (i = 0; i < noNoiseBands; i++) {
+ pSettings->bwBorders[i] = noiseBandTable[i + 1];
}
- for (;i < MAX_NUM_NOISE_VALUES; i++) {
+ for (; i < MAX_NUM_NOISE_VALUES; i++) {
pSettings->bwBorders[i] = 255;
}
-
/*
* Choose whitening factors
*/
- startFreqHz = ( (lsb + xoverOffset)*fs ) >> 7; /* Shift does a division by 2*(64) */
+ startFreqHz =
+ ((lsb + xoverOffset) * fs) >> 7; /* Shift does a division by 2*(64) */
- for( i = 1; i < NUM_WHFACTOR_TABLE_ENTRIES; i++ )
- {
- if( startFreqHz < FDK_sbrDecoder_sbr_whFactorsIndex[i])
- break;
+ for (i = 1; i < NUM_WHFACTOR_TABLE_ENTRIES; i++) {
+ if (startFreqHz < FDK_sbrDecoder_sbr_whFactorsIndex[i]) break;
}
i--;
pSettings->whFactors.off = FDK_sbrDecoder_sbr_whFactorsTable[i][0];
- pSettings->whFactors.transitionLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][1];
+ pSettings->whFactors.transitionLevel =
+ FDK_sbrDecoder_sbr_whFactorsTable[i][1];
pSettings->whFactors.lowLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][2];
pSettings->whFactors.midLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][3];
pSettings->whFactors.highLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][4];