summaryrefslogtreecommitdiffstats
path: root/libFDK/src/qmf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libFDK/src/qmf.cpp')
-rw-r--r--libFDK/src/qmf.cpp1196
1 files changed, 0 insertions, 1196 deletions
diff --git a/libFDK/src/qmf.cpp b/libFDK/src/qmf.cpp
deleted file mode 100644
index 54526dd..0000000
--- a/libFDK/src/qmf.cpp
+++ /dev/null
@@ -1,1196 +0,0 @@
-
-/* -----------------------------------------------------------------------------------------------------------
-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.
-
- 1. INTRODUCTION
-The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
-the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
-This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
-
-AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
-audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
-independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
-of the MPEG specifications.
-
-Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
-may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
-individually for the purpose of encoding or decoding bit streams in products that are compliant with
-the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
-these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
-software may already be covered under those patent licenses when it is used for those licensed purposes only.
-
-Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
-are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
-applications information and documentation.
-
-2. COPYRIGHT LICENSE
-
-Redistribution and use in source and binary forms, with or without modification, are permitted without
-payment of copyright license fees provided that you satisfy the following conditions:
-
-You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
-your modifications thereto in source code form.
-
-You must retain the complete text of this software license in the documentation and/or other materials
-provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
-You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
-modifications thereto to recipients of copies in binary form.
-
-The name of Fraunhofer may not be used to endorse or promote products derived from this library without
-prior written permission.
-
-You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
-software or your modifications thereto.
-
-Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
-and the date of any change. For modified versions of the FDK AAC Codec, the term
-"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
-"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
-
-3. NO PATENT LICENSE
-
-NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
-ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
-respect to this software.
-
-You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
-by appropriate patent licenses.
-
-4. DISCLAIMER
-
-This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
-"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
-of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
-including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
-or business interruption, however caused and on any theory of liability, whether in contract, strict
-liability, or tort (including negligence), arising in any way out of the use of this software, even if
-advised of the possibility of such damage.
-
-5. CONTACT INFORMATION
-
-Fraunhofer Institute for Integrated Circuits IIS
-Attention: Audio and Multimedia Departments - FDK AAC LL
-Am Wolfsmantel 33
-91058 Erlangen, Germany
-
-www.iis.fraunhofer.de/amm
-amm-info@iis.fraunhofer.de
------------------------------------------------------------------------------------------------------------ */
-
-/******************************** Fraunhofer IIS ***************************
-
- Author(s): Markus Lohwasser, Josef Hoepfl, Manuel Jander
- Description: QMF filterbank
-
-******************************************************************************/
-
-/*!
- \file
- \brief Complex qmf analysis/synthesis,
- This module contains the qmf filterbank for analysis [ cplxAnalysisQmfFiltering() ] and
- synthesis [ cplxSynthesisQmfFiltering() ]. It is a polyphase implementation of a complex
- exponential modulated filter bank. The analysis part usually runs at half the sample rate
- than the synthesis part. (So called "dual-rate" mode.)
-
- The coefficients of the prototype filter are specified in #sbr_qmf_64_640 (in sbr_rom.cpp).
- Thus only a 64 channel version (32 on the analysis side) with a 640 tap prototype filter
- are used.
-
- \anchor PolyphaseFiltering <h2>About polyphase filtering</h2>
- The polyphase implementation of a filterbank requires filtering at the input and output.
- This is implemented as part of cplxAnalysisQmfFiltering() and cplxSynthesisQmfFiltering().
- The implementation requires the filter coefficients in a specific structure as described in
- #sbr_qmf_64_640_qmf (in sbr_rom.cpp).
-
- This module comprises the computationally most expensive functions of the SBR decoder. The accuracy of
- computations is also important and has a direct impact on the overall sound quality. Therefore a special
- test program is available which can be used to only test the filterbank: main_audio.cpp
-
- This modules also uses scaling of data to provide better SNR on fixed-point processors. See #QMF_SCALE_FACTOR (in sbr_scale.h) for details.
- An interesting note: The function getScalefactor() can constitute a significant amount of computational complexity - very much depending on the
- bitrate. Since it is a rather small function, effective assembler optimization might be possible.
-
-*/
-
-#include "qmf.h"
-
-
-#include "fixpoint_math.h"
-#include "dct.h"
-
-#ifdef QMFSYN_STATES_16BIT
-#define QSSCALE (7)
-#define FX_DBL2FX_QSS(x) ((FIXP_QSS) ((x)>>(DFRACT_BITS-QSS_BITS-QSSCALE) ))
-#define FX_QSS2FX_DBL(x) ((FIXP_DBL)((LONG)x)<<(DFRACT_BITS-QSS_BITS-QSSCALE))
-#else
-#define QSSCALE (0)
-#define FX_DBL2FX_QSS(x) (x)
-#define FX_QSS2FX_DBL(x) (x)
-#endif
-
-
-#if defined(__arm__)
-#include "arm/qmf_arm.cpp"
-
-#endif
-
-/*!
- * \brief Algorithmic scaling in sbrForwardModulation()
- *
- * The scaling in sbrForwardModulation() is caused by:
- *
- * \li 1 R_SHIFT in sbrForwardModulation()
- * \li 5/6 R_SHIFT in dct3() if using 32/64 Bands
- * \li 1 ommited gain of 2.0 in qmfForwardModulation()
- */
-#define ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK 7
-
-/*!
- * \brief Algorithmic scaling in cplxSynthesisQmfFiltering()
- *
- * The scaling in cplxSynthesisQmfFiltering() is caused by:
- *
- * \li 5/6 R_SHIFT in dct2() if using 32/64 Bands
- * \li 1 ommited gain of 2.0 in qmfInverseModulation()
- * \li -6 division by 64 in synthesis filterbank
- * \li x bits external influence
- */
-#define ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK 1
-
-
-/*!
- \brief Perform Synthesis Prototype Filtering on a single slot of input data.
-
- The filter takes 2 * qmf->no_channels of input data and
- generates qmf->no_channels time domain output samples.
-*/
-static
-#ifndef FUNCTION_qmfSynPrototypeFirSlot
-void qmfSynPrototypeFirSlot(
-#else
-void qmfSynPrototypeFirSlot_fallback(
-#endif
- HANDLE_QMF_FILTER_BANK qmf,
- FIXP_QMF *RESTRICT realSlot, /*!< Input: Pointer to real Slot */
- FIXP_QMF *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */
- INT_PCM *RESTRICT timeOut, /*!< Time domain data */
- int stride
- )
-{
- FIXP_QSS* FilterStates = (FIXP_QSS*)qmf->FilterStates;
- int no_channels = qmf->no_channels;
- const FIXP_PFT *p_Filter = qmf->p_filter;
- int p_stride = qmf->p_stride;
- int j;
- FIXP_QSS *RESTRICT sta = FilterStates;
- const FIXP_PFT *RESTRICT p_flt, *RESTRICT p_fltm;
- int scale = ((DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor);
-
- p_flt = p_Filter+p_stride*QMF_NO_POLY; /* 5-ter von 330 */
- p_fltm = p_Filter+(qmf->FilterSize/2)-p_stride*QMF_NO_POLY; /* 5 + (320 - 2*5) = 315-ter von 330 */
-
- FDK_ASSERT(SAMPLE_BITS-1-qmf->outScalefactor >= 0); // (DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor >= 0);
-
- for (j = no_channels-1; j >= 0; j--) { /* ---- läuft ueber alle Linien eines Slots ---- */
- FIXP_QMF imag = imagSlot[j]; // no_channels-1 .. 0
- FIXP_QMF real = realSlot[j]; // ~~"~~
- {
- INT_PCM tmp;
- FIXP_DBL Are = FX_QSS2FX_DBL(sta[0]) + fMultDiv2( p_fltm[0] , real);
-
- if (qmf->outGain!=(FIXP_DBL)0x80000000) {
- Are = fMult(Are,qmf->outGain);
- }
-
- #if SAMPLE_BITS > 16
- tmp = (INT_PCM)(SATURATE_SHIFT(fAbs(Are), scale, SAMPLE_BITS));
- #else
- tmp = (INT_PCM)(SATURATE_RIGHT_SHIFT(fAbs(Are), scale, SAMPLE_BITS));
- #endif
- if (Are < (FIXP_QMF)0) {
- tmp = -tmp;
- }
- timeOut[ (j)*stride ] = tmp;
- }
-
- sta[0] = sta[1] + FX_DBL2FX_QSS(fMultDiv2( p_flt [4] , imag ));
- sta[1] = sta[2] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[1] , real ));
- sta[2] = sta[3] + FX_DBL2FX_QSS(fMultDiv2( p_flt [3] , imag ));
- sta[3] = sta[4] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[2] , real ));
- sta[4] = sta[5] + FX_DBL2FX_QSS(fMultDiv2( p_flt [2] , imag ));
- sta[5] = sta[6] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[3] , real ));
- sta[6] = sta[7] + FX_DBL2FX_QSS(fMultDiv2( p_flt [1] , imag ));
- sta[7] = sta[8] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[4] , real ));
- sta[8] = FX_DBL2FX_QSS(fMultDiv2( p_flt [0] , imag ));
-
- p_flt += (p_stride*QMF_NO_POLY);
- p_fltm -= (p_stride*QMF_NO_POLY);
- sta += 9; // = (2*QMF_NO_POLY-1);
- }
-}
-
-#ifndef FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric
-/*!
- \brief Perform Synthesis Prototype Filtering on a single slot of input data.
-
- The filter takes 2 * qmf->no_channels of input data and
- generates qmf->no_channels time domain output samples.
-*/
-static
-void qmfSynPrototypeFirSlot_NonSymmetric(
- HANDLE_QMF_FILTER_BANK qmf,
- FIXP_QMF *RESTRICT realSlot, /*!< Input: Pointer to real Slot */
- FIXP_QMF *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */
- INT_PCM *RESTRICT timeOut, /*!< Time domain data */
- int stride
- )
-{
- FIXP_QSS* FilterStates = (FIXP_QSS*)qmf->FilterStates;
- int no_channels = qmf->no_channels;
- const FIXP_PFT *p_Filter = qmf->p_filter;
- int p_stride = qmf->p_stride;
- int j;
- FIXP_QSS *RESTRICT sta = FilterStates;
- const FIXP_PFT *RESTRICT p_flt, *RESTRICT p_fltm;
- int scale = ((DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor);
-
- p_flt = p_Filter; /*!< Pointer to first half of filter coefficients */
- p_fltm = &p_flt[qmf->FilterSize/2]; /* at index 320, overall 640 coefficients */
-
- FDK_ASSERT(SAMPLE_BITS-1-qmf->outScalefactor >= 0); // (DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor >= 0);
-
- for (j = no_channels-1; j >= 0; j--) { /* ---- läuft ueber alle Linien eines Slots ---- */
-
- FIXP_QMF imag = imagSlot[j]; // no_channels-1 .. 0
- FIXP_QMF real = realSlot[j]; // ~~"~~
- {
- INT_PCM tmp;
- FIXP_QMF Are = sta[0] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[4] , real ));
-
- #if SAMPLE_BITS > 16
- tmp = (INT_PCM)(SATURATE_SHIFT(fAbs(Are), scale, SAMPLE_BITS));
- #else
- tmp = (INT_PCM)(SATURATE_RIGHT_SHIFT(fAbs(Are), scale, SAMPLE_BITS));
- #endif
- if (Are < (FIXP_QMF)0) {
- tmp = -tmp;
- }
- timeOut[j*stride] = tmp;
- }
-
- sta[0] = sta[1] + FX_DBL2FX_QSS(fMultDiv2( p_flt [4] , imag ));
- sta[1] = sta[2] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[3] , real ));
- sta[2] = sta[3] + FX_DBL2FX_QSS(fMultDiv2( p_flt [3] , imag ));
-
- sta[3] = sta[4] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[2] , real ));
- sta[4] = sta[5] + FX_DBL2FX_QSS(fMultDiv2( p_flt [2] , imag ));
- sta[5] = sta[6] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[1] , real ));
- sta[6] = sta[7] + FX_DBL2FX_QSS(fMultDiv2( p_flt [1] , imag ));
-
- sta[7] = sta[8] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[0] , real ));
- sta[8] = FX_DBL2FX_QSS(fMultDiv2( p_flt [0] , imag ));
-
- p_flt += (p_stride*QMF_NO_POLY);
- p_fltm += (p_stride*QMF_NO_POLY);
- sta += 9; // = (2*QMF_NO_POLY-1);
- }
-
-}
-#endif /* FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric */
-
-#ifndef FUNCTION_qmfAnaPrototypeFirSlot
-/*!
- \brief Perform Analysis Prototype Filtering on a single slot of input data.
-*/
-static
-void qmfAnaPrototypeFirSlot( FIXP_QMF *analysisBuffer,
- int no_channels, /*!< Number channels of analysis filter */
- const FIXP_PFT *p_filter,
- int p_stride, /*!< Stide of analysis filter */
- FIXP_QAS *RESTRICT pFilterStates
- )
-{
- int k;
-
- FIXP_DBL accu;
- const FIXP_PFT *RESTRICT p_flt = p_filter;
- FIXP_QMF *RESTRICT pData_0 = analysisBuffer + 2*no_channels - 1;
- FIXP_QMF *RESTRICT pData_1 = analysisBuffer;
-
- FIXP_QAS *RESTRICT sta_0 = (FIXP_QAS *)pFilterStates;
- FIXP_QAS *RESTRICT sta_1 = (FIXP_QAS *)pFilterStates + (2*QMF_NO_POLY*no_channels) - 1;
- int pfltStep = QMF_NO_POLY * (p_stride);
- int staStep1 = no_channels<<1;
- int staStep2 = (no_channels<<3) - 1; /* Rewind one less */
-
- /* FIR filter 0 */
- accu = fMultDiv2( p_flt[0], *sta_1); sta_1 -= staStep1;
- accu += fMultDiv2( p_flt[1], *sta_1); sta_1 -= staStep1;
- accu += fMultDiv2( p_flt[2], *sta_1); sta_1 -= staStep1;
- accu += fMultDiv2( p_flt[3], *sta_1); sta_1 -= staStep1;
- accu += fMultDiv2( p_flt[4], *sta_1);
- *pData_1++ = FX_DBL2FX_QMF(accu<<1);
- sta_1 += staStep2;
-
- p_flt += pfltStep;
-
- /* FIR filters 1..63 127..65 */
- for (k=0; k<no_channels-1; k++)
- {
- accu = fMultDiv2( p_flt[0], *sta_0); sta_0 += staStep1;
- accu += fMultDiv2( p_flt[1], *sta_0); sta_0 += staStep1;
- accu += fMultDiv2( p_flt[2], *sta_0); sta_0 += staStep1;
- accu += fMultDiv2( p_flt[3], *sta_0); sta_0 += staStep1;
- accu += fMultDiv2( p_flt[4], *sta_0);
- *pData_0-- = FX_DBL2FX_QMF(accu<<1);
- sta_0 -= staStep2;
-
- accu = fMultDiv2( p_flt[0], *sta_1); sta_1 -= staStep1;
- accu += fMultDiv2( p_flt[1], *sta_1); sta_1 -= staStep1;
- accu += fMultDiv2( p_flt[2], *sta_1); sta_1 -= staStep1;
- accu += fMultDiv2( p_flt[3], *sta_1); sta_1 -= staStep1;
- accu += fMultDiv2( p_flt[4], *sta_1);
- *pData_1++ = FX_DBL2FX_QMF(accu<<1);
- sta_1 += staStep2;
-
- p_flt += pfltStep;
- }
-
- /* FIR filter 64 */
- accu = fMultDiv2( p_flt[0], *sta_0); sta_0 += staStep1;
- accu += fMultDiv2( p_flt[1], *sta_0); sta_0 += staStep1;
- accu += fMultDiv2( p_flt[2], *sta_0); sta_0 += staStep1;
- accu += fMultDiv2( p_flt[3], *sta_0); sta_0 += staStep1;
- accu += fMultDiv2( p_flt[4], *sta_0);
- *pData_0-- = FX_DBL2FX_QMF(accu<<1);
- sta_0 -= staStep2;
-}
-#endif /* !defined(FUNCTION_qmfAnaPrototypeFirSlot) */
-
-
-#ifndef FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric
-/*!
- \brief Perform Analysis Prototype Filtering on a single slot of input data.
-*/
-static
-void qmfAnaPrototypeFirSlot_NonSymmetric(
- FIXP_QMF *analysisBuffer,
- int no_channels, /*!< Number channels of analysis filter */
- const FIXP_PFT *p_filter,
- int p_stride, /*!< Stide of analysis filter */
- FIXP_QAS *RESTRICT pFilterStates
- )
-{
- const FIXP_PFT *RESTRICT p_flt = p_filter;
- int p, k;
-
- for (k = 0; k < 2*no_channels; k++)
- {
- FIXP_DBL accu = (FIXP_DBL)0;
-
- p_flt += QMF_NO_POLY * (p_stride - 1);
-
- /*
- Perform FIR-Filter
- */
- for (p = 0; p < QMF_NO_POLY; p++) {
- accu += fMultDiv2(*p_flt++, pFilterStates[2*no_channels * p]);
- }
- analysisBuffer[2*no_channels - 1 - k] = FX_DBL2FX_QMF(accu<<1);
- pFilterStates++;
- }
-}
-#endif /* FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric */
-
-/*!
- *
- * \brief Perform real-valued forward modulation of the time domain
- * data of timeIn and stores the real part of the subband
- * samples in rSubband
- *
- */
-static void
-qmfForwardModulationLP_even( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */
- FIXP_QMF *timeIn, /*!< Time Signal */
- FIXP_QMF *rSubband ) /*!< Real Output */
-{
- int i;
- int L = anaQmf->no_channels;
- int M = L>>1;
- int scale;
- FIXP_QMF accu;
-
- const FIXP_QMF *timeInTmp1 = (FIXP_QMF *) &timeIn[3 * M];
- const FIXP_QMF *timeInTmp2 = timeInTmp1;
- FIXP_QMF *rSubbandTmp = rSubband;
-
- rSubband[0] = timeIn[3 * M] >> 1;
-
- for (i = M-1; i != 0; i--) {
- accu = ((*--timeInTmp1) >> 1) + ((*++timeInTmp2) >> 1);
- *++rSubbandTmp = accu;
- }
-
- timeInTmp1 = &timeIn[2 * M];
- timeInTmp2 = &timeIn[0];
- rSubbandTmp = &rSubband[M];
-
- for (i = L-M; i != 0; i--) {
- accu = ((*timeInTmp1--) >> 1) - ((*timeInTmp2++) >> 1);
- *rSubbandTmp++ = accu;
- }
-
- dct_III(rSubband, timeIn, L, &scale);
-}
-
-#if !defined(FUNCTION_qmfForwardModulationLP_odd)
-static void
-qmfForwardModulationLP_odd( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */
- const FIXP_QMF *timeIn, /*!< Time Signal */
- FIXP_QMF *rSubband ) /*!< Real Output */
-{
- int i;
- int L = anaQmf->no_channels;
- int M = L>>1;
- int shift = (anaQmf->no_channels>>6) + 1;
-
- for (i = 0; i < M; i++) {
- rSubband[M + i] = (timeIn[L - 1 - i]>>1) - (timeIn[i]>>shift);
- rSubband[M - 1 - i] = (timeIn[L + i]>>1) + (timeIn[2 * L - 1 - i]>>shift);
- }
-
- dct_IV(rSubband, L, &shift);
-}
-#endif /* !defined(FUNCTION_qmfForwardModulationLP_odd) */
-
-
-
-/*!
- *
- * \brief Perform complex-valued forward modulation of the time domain
- * data of timeIn and stores the real part of the subband
- * samples in rSubband, and the imaginary part in iSubband
- *
- * Only the lower bands are obtained (upto anaQmf->lsb). For
- * a full bandwidth analysis it is required to set both anaQmf->lsb
- * and anaQmf->usb to the amount of QMF bands.
- *
- */
-static void
-qmfForwardModulationHQ( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */
- const FIXP_QMF *RESTRICT timeIn, /*!< Time Signal */
- FIXP_QMF *RESTRICT rSubband, /*!< Real Output */
- FIXP_QMF *RESTRICT iSubband /*!< Imaginary Output */
- )
-{
- int i;
- int L = anaQmf->no_channels;
- int L2 = L<<1;
- int shift = 0;
-
- for (i = 0; i < L; i+=2) {
- FIXP_QMF x0, x1, y0, y1;
-
- x0 = timeIn[i] >> 1;
- x1 = timeIn[i+1] >> 1;
- y0 = timeIn[L2 - 1 - i] >> 1;
- y1 = timeIn[L2 - 2 - i] >> 1;
-
- rSubband[i] = x0 - y0;
- rSubband[i+1] = x1 - y1;
- iSubband[i] = x0 + y0;
- iSubband[i+1] = x1 + y1;
- }
-
- dct_IV(rSubband, L, &shift);
- dst_IV(iSubband, L, &shift);
-
- {
- {
- const FIXP_QTW *RESTRICT sbr_t_cos;
- const FIXP_QTW *RESTRICT sbr_t_sin;
- sbr_t_cos = anaQmf->t_cos;
- sbr_t_sin = anaQmf->t_sin;
-
- for (i = 0; i < anaQmf->lsb; i++) {
- cplxMult(&iSubband[i], &rSubband[i], iSubband[i], rSubband[i], sbr_t_cos[i], sbr_t_sin[i]);
- }
- }
- }
-}
-
-/*
- * \brief Perform one QMF slot analysis of the time domain data of timeIn
- * with specified stride and stores the real part of the subband
- * samples in rSubband, and the imaginary part in iSubband
- *
- * Only the lower bands are obtained (upto anaQmf->lsb). For
- * a full bandwidth analysis it is required to set both anaQmf->lsb
- * and anaQmf->usb to the amount of QMF bands.
- */
-void
-qmfAnalysisFilteringSlot( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */
- FIXP_QMF *qmfReal, /*!< Low and High band, real */
- FIXP_QMF *qmfImag, /*!< Low and High band, imag */
- const INT_PCM *RESTRICT timeIn, /*!< Pointer to input */
- const int stride, /*!< stride factor of input */
- FIXP_QMF *pWorkBuffer /*!< pointer to temporal working buffer */
- )
-{
- int i;
- int offset = anaQmf->no_channels*(QMF_NO_POLY*2-1);
- /*
- Feed time signal into oldest anaQmf->no_channels states
- */
- {
- FIXP_QAS *RESTRICT FilterStatesAnaTmp = ((FIXP_QAS*)anaQmf->FilterStates)+offset;
-
- /* Feed and scale actual time in slot */
- for(i=anaQmf->no_channels>>1; i!=0; i--) {
- /* Place INT_PCM value left aligned in scaledTimeIn */
-#if (QAS_BITS==SAMPLE_BITS)
- *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; timeIn += stride;
- *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; timeIn += stride;
-#elif (QAS_BITS>SAMPLE_BITS)
- *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)<<(QAS_BITS-SAMPLE_BITS)); timeIn += stride;
- *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)<<(QAS_BITS-SAMPLE_BITS)); timeIn += stride;
-#else
- *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)>>(SAMPLE_BITS-QAS_BITS)); timeIn += stride;
- *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)>>(SAMPLE_BITS-QAS_BITS)); timeIn += stride;
-#endif
- }
- }
-
- if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) {
- qmfAnaPrototypeFirSlot_NonSymmetric(
- pWorkBuffer,
- anaQmf->no_channels,
- anaQmf->p_filter,
- anaQmf->p_stride,
- (FIXP_QAS*)anaQmf->FilterStates
- );
- } else {
- qmfAnaPrototypeFirSlot( pWorkBuffer,
- anaQmf->no_channels,
- anaQmf->p_filter,
- anaQmf->p_stride,
- (FIXP_QAS*)anaQmf->FilterStates
- );
- }
-
- if (anaQmf->flags & QMF_FLAG_LP) {
- if (anaQmf->flags & QMF_FLAG_CLDFB)
- qmfForwardModulationLP_odd( anaQmf,
- pWorkBuffer,
- qmfReal );
- else
- qmfForwardModulationLP_even( anaQmf,
- pWorkBuffer,
- qmfReal );
-
- } else {
- qmfForwardModulationHQ( anaQmf,
- pWorkBuffer,
- qmfReal,
- qmfImag
- );
- }
- /*
- Shift filter states
-
- Should be realized with modulo adressing on a DSP instead of a true buffer shift
- */
- FDKmemmove ((FIXP_QAS*)anaQmf->FilterStates, (FIXP_QAS*)anaQmf->FilterStates+anaQmf->no_channels, offset*sizeof(FIXP_QAS));
-}
-
-
-/*!
- *
- * \brief Perform complex-valued subband filtering of the time domain
- * data of timeIn and stores the real part of the subband
- * samples in rAnalysis, and the imaginary part in iAnalysis
- * The qmf coefficient table is symmetric. The symmetry is expoited by
- * shrinking the coefficient table to half the size. The addressing mode
- * takes care of the symmetries.
- *
- * Only the lower bands are obtained (upto anaQmf->lsb). For
- * a full bandwidth analysis it is required to set both anaQmf->lsb
- * and anaQmf->usb to the amount of QMF bands.
- *
- * \sa PolyphaseFiltering
- */
-
-void
-qmfAnalysisFiltering( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */
- FIXP_QMF **qmfReal, /*!< Pointer to real subband slots */
- FIXP_QMF **qmfImag, /*!< Pointer to imag subband slots */
- QMF_SCALE_FACTOR *scaleFactor,
- const INT_PCM *timeIn, /*!< Time signal */
- const int stride,
- FIXP_QMF *pWorkBuffer /*!< pointer to temporal working buffer */
- )
-{
- int i;
- int no_channels = anaQmf->no_channels;
-
- scaleFactor->lb_scale = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK;
- scaleFactor->lb_scale -= anaQmf->filterScale;
-
- for (i = 0; i < anaQmf->no_col; i++)
- {
- FIXP_QMF *qmfImagSlot = NULL;
-
- if (!(anaQmf->flags & QMF_FLAG_LP)) {
- qmfImagSlot = qmfImag[i];
- }
-
- qmfAnalysisFilteringSlot( anaQmf, qmfReal[i], qmfImagSlot, timeIn , stride, pWorkBuffer );
-
- timeIn += no_channels*stride;
-
- } /* no_col loop i */
-}
-
-/*!
- *
- * \brief Perform low power inverse modulation of the subband
- * samples stored in rSubband (real part) and iSubband (imaginary
- * part) and stores the result in pWorkBuffer.
- *
- */
-inline
-static void
-qmfInverseModulationLP_even( HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */
- const FIXP_QMF *qmfReal, /*!< Pointer to qmf real subband slot (input) */
- const int scaleFactorLowBand, /*!< Scalefactor for Low band */
- const int scaleFactorHighBand, /*!< Scalefactor for High band */
- FIXP_QMF *pTimeOut /*!< Pointer to qmf subband slot (output)*/
- )
-{
- int i;
- int L = synQmf->no_channels;
- int M = L>>1;
- int scale;
- FIXP_QMF tmp;
- FIXP_QMF *RESTRICT tReal = pTimeOut;
- FIXP_QMF *RESTRICT tImag = pTimeOut + L;
-
- /* Move input to output vector with offset */
- scaleValues(&tReal[0], &qmfReal[0], synQmf->lsb, scaleFactorLowBand);
- scaleValues(&tReal[0+synQmf->lsb], &qmfReal[0+synQmf->lsb], synQmf->usb-synQmf->lsb, scaleFactorHighBand);
- FDKmemclear(&tReal[0+synQmf->usb], (L-synQmf->usb)*sizeof(FIXP_QMF));
-
- /* Dct type-2 transform */
- dct_II(tReal, tImag, L, &scale);
-
- /* Expand output and replace inplace the output buffers */
- tImag[0] = tReal[M];
- tImag[M] = (FIXP_QMF)0;
- tmp = tReal [0];
- tReal [0] = tReal[M];
- tReal [M] = tmp;
-
- for (i = 1; i < M/2; i++) {
- /* Imag */
- tmp = tReal[L - i];
- tImag[M - i] = tmp;
- tImag[i + M] = -tmp;
-
- tmp = tReal[M + i];
- tImag[i] = tmp;
- tImag[L - i] = -tmp;
-
- /* Real */
- tReal [M + i] = tReal[i];
- tReal [L - i] = tReal[M - i];
- tmp = tReal[i];
- tReal[i] = tReal [M - i];
- tReal [M - i] = tmp;
-
- }
- /* Remaining odd terms */
- tmp = tReal[M + M/2];
- tImag[M/2] = tmp;
- tImag[M/2 + M] = -tmp;
-
- tReal [M + M/2] = tReal[M/2];
-}
-
-inline
-static void
-qmfInverseModulationLP_odd( HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */
- const FIXP_QMF *qmfReal, /*!< Pointer to qmf real subband slot (input) */
- const int scaleFactorLowBand, /*!< Scalefactor for Low band */
- const int scaleFactorHighBand, /*!< Scalefactor for High band */
- FIXP_QMF *pTimeOut /*!< Pointer to qmf subband slot (output)*/
- )
-{
- int i;
- int L = synQmf->no_channels;
- int M = L>>1;
- int shift = 0;
-
- /* Move input to output vector with offset */
- scaleValues(pTimeOut+M, qmfReal, synQmf->lsb, scaleFactorLowBand);
- scaleValues(pTimeOut+M+synQmf->lsb, qmfReal+synQmf->lsb, synQmf->usb-synQmf->lsb, scaleFactorHighBand);
- FDKmemclear(pTimeOut+M+synQmf->usb, (L-synQmf->usb)*sizeof(FIXP_QMF));
-
- dct_IV(pTimeOut+M, L, &shift);
- for (i = 0; i < M; i++) {
- pTimeOut[i] = pTimeOut[L - 1 - i];
- pTimeOut[2 * L - 1 - i] = -pTimeOut[L + i];
- }
-}
-
-
-/*!
- *
- * \brief Perform complex-valued inverse modulation of the subband
- * samples stored in rSubband (real part) and iSubband (imaginary
- * part) and stores the result in pWorkBuffer.
- *
- */
-inline
-static void
-qmfInverseModulationHQ( HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */
- const FIXP_QMF *qmfReal, /*!< Pointer to qmf real subband slot */
- const FIXP_QMF *qmfImag, /*!< Pointer to qmf imag subband slot */
- const int scaleFactorLowBand, /*!< Scalefactor for Low band */
- const int scaleFactorHighBand,/*!< Scalefactor for High band */
- FIXP_QMF *pWorkBuffer /*!< WorkBuffer (output) */
- )
-{
- int i;
- int L = synQmf->no_channels;
- int M = L>>1;
- int shift = 0;
- FIXP_QMF *RESTRICT tReal = pWorkBuffer;
- FIXP_QMF *RESTRICT tImag = pWorkBuffer+L;
-
- if (synQmf->flags & QMF_FLAG_CLDFB){
- for (i = 0; i < synQmf->lsb; i++) {
- cplxMult(&tImag[i], &tReal[i],
- scaleValue(qmfImag[i],scaleFactorLowBand), scaleValue(qmfReal[i],scaleFactorLowBand),
- synQmf->t_cos[i], synQmf->t_sin[i]);
- }
- for (; i < synQmf->usb; i++) {
- cplxMult(&tImag[i], &tReal[i],
- scaleValue(qmfImag[i],scaleFactorHighBand), scaleValue(qmfReal[i],scaleFactorHighBand),
- synQmf->t_cos[i], synQmf->t_sin[i]);
- }
- }
-
- if ( (synQmf->flags & QMF_FLAG_CLDFB) == 0) {
- scaleValues(&tReal[0], &qmfReal[0], synQmf->lsb, scaleFactorLowBand);
- scaleValues(&tReal[0+synQmf->lsb], &qmfReal[0+synQmf->lsb], synQmf->usb-synQmf->lsb, scaleFactorHighBand);
- scaleValues(&tImag[0], &qmfImag[0], synQmf->lsb, scaleFactorLowBand);
- scaleValues(&tImag[0+synQmf->lsb], &qmfImag[0+synQmf->lsb], synQmf->usb-synQmf->lsb, scaleFactorHighBand);
- }
-
- FDKmemclear(&tReal[synQmf->usb], (synQmf->no_channels-synQmf->usb)*sizeof(FIXP_QMF));
- FDKmemclear(&tImag[synQmf->usb], (synQmf->no_channels-synQmf->usb)*sizeof(FIXP_QMF));
-
- dct_IV(tReal, L, &shift);
- dst_IV(tImag, L, &shift);
-
- if (synQmf->flags & QMF_FLAG_CLDFB){
- for (i = 0; i < M; i++) {
- FIXP_QMF r1, i1, r2, i2;
- r1 = tReal[i];
- i2 = tImag[L - 1 - i];
- r2 = tReal[L - i - 1];
- i1 = tImag[i];
-
- tReal[i] = (r1 - i1)>>1;
- tImag[L - 1 - i] = -(r1 + i1)>>1;
- tReal[L - i - 1] = (r2 - i2)>>1;
- tImag[i] = -(r2 + i2)>>1;
- }
- } else
- {
- /* The array accesses are negative to compensate the missing minus sign in the low and hi band gain. */
- /* 26 cycles on ARM926 */
- for (i = 0; i < M; i++) {
- FIXP_QMF r1, i1, r2, i2;
- r1 = -tReal[i];
- i2 = -tImag[L - 1 - i];
- r2 = -tReal[L - i - 1];
- i1 = -tImag[i];
-
- tReal[i] = (r1 - i1)>>1;
- tImag[L - 1 - i] = -(r1 + i1)>>1;
- tReal[L - i - 1] = (r2 - i2)>>1;
- tImag[i] = -(r2 + i2)>>1;
- }
- }
-}
-
-void qmfSynthesisFilteringSlot( HANDLE_QMF_FILTER_BANK synQmf,
- const FIXP_QMF *realSlot,
- const FIXP_QMF *imagSlot,
- const int scaleFactorLowBand,
- const int scaleFactorHighBand,
- INT_PCM *timeOut,
- const int stride,
- FIXP_QMF *pWorkBuffer)
-{
- if (!(synQmf->flags & QMF_FLAG_LP))
- qmfInverseModulationHQ ( synQmf,
- realSlot,
- imagSlot,
- scaleFactorLowBand,
- scaleFactorHighBand,
- pWorkBuffer
- );
- else
- {
- if (synQmf->flags & QMF_FLAG_CLDFB) {
- qmfInverseModulationLP_odd ( synQmf,
- realSlot,
- scaleFactorLowBand,
- scaleFactorHighBand,
- pWorkBuffer
- );
- } else {
- qmfInverseModulationLP_even ( synQmf,
- realSlot,
- scaleFactorLowBand,
- scaleFactorHighBand,
- pWorkBuffer
- );
- }
- }
-
- if (synQmf->flags & QMF_FLAG_NONSYMMETRIC) {
- qmfSynPrototypeFirSlot_NonSymmetric (
- synQmf,
- pWorkBuffer,
- pWorkBuffer+synQmf->no_channels,
- timeOut,
- stride
- );
- } else {
- qmfSynPrototypeFirSlot ( synQmf,
- pWorkBuffer,
- pWorkBuffer+synQmf->no_channels,
- timeOut,
- stride
- );
- }
-}
-
-
-/*!
- *
- *
- * \brief Perform complex-valued subband synthesis of the
- * low band and the high band and store the
- * time domain data in timeOut
- *
- * First step: Calculate the proper scaling factor of current
- * spectral data in qmfReal/qmfImag, old spectral data in the overlap
- * range and filter states.
- *
- * Second step: Perform Frequency-to-Time mapping with inverse
- * Modulation slot-wise.
- *
- * Third step: Perform FIR-filter slot-wise. To save space for filter
- * states, the MAC operations are executed directly on the filter states
- * instead of accumulating several products in the accumulator. The
- * buffer shift at the end of the function should be replaced by a
- * modulo operation, which is available on some DSPs.
- *
- * Last step: Copy the upper part of the spectral data to the overlap buffer.
- *
- * The qmf coefficient table is symmetric. The symmetry is exploited by
- * shrinking the coefficient table to half the size. The addressing mode
- * takes care of the symmetries. If the #define #QMFTABLE_FULL is set,
- * coefficient addressing works on the full table size. The code will be
- * slightly faster and slightly more compact.
- *
- * Workbuffer requirement: 2 x sizeof(**QmfBufferReal) * synQmf->no_channels
- */
-void
-qmfSynthesisFiltering( HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */
- FIXP_QMF **QmfBufferReal, /*!< Low and High band, real */
- FIXP_QMF **QmfBufferImag, /*!< Low and High band, imag */
- const QMF_SCALE_FACTOR *scaleFactor,
- const INT ov_len, /*!< split Slot of overlap and actual slots */
- INT_PCM *timeOut, /*!< Pointer to output */
- const INT stride, /*!< stride factor of output */
- FIXP_QMF *pWorkBuffer /*!< pointer to temporal working buffer */
- )
-{
- int i;
- int L = synQmf->no_channels;
- SCHAR scaleFactorHighBand;
- SCHAR scaleFactorLowBand_ov, scaleFactorLowBand_no_ov;
-
- /* adapt scaling */
- scaleFactorHighBand = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - scaleFactor->hb_scale;
- scaleFactorLowBand_ov = - ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - scaleFactor->ov_lb_scale;
- scaleFactorLowBand_no_ov = - ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - scaleFactor->lb_scale;
-
- for (i = 0; i < synQmf->no_col; i++) /* ----- no_col loop ----- */
- {
- const FIXP_DBL *QmfBufferImagSlot = NULL;
-
- SCHAR scaleFactorLowBand = (i<ov_len) ? scaleFactorLowBand_ov : scaleFactorLowBand_no_ov;
-
- if (!(synQmf->flags & QMF_FLAG_LP))
- QmfBufferImagSlot = QmfBufferImag[i];
-
- qmfSynthesisFilteringSlot( synQmf,
- QmfBufferReal[i],
- QmfBufferImagSlot,
- scaleFactorLowBand,
- scaleFactorHighBand,
- timeOut+(i*L*stride),
- stride,
- pWorkBuffer);
- } /* no_col loop i */
-
-}
-
-
-/*!
- *
- * \brief Create QMF filter bank instance
- *
- * \return 0 if successful
- *
- */
-static int
-qmfInitFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Handle to return */
- void *pFilterStates, /*!< Handle to filter states */
- int noCols, /*!< Number of timeslots per frame */
- int lsb, /*!< Lower end of QMF frequency range */
- int usb, /*!< Upper end of QMF frequency range */
- int no_channels, /*!< Number of channels (bands) */
- UINT flags) /*!< flags */
-{
- FDKmemclear(h_Qmf,sizeof(QMF_FILTER_BANK));
-
- if (flags & QMF_FLAG_MPSLDFB)
- {
- return -1;
- }
-
- if ( !(flags & QMF_FLAG_MPSLDFB) && (flags & QMF_FLAG_CLDFB) )
- {
- flags |= QMF_FLAG_NONSYMMETRIC;
- h_Qmf->filterScale = QMF_CLDFB_PFT_SCALE;
-
- h_Qmf->p_stride = 1;
- switch (no_channels) {
- case 64:
- h_Qmf->t_cos = qmf_phaseshift_cos64_cldfb;
- h_Qmf->t_sin = qmf_phaseshift_sin64_cldfb;
- h_Qmf->p_filter = qmf_cldfb_640;
- h_Qmf->FilterSize = 640;
- break;
- case 32:
- h_Qmf->t_cos = qmf_phaseshift_cos32_cldfb;
- h_Qmf->t_sin = qmf_phaseshift_sin32_cldfb;
- h_Qmf->p_filter = qmf_cldfb_320;
- h_Qmf->FilterSize = 320;
- break;
- default:
- return -1;
- }
- }
-
- if ( !(flags & QMF_FLAG_MPSLDFB) && ((flags & QMF_FLAG_CLDFB) == 0) )
- {
- switch (no_channels) {
- case 64:
- h_Qmf->p_filter = qmf_64;
- h_Qmf->t_cos = qmf_phaseshift_cos64;
- h_Qmf->t_sin = qmf_phaseshift_sin64;
- h_Qmf->p_stride = 1;
- h_Qmf->FilterSize = 640;
- h_Qmf->filterScale = 0;
- break;
- case 32:
- h_Qmf->p_filter = qmf_64;
- if (flags & QMF_FLAG_DOWNSAMPLED) {
- h_Qmf->t_cos = qmf_phaseshift_cos_downsamp32;
- h_Qmf->t_sin = qmf_phaseshift_sin_downsamp32;
- }
- else {
- h_Qmf->t_cos = qmf_phaseshift_cos32;
- h_Qmf->t_sin = qmf_phaseshift_sin32;
- }
- h_Qmf->p_stride = 2;
- h_Qmf->FilterSize = 640;
- h_Qmf->filterScale = 0;
- break;
- default:
- return -1;
- }
- }
-
- h_Qmf->flags = flags;
-
- h_Qmf->no_channels = no_channels;
- h_Qmf->no_col = noCols;
-
- h_Qmf->lsb = lsb;
- h_Qmf->usb = fMin(usb, h_Qmf->no_channels);
-
- h_Qmf->FilterStates = (void*)pFilterStates;
-
- h_Qmf->outScalefactor = ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + h_Qmf->filterScale;
-
- if ( (h_Qmf->p_stride == 2)
- || ((flags & QMF_FLAG_CLDFB) && (no_channels == 32)) ) {
- h_Qmf->outScalefactor -= 1;
- }
- h_Qmf->outGain = (FIXP_DBL)0x80000000; /* default init value will be not applied */
-
- return (0);
-}
-
-/*!
- *
- * \brief Adjust synthesis qmf filter states
- *
- * \return void
- *
- */
-static inline void
-qmfAdaptFilterStates (HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Filter Bank */
- int scaleFactorDiff) /*!< Scale factor difference to be applied */
-{
- if (synQmf == NULL || synQmf->FilterStates == NULL) {
- return;
- }
- scaleValues((FIXP_QSS*)synQmf->FilterStates, synQmf->no_channels*(QMF_NO_POLY*2 - 1), scaleFactorDiff);
-}
-
-/*!
- *
- * \brief Create QMF filter bank instance
- *
- * Only the lower bands are obtained (upto anaQmf->lsb). For
- * a full bandwidth analysis it is required to set both anaQmf->lsb
- * and anaQmf->usb to the amount of QMF bands.
- *
- * \return 0 if succesful
- *
- */
-int
-qmfInitAnalysisFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */
- FIXP_QAS *pFilterStates, /*!< Handle to filter states */
- int noCols, /*!< Number of timeslots per frame */
- int lsb, /*!< lower end of QMF */
- int usb, /*!< upper end of QMF */
- int no_channels, /*!< Number of channels (bands) */
- int flags) /*!< Low Power flag */
-{
- int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, no_channels, flags);
- if ( !(flags & QMF_FLAG_KEEP_STATES) && (h_Qmf->FilterStates != NULL) ) {
- FDKmemclear(h_Qmf->FilterStates, (2*QMF_NO_POLY-1)*h_Qmf->no_channels*sizeof(FIXP_QAS));
- }
-
- return err;
-}
-
-/*!
- *
- * \brief Create QMF filter bank instance
- *
- * Only the lower bands are obtained (upto anaQmf->lsb). For
- * a full bandwidth analysis it is required to set both anaQmf->lsb
- * and anaQmf->usb to the amount of QMF bands.
- *
- * \return 0 if succesful
- *
- */
-int
-qmfInitSynthesisFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */
- FIXP_QSS *pFilterStates, /*!< Handle to filter states */
- int noCols, /*!< Number of timeslots per frame */
- int lsb, /*!< lower end of QMF */
- int usb, /*!< upper end of QMF */
- int no_channels, /*!< Number of channels (bands) */
- int flags) /*!< Low Power flag */
-{
- int oldOutScale = h_Qmf->outScalefactor;
- int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, no_channels, flags);
- if ( h_Qmf->FilterStates != NULL ) {
- if ( !(flags & QMF_FLAG_KEEP_STATES) ) {
- FDKmemclear(h_Qmf->FilterStates, (2*QMF_NO_POLY-1)*h_Qmf->no_channels*sizeof(FIXP_QSS));
- } else {
- qmfAdaptFilterStates(h_Qmf, oldOutScale-h_Qmf->outScalefactor);
- }
- }
- return err;
-}
-
-
-
-
-/*!
- *
- * \brief Change scale factor for output data and adjust qmf filter states
- *
- * \return void
- *
- */
-void
-qmfChangeOutScalefactor (HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */
- int outScalefactor /*!< New scaling factor for output data */
- )
-{
- if (synQmf == NULL || synQmf->FilterStates == NULL) {
- return;
- }
-
- /* Add internal filterbank scale */
- outScalefactor += ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + synQmf->filterScale;
-
- if ( (synQmf->p_stride == 2)
- || ((synQmf->flags & QMF_FLAG_CLDFB) && (synQmf->no_channels == 32)) ) {
- outScalefactor -= 1;
- }
-
- /* adjust filter states when scale factor has been changed */
- if (synQmf->outScalefactor != outScalefactor)
- {
- int diff;
-
- if (outScalefactor > (SAMPLE_BITS - 1)) {
- outScalefactor = SAMPLE_BITS - 1;
- } else if (outScalefactor < (1 - SAMPLE_BITS)) {
- outScalefactor = 1 - SAMPLE_BITS;
- }
-
- diff = synQmf->outScalefactor - outScalefactor;
-
- qmfAdaptFilterStates(synQmf, diff);
-
- /* save new scale factor */
- synQmf->outScalefactor = outScalefactor;
- }
-}
-
-/*!
- *
- * \brief Change gain for output data
- *
- * \return void
- *
- */
-void
-qmfChangeOutGain (HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */
- FIXP_DBL outputGain /*!< New gain for output data */
- )
-{
- synQmf->outGain = outputGain;
-}
-