1
2/* -----------------------------------------------------------------------------------------------------------
3Software License for The Fraunhofer FDK AAC Codec Library for Android
4
5© Copyright  1995 - 2012 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
6  All rights reserved.
7
8 1.    INTRODUCTION
9The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
12
13AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16of the MPEG specifications.
17
18Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20individually for the purpose of encoding or decoding bit streams in products that are compliant with
21the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23software may already be covered under those patent licenses when it is used for those licensed purposes only.
24
25Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27applications information and documentation.
28
292.    COPYRIGHT LICENSE
30
31Redistribution and use in source and binary forms, with or without modification, are permitted without
32payment of copyright license fees provided that you satisfy the following conditions:
33
34You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35your modifications thereto in source code form.
36
37You must retain the complete text of this software license in the documentation and/or other materials
38provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40modifications thereto to recipients of copies in binary form.
41
42The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43prior written permission.
44
45You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46software or your modifications thereto.
47
48Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49and the date of any change. For modified versions of the FDK AAC Codec, the term
50"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
51"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
52
533.    NO PATENT LICENSE
54
55NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57respect to this software.
58
59You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60by appropriate patent licenses.
61
624.    DISCLAIMER
63
64This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
65"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
66of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69or business interruption, however caused and on any theory of liability, whether in contract, strict
70liability, or tort (including negligence), arising in any way out of the use of this software, even if
71advised of the possibility of such damage.
72
735.    CONTACT INFORMATION
74
75Fraunhofer Institute for Integrated Circuits IIS
76Attention: Audio and Multimedia Departments - FDK AAC LL
77Am Wolfsmantel 33
7891058 Erlangen, Germany
79
80www.iis.fraunhofer.de/amm
81amm-info@iis.fraunhofer.de
82----------------------------------------------------------------------------------------------------------- */
83
84/********************************  Fraunhofer IIS  ***************************
85
86   Author(s):   Markus Lohwasser, Josef Hoepfl, Manuel Jander
87   Description: QMF filterbank
88
89******************************************************************************/
90
91/*!
92  \file
93  \brief  Complex qmf analysis/synthesis,
94  This module contains the qmf filterbank for analysis [ cplxAnalysisQmfFiltering() ] and
95  synthesis [ cplxSynthesisQmfFiltering() ]. It is a polyphase implementation of a complex
96  exponential modulated filter bank. The analysis part usually runs at half the sample rate
97  than the synthesis part. (So called "dual-rate" mode.)
98
99  The coefficients of the prototype filter are specified in #sbr_qmf_64_640 (in sbr_rom.cpp).
100  Thus only a 64 channel version (32 on the analysis side) with a 640 tap prototype filter
101  are used.
102
103  \anchor PolyphaseFiltering <h2>About polyphase filtering</h2>
104  The polyphase implementation of a filterbank requires filtering at the input and output.
105  This is implemented as part of cplxAnalysisQmfFiltering() and cplxSynthesisQmfFiltering().
106  The implementation requires the filter coefficients in a specific structure as described in
107  #sbr_qmf_64_640_qmf (in sbr_rom.cpp).
108
109  This module comprises the computationally most expensive functions of the SBR decoder. The accuracy of
110  computations is also important and has a direct impact on the overall sound quality. Therefore a special
111  test program is available which can be used to only test the filterbank: main_audio.cpp
112
113  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.
114  An interesting note: The function getScalefactor() can constitute a significant amount of computational complexity - very much depending on the
115  bitrate. Since it is a rather small function, effective assembler optimization might be possible.
116
117*/
118
119#include "qmf.h"
120
121
122#include "fixpoint_math.h"
123#include "dct.h"
124
125#ifdef QMFSYN_STATES_16BIT
126#define QSSCALE (7)
127#define FX_DBL2FX_QSS(x) ((FIXP_QSS) ((x)>>(DFRACT_BITS-QSS_BITS-QSSCALE) ))
128#define FX_QSS2FX_DBL(x) ((FIXP_DBL)((LONG)x)<<(DFRACT_BITS-QSS_BITS-QSSCALE))
129#else
130#define QSSCALE (0)
131#define FX_DBL2FX_QSS(x) (x)
132#define FX_QSS2FX_DBL(x) (x)
133#endif
134
135
136#if defined(__arm__)
137#include "arm/qmf_arm.cpp"
138
139#endif
140
141/*!
142 * \brief Algorithmic scaling in sbrForwardModulation()
143 *
144 * The scaling in sbrForwardModulation() is caused by:
145 *
146 *   \li 1 R_SHIFT in sbrForwardModulation()
147 *   \li 5/6 R_SHIFT in dct3() if using 32/64 Bands
148 *   \li 1 ommited gain of 2.0 in qmfForwardModulation()
149 */
150#define ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK 7
151
152/*!
153 * \brief Algorithmic scaling in cplxSynthesisQmfFiltering()
154 *
155 * The scaling in cplxSynthesisQmfFiltering() is caused by:
156 *
157 *   \li  5/6 R_SHIFT in dct2() if using 32/64 Bands
158 *   \li  1 ommited gain of 2.0 in qmfInverseModulation()
159 *   \li -6 division by 64 in synthesis filterbank
160 *   \li x bits external influence
161 */
162#define ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK 1
163
164
165/*!
166  \brief Perform Synthesis Prototype Filtering on a single slot of input data.
167
168  The filter takes 2 * qmf->no_channels of input data and
169  generates qmf->no_channels time domain output samples.
170*/
171static
172#ifndef FUNCTION_qmfSynPrototypeFirSlot
173void qmfSynPrototypeFirSlot(
174#else
175void qmfSynPrototypeFirSlot_fallback(
176#endif
177                             HANDLE_QMF_FILTER_BANK qmf,
178                             FIXP_QMF *RESTRICT realSlot,            /*!< Input: Pointer to real Slot */
179                             FIXP_QMF *RESTRICT imagSlot,            /*!< Input: Pointer to imag Slot */
180                             INT_PCM  *RESTRICT timeOut,             /*!< Time domain data */
181                             int       stride
182                            )
183{
184  FIXP_QSS* FilterStates = (FIXP_QSS*)qmf->FilterStates;
185  int       no_channels = qmf->no_channels;
186  const FIXP_PFT *p_Filter = qmf->p_filter;
187  int p_stride = qmf->p_stride;
188  int j;
189  FIXP_QSS *RESTRICT sta = FilterStates;
190  const FIXP_PFT *RESTRICT p_flt, *RESTRICT p_fltm;
191  int scale = ((DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor);
192
193  p_flt  = p_Filter+p_stride*QMF_NO_POLY;          /*                     5-ter von 330 */
194  p_fltm = p_Filter+(qmf->FilterSize/2)-p_stride*QMF_NO_POLY;  /* 5 + (320 - 2*5) = 315-ter von 330 */
195
196  FDK_ASSERT(SAMPLE_BITS-1-qmf->outScalefactor >= 0); //   (DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor >= 0);
197
198  for (j = no_channels-1; j >= 0; j--) {  /* ---- läuft ueber alle Linien eines Slots ---- */
199    FIXP_QMF imag  =  imagSlot[j];  // no_channels-1 .. 0
200    FIXP_QMF real  =  realSlot[j];  // ~~"~~
201    {
202      INT_PCM tmp;
203      FIXP_DBL Are = FX_QSS2FX_DBL(sta[0]) + fMultDiv2( p_fltm[0] , real);
204
205      if (qmf->outGain!=(FIXP_DBL)0x80000000) {
206        Are = fMult(Are,qmf->outGain);
207      }
208
209  #if SAMPLE_BITS > 16
210      tmp = (INT_PCM)(SATURATE_SHIFT(fAbs(Are), scale, SAMPLE_BITS));
211  #else
212      tmp = (INT_PCM)(SATURATE_RIGHT_SHIFT(fAbs(Are), scale, SAMPLE_BITS));
213  #endif
214      if (Are < (FIXP_QMF)0) {
215        tmp = -tmp;
216      }
217      timeOut[ (j)*stride ] = tmp;
218    }
219
220    sta[0] = sta[1] + FX_DBL2FX_QSS(fMultDiv2( p_flt [4] , imag ));
221    sta[1] = sta[2] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[1] , real ));
222    sta[2] = sta[3] + FX_DBL2FX_QSS(fMultDiv2( p_flt [3] , imag ));
223    sta[3] = sta[4] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[2] , real ));
224    sta[4] = sta[5] + FX_DBL2FX_QSS(fMultDiv2( p_flt [2] , imag ));
225    sta[5] = sta[6] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[3] , real ));
226    sta[6] = sta[7] + FX_DBL2FX_QSS(fMultDiv2( p_flt [1] , imag ));
227    sta[7] = sta[8] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[4] , real ));
228    sta[8] =          FX_DBL2FX_QSS(fMultDiv2( p_flt [0] , imag ));
229
230    p_flt  += (p_stride*QMF_NO_POLY);
231    p_fltm -= (p_stride*QMF_NO_POLY);
232    sta    += 9; // = (2*QMF_NO_POLY-1);
233  }
234}
235
236#ifndef FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric
237/*!
238  \brief Perform Synthesis Prototype Filtering on a single slot of input data.
239
240  The filter takes 2 * qmf->no_channels of input data and
241  generates qmf->no_channels time domain output samples.
242*/
243static
244void qmfSynPrototypeFirSlot_NonSymmetric(
245                             HANDLE_QMF_FILTER_BANK qmf,
246                             FIXP_QMF *RESTRICT realSlot,            /*!< Input: Pointer to real Slot */
247                             FIXP_QMF *RESTRICT imagSlot,            /*!< Input: Pointer to imag Slot */
248                             INT_PCM  *RESTRICT timeOut,             /*!< Time domain data */
249                             int       stride
250                            )
251{
252  FIXP_QSS* FilterStates = (FIXP_QSS*)qmf->FilterStates;
253  int       no_channels = qmf->no_channels;
254  const FIXP_PFT *p_Filter = qmf->p_filter;
255  int p_stride = qmf->p_stride;
256  int j;
257  FIXP_QSS *RESTRICT sta = FilterStates;
258  const FIXP_PFT *RESTRICT p_flt, *RESTRICT p_fltm;
259  int scale = ((DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor);
260
261  p_flt  = p_Filter;                           /*!< Pointer to first half of filter coefficients */
262  p_fltm = &p_flt[qmf->FilterSize/2];  /* at index 320, overall 640 coefficients */
263
264  FDK_ASSERT(SAMPLE_BITS-1-qmf->outScalefactor >= 0); //   (DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor >= 0);
265
266  for (j = no_channels-1; j >= 0; j--) {  /* ---- läuft ueber alle Linien eines Slots ---- */
267
268    FIXP_QMF imag  =  imagSlot[j];  // no_channels-1 .. 0
269    FIXP_QMF real  =  realSlot[j];  // ~~"~~
270    {
271      INT_PCM tmp;
272      FIXP_QMF Are = sta[0] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[4] , real ));
273
274  #if SAMPLE_BITS > 16
275      tmp = (INT_PCM)(SATURATE_SHIFT(fAbs(Are), scale, SAMPLE_BITS));
276  #else
277      tmp = (INT_PCM)(SATURATE_RIGHT_SHIFT(fAbs(Are), scale, SAMPLE_BITS));
278  #endif
279      if (Are < (FIXP_QMF)0) {
280        tmp = -tmp;
281      }
282      timeOut[j*stride] = tmp;
283    }
284
285    sta[0] = sta[1] + FX_DBL2FX_QSS(fMultDiv2( p_flt [4] , imag ));
286    sta[1] = sta[2] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[3] , real ));
287    sta[2] = sta[3] + FX_DBL2FX_QSS(fMultDiv2( p_flt [3] , imag ));
288
289    sta[3] = sta[4] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[2] , real ));
290    sta[4] = sta[5] + FX_DBL2FX_QSS(fMultDiv2( p_flt [2] , imag ));
291    sta[5] = sta[6] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[1] , real ));
292    sta[6] = sta[7] + FX_DBL2FX_QSS(fMultDiv2( p_flt [1] , imag ));
293
294    sta[7] = sta[8] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[0] , real ));
295    sta[8] =          FX_DBL2FX_QSS(fMultDiv2( p_flt [0] , imag ));
296
297    p_flt  += (p_stride*QMF_NO_POLY);
298    p_fltm += (p_stride*QMF_NO_POLY);
299    sta    += 9; // = (2*QMF_NO_POLY-1);
300  }
301
302}
303#endif /* FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric */
304
305#ifndef FUNCTION_qmfAnaPrototypeFirSlot
306/*!
307  \brief Perform Analysis Prototype Filtering on a single slot of input data.
308*/
309static
310void qmfAnaPrototypeFirSlot( FIXP_QMF *analysisBuffer,
311                             int       no_channels,             /*!< Number channels of analysis filter */
312                             const FIXP_PFT *p_filter,
313                             int       p_stride,                /*!< Stide of analysis filter    */
314                             FIXP_QAS *RESTRICT pFilterStates
315                            )
316{
317    int k;
318
319    FIXP_DBL accu;
320    const FIXP_PFT *RESTRICT p_flt = p_filter;
321    FIXP_QMF *RESTRICT pData_0 = analysisBuffer + 2*no_channels - 1;
322    FIXP_QMF *RESTRICT pData_1 = analysisBuffer;
323
324    FIXP_QAS *RESTRICT sta_0 = (FIXP_QAS *)pFilterStates;
325    FIXP_QAS *RESTRICT sta_1 = (FIXP_QAS *)pFilterStates + (2*QMF_NO_POLY*no_channels) - 1;
326    int pfltStep = QMF_NO_POLY * (p_stride);
327    int staStep1 = no_channels<<1;
328    int staStep2 = (no_channels<<3) - 1; /* Rewind one less */
329
330    /* FIR filter 0 */
331    accu =   fMultDiv2( p_flt[0], *sta_1);  sta_1 -= staStep1;
332    accu +=  fMultDiv2( p_flt[1], *sta_1);  sta_1 -= staStep1;
333    accu +=  fMultDiv2( p_flt[2], *sta_1);  sta_1 -= staStep1;
334    accu +=  fMultDiv2( p_flt[3], *sta_1);  sta_1 -= staStep1;
335    accu +=  fMultDiv2( p_flt[4], *sta_1);
336    *pData_1++ = FX_DBL2FX_QMF(accu<<1);
337    sta_1 += staStep2;
338
339    p_flt += pfltStep;
340
341    /* FIR filters 1..63 127..65 */
342    for (k=0; k<no_channels-1; k++)
343    {
344      accu =  fMultDiv2( p_flt[0], *sta_0);  sta_0 += staStep1;
345      accu += fMultDiv2( p_flt[1], *sta_0);  sta_0 += staStep1;
346      accu += fMultDiv2( p_flt[2], *sta_0);  sta_0 += staStep1;
347      accu += fMultDiv2( p_flt[3], *sta_0);  sta_0 += staStep1;
348      accu += fMultDiv2( p_flt[4], *sta_0);
349      *pData_0-- = FX_DBL2FX_QMF(accu<<1);
350      sta_0 -= staStep2;
351
352      accu =   fMultDiv2( p_flt[0], *sta_1);  sta_1 -= staStep1;
353      accu +=  fMultDiv2( p_flt[1], *sta_1);  sta_1 -= staStep1;
354      accu +=  fMultDiv2( p_flt[2], *sta_1);  sta_1 -= staStep1;
355      accu +=  fMultDiv2( p_flt[3], *sta_1);  sta_1 -= staStep1;
356      accu +=  fMultDiv2( p_flt[4], *sta_1);
357      *pData_1++ = FX_DBL2FX_QMF(accu<<1);
358      sta_1 += staStep2;
359
360      p_flt += pfltStep;
361    }
362
363    /* FIR filter 64 */
364    accu =  fMultDiv2( p_flt[0], *sta_0);  sta_0 += staStep1;
365    accu += fMultDiv2( p_flt[1], *sta_0);  sta_0 += staStep1;
366    accu += fMultDiv2( p_flt[2], *sta_0);  sta_0 += staStep1;
367    accu += fMultDiv2( p_flt[3], *sta_0);  sta_0 += staStep1;
368    accu += fMultDiv2( p_flt[4], *sta_0);
369    *pData_0-- = FX_DBL2FX_QMF(accu<<1);
370    sta_0 -= staStep2;
371}
372#endif /* !defined(FUNCTION_qmfAnaPrototypeFirSlot) */
373
374
375#ifndef FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric
376/*!
377  \brief Perform Analysis Prototype Filtering on a single slot of input data.
378*/
379static
380void qmfAnaPrototypeFirSlot_NonSymmetric(
381                                        FIXP_QMF *analysisBuffer,
382                                        int       no_channels,             /*!< Number channels of analysis filter */
383                                        const FIXP_PFT *p_filter,
384                                        int       p_stride,                /*!< Stide of analysis filter    */
385                                        FIXP_QAS *RESTRICT pFilterStates
386                                       )
387{
388  const FIXP_PFT *RESTRICT p_flt = p_filter;
389  int  p, k;
390
391  for (k = 0; k < 2*no_channels; k++)
392  {
393    FIXP_DBL accu = (FIXP_DBL)0;
394
395    p_flt += QMF_NO_POLY * (p_stride - 1);
396
397    /*
398      Perform FIR-Filter
399    */
400    for (p = 0; p < QMF_NO_POLY; p++) {
401      accu +=  fMultDiv2(*p_flt++, pFilterStates[2*no_channels * p]);
402    }
403    analysisBuffer[2*no_channels - 1 - k] = FX_DBL2FX_QMF(accu<<1);
404    pFilterStates++;
405  }
406}
407#endif /* FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric */
408
409/*!
410 *
411 * \brief Perform real-valued forward modulation of the time domain
412 *        data of timeIn and stores the real part of the subband
413 *        samples in rSubband
414 *
415 */
416static void
417qmfForwardModulationLP_even( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank  */
418                             FIXP_QMF *timeIn,              /*!< Time Signal */
419                             FIXP_QMF *rSubband )           /*!< Real Output */
420{
421  int i;
422  int L = anaQmf->no_channels;
423  int M = L>>1;
424  int scale;
425  FIXP_QMF accu;
426
427  const FIXP_QMF *timeInTmp1 = (FIXP_QMF *) &timeIn[3 * M];
428  const FIXP_QMF *timeInTmp2 = timeInTmp1;
429  FIXP_QMF *rSubbandTmp = rSubband;
430
431  rSubband[0] = timeIn[3 * M] >> 1;
432
433  for (i = M-1; i != 0; i--) {
434    accu = ((*--timeInTmp1) >> 1) + ((*++timeInTmp2) >> 1);
435    *++rSubbandTmp = accu;
436  }
437
438  timeInTmp1 = &timeIn[2 * M];
439  timeInTmp2 = &timeIn[0];
440  rSubbandTmp = &rSubband[M];
441
442  for (i = L-M; i != 0; i--) {
443    accu = ((*timeInTmp1--) >> 1) - ((*timeInTmp2++) >> 1);
444    *rSubbandTmp++ = accu;
445  }
446
447  dct_III(rSubband, timeIn, L, &scale);
448}
449
450#if !defined(FUNCTION_qmfForwardModulationLP_odd)
451static void
452qmfForwardModulationLP_odd( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank  */
453                            const FIXP_QMF *timeIn,        /*!< Time Signal */
454                            FIXP_QMF *rSubband )           /*!< Real Output */
455{
456  int i;
457  int L = anaQmf->no_channels;
458  int M = L>>1;
459  int shift = (anaQmf->no_channels>>6) + 1;
460
461  for (i = 0; i < M; i++) {
462    rSubband[M + i]     = (timeIn[L - 1 - i]>>1) - (timeIn[i]>>shift);
463    rSubband[M - 1 - i] = (timeIn[L + i]>>1)     + (timeIn[2 * L - 1 - i]>>shift);
464  }
465
466  dct_IV(rSubband, L, &shift);
467}
468#endif /* !defined(FUNCTION_qmfForwardModulationLP_odd) */
469
470
471
472/*!
473 *
474 * \brief Perform complex-valued forward modulation of the time domain
475 *        data of timeIn and stores the real part of the subband
476 *        samples in rSubband, and the imaginary part in iSubband
477 *
478 *        Only the lower bands are obtained (upto anaQmf->lsb). For
479 *        a full bandwidth analysis it is required to set both anaQmf->lsb
480 *        and anaQmf->usb to the amount of QMF bands.
481 *
482 */
483static void
484qmfForwardModulationHQ( HANDLE_QMF_FILTER_BANK anaQmf,     /*!< Handle of Qmf Analysis Bank  */
485                        const FIXP_QMF *RESTRICT timeIn,   /*!< Time Signal */
486                        FIXP_QMF *RESTRICT rSubband,       /*!< Real Output */
487                        FIXP_QMF *RESTRICT iSubband        /*!< Imaginary Output */
488                       )
489{
490  int i;
491  int L = anaQmf->no_channels;
492  int L2 = L<<1;
493  int shift = 0;
494
495  for (i = 0; i < L; i+=2) {
496    FIXP_QMF x0, x1, y0, y1;
497
498    x0 = timeIn[i] >> 1;
499    x1 = timeIn[i+1] >> 1;
500    y0 = timeIn[L2 - 1 - i] >> 1;
501    y1 = timeIn[L2 - 2 - i] >> 1;
502
503    rSubband[i] = x0 - y0;
504    rSubband[i+1] = x1 - y1;
505    iSubband[i] = x0 + y0;
506    iSubband[i+1] = x1 + y1;
507  }
508
509  dct_IV(rSubband, L, &shift);
510  dst_IV(iSubband, L, &shift);
511
512  {
513    {
514      const FIXP_QTW *RESTRICT sbr_t_cos;
515      const FIXP_QTW *RESTRICT sbr_t_sin;
516      sbr_t_cos = anaQmf->t_cos;
517      sbr_t_sin = anaQmf->t_sin;
518
519      for (i = 0; i < anaQmf->lsb; i++) {
520        cplxMult(&iSubband[i], &rSubband[i], iSubband[i], rSubband[i], sbr_t_cos[i], sbr_t_sin[i]);
521      }
522    }
523  }
524}
525
526/*
527 * \brief Perform one QMF slot analysis of the time domain data of timeIn
528 *        with specified stride and stores the real part of the subband
529 *        samples in rSubband, and the imaginary part in iSubband
530 *
531 *        Only the lower bands are obtained (upto anaQmf->lsb). For
532 *        a full bandwidth analysis it is required to set both anaQmf->lsb
533 *        and anaQmf->usb to the amount of QMF bands.
534 */
535void
536qmfAnalysisFilteringSlot( HANDLE_QMF_FILTER_BANK anaQmf,  /*!< Handle of Qmf Synthesis Bank  */
537                          FIXP_QMF      *qmfReal,         /*!< Low and High band, real */
538                          FIXP_QMF      *qmfImag,         /*!< Low and High band, imag */
539                          const INT_PCM *RESTRICT timeIn, /*!< Pointer to input */
540                          const int      stride,          /*!< stride factor of input */
541                          FIXP_QMF      *pWorkBuffer      /*!< pointer to temporal working buffer */
542                         )
543{
544    int i;
545    int offset = anaQmf->no_channels*(QMF_NO_POLY*2-1);
546    /*
547      Feed time signal into oldest anaQmf->no_channels states
548    */
549    {
550      FIXP_QAS *RESTRICT FilterStatesAnaTmp = ((FIXP_QAS*)anaQmf->FilterStates)+offset;
551
552      /* Feed and scale actual time in slot */
553      for(i=anaQmf->no_channels>>1; i!=0; i--) {
554        /* Place INT_PCM value left aligned in scaledTimeIn */
555#if (QAS_BITS==SAMPLE_BITS)
556        *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; timeIn += stride;
557        *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; timeIn += stride;
558#elif (QAS_BITS>SAMPLE_BITS)
559        *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)<<(QAS_BITS-SAMPLE_BITS)); timeIn += stride;
560        *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)<<(QAS_BITS-SAMPLE_BITS)); timeIn += stride;
561#else
562        *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)>>(SAMPLE_BITS-QAS_BITS)); timeIn += stride;
563        *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)>>(SAMPLE_BITS-QAS_BITS)); timeIn += stride;
564#endif
565      }
566    }
567
568    if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) {
569      qmfAnaPrototypeFirSlot_NonSymmetric(
570                              pWorkBuffer,
571                              anaQmf->no_channels,
572                              anaQmf->p_filter,
573                              anaQmf->p_stride,
574                              (FIXP_QAS*)anaQmf->FilterStates
575                            );
576    } else {
577      qmfAnaPrototypeFirSlot( pWorkBuffer,
578                              anaQmf->no_channels,
579                              anaQmf->p_filter,
580                              anaQmf->p_stride,
581                              (FIXP_QAS*)anaQmf->FilterStates
582                            );
583    }
584
585    if (anaQmf->flags & QMF_FLAG_LP) {
586      if (anaQmf->flags & QMF_FLAG_CLDFB)
587        qmfForwardModulationLP_odd( anaQmf,
588                                    pWorkBuffer,
589                                    qmfReal );
590      else
591        qmfForwardModulationLP_even( anaQmf,
592                                     pWorkBuffer,
593                                     qmfReal );
594
595    } else {
596      qmfForwardModulationHQ( anaQmf,
597                              pWorkBuffer,
598                              qmfReal,
599                              qmfImag
600                             );
601    }
602    /*
603      Shift filter states
604
605      Should be realized with modulo adressing on a DSP instead of a true buffer shift
606    */
607    FDKmemmove ((FIXP_QAS*)anaQmf->FilterStates, (FIXP_QAS*)anaQmf->FilterStates+anaQmf->no_channels, offset*sizeof(FIXP_QAS));
608}
609
610
611/*!
612 *
613 * \brief Perform complex-valued subband filtering of the time domain
614 *        data of timeIn and stores the real part of the subband
615 *        samples in rAnalysis, and the imaginary part in iAnalysis
616 * The qmf coefficient table is symmetric. The symmetry is expoited by
617 * shrinking the coefficient table to half the size. The addressing mode
618 * takes care of the symmetries.
619 *
620 * Only the lower bands are obtained (upto anaQmf->lsb). For
621 * a full bandwidth analysis it is required to set both anaQmf->lsb
622 * and anaQmf->usb to the amount of QMF bands.
623 *
624 * \sa PolyphaseFiltering
625 */
626
627void
628qmfAnalysisFiltering( HANDLE_QMF_FILTER_BANK anaQmf,    /*!< Handle of Qmf Analysis Bank */
629                      FIXP_QMF **qmfReal,               /*!< Pointer to real subband slots */
630                      FIXP_QMF **qmfImag,               /*!< Pointer to imag subband slots */
631                      QMF_SCALE_FACTOR *scaleFactor,
632                      const INT_PCM *timeIn,            /*!< Time signal */
633                      const int  stride,
634                      FIXP_QMF  *pWorkBuffer            /*!< pointer to temporal working buffer */
635                      )
636{
637  int i;
638  int no_channels = anaQmf->no_channels;
639
640  scaleFactor->lb_scale = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK;
641  scaleFactor->lb_scale -= anaQmf->filterScale;
642
643  for (i = 0; i < anaQmf->no_col; i++)
644  {
645      FIXP_QMF *qmfImagSlot = NULL;
646
647      if (!(anaQmf->flags & QMF_FLAG_LP)) {
648        qmfImagSlot = qmfImag[i];
649      }
650
651      qmfAnalysisFilteringSlot( anaQmf, qmfReal[i], qmfImagSlot, timeIn , stride, pWorkBuffer );
652
653      timeIn += no_channels*stride;
654
655  } /* no_col loop  i  */
656}
657
658/*!
659 *
660 * \brief Perform low power inverse modulation of the subband
661 *        samples stored in rSubband (real part) and iSubband (imaginary
662 *        part) and stores the result in pWorkBuffer.
663 *
664 */
665inline
666static void
667qmfInverseModulationLP_even( HANDLE_QMF_FILTER_BANK synQmf,   /*!< Handle of Qmf Synthesis Bank  */
668                             const FIXP_QMF *qmfReal,         /*!< Pointer to qmf real subband slot (input) */
669                             const int   scaleFactorLowBand,  /*!< Scalefactor for Low band */
670                             const int   scaleFactorHighBand, /*!< Scalefactor for High band */
671                             FIXP_QMF *pTimeOut               /*!< Pointer to qmf subband slot (output)*/
672                           )
673{
674  int i;
675  int L = synQmf->no_channels;
676  int M = L>>1;
677  int scale;
678  FIXP_QMF tmp;
679  FIXP_QMF *RESTRICT tReal = pTimeOut;
680  FIXP_QMF *RESTRICT tImag = pTimeOut + L;
681
682  /* Move input to output vector with offset */
683  scaleValues(&tReal[0],             &qmfReal[0],             synQmf->lsb,             scaleFactorLowBand);
684  scaleValues(&tReal[0+synQmf->lsb], &qmfReal[0+synQmf->lsb], synQmf->usb-synQmf->lsb, scaleFactorHighBand);
685  FDKmemclear(&tReal[0+synQmf->usb], (L-synQmf->usb)*sizeof(FIXP_QMF));
686
687  /* Dct type-2 transform */
688  dct_II(tReal, tImag, L, &scale);
689
690  /* Expand output and replace inplace the output buffers */
691  tImag[0] = tReal[M];
692  tImag[M] = (FIXP_QMF)0;
693  tmp = tReal [0];
694  tReal [0] = tReal[M];
695  tReal [M] = tmp;
696
697  for (i = 1; i < M/2; i++) {
698    /* Imag */
699    tmp = tReal[L - i];
700    tImag[M - i] =  tmp;
701    tImag[i + M] = -tmp;
702
703    tmp = tReal[M + i];
704    tImag[i] =  tmp;
705    tImag[L - i] = -tmp;
706
707    /* Real */
708    tReal [M + i] = tReal[i];
709    tReal [L - i] = tReal[M - i];
710    tmp = tReal[i];
711    tReal[i] = tReal [M - i];
712    tReal [M - i] = tmp;
713
714  }
715  /* Remaining odd terms */
716  tmp = tReal[M + M/2];
717  tImag[M/2]     =  tmp;
718  tImag[M/2 + M] = -tmp;
719
720  tReal [M + M/2] = tReal[M/2];
721}
722
723inline
724static void
725qmfInverseModulationLP_odd( HANDLE_QMF_FILTER_BANK synQmf,   /*!< Handle of Qmf Synthesis Bank  */
726                            const FIXP_QMF *qmfReal,         /*!< Pointer to qmf real subband slot (input) */
727                            const int scaleFactorLowBand,    /*!< Scalefactor for Low band */
728                            const int scaleFactorHighBand,   /*!< Scalefactor for High band */
729                            FIXP_QMF *pTimeOut               /*!< Pointer to qmf subband slot (output)*/
730                          )
731{
732  int i;
733  int L = synQmf->no_channels;
734  int M = L>>1;
735  int shift = 0;
736
737  /* Move input to output vector with offset */
738  scaleValues(pTimeOut+M,              qmfReal,             synQmf->lsb,             scaleFactorLowBand);
739  scaleValues(pTimeOut+M+synQmf->lsb,  qmfReal+synQmf->lsb, synQmf->usb-synQmf->lsb, scaleFactorHighBand);
740  FDKmemclear(pTimeOut+M+synQmf->usb, (L-synQmf->usb)*sizeof(FIXP_QMF));
741
742  dct_IV(pTimeOut+M, L, &shift);
743  for (i = 0; i < M; i++) {
744    pTimeOut[i]             =  pTimeOut[L - 1 - i];
745    pTimeOut[2 * L - 1 - i] = -pTimeOut[L + i];
746  }
747}
748
749
750/*!
751 *
752 * \brief Perform complex-valued inverse modulation of the subband
753 *        samples stored in rSubband (real part) and iSubband (imaginary
754 *        part) and stores the result in pWorkBuffer.
755 *
756 */
757inline
758static void
759qmfInverseModulationHQ( HANDLE_QMF_FILTER_BANK synQmf,  /*!< Handle of Qmf Synthesis Bank     */
760                        const FIXP_QMF *qmfReal,        /*!< Pointer to qmf real subband slot */
761                        const FIXP_QMF *qmfImag,        /*!< Pointer to qmf imag subband slot */
762                        const int   scaleFactorLowBand, /*!< Scalefactor for Low band         */
763                        const int   scaleFactorHighBand,/*!< Scalefactor for High band        */
764                        FIXP_QMF  *pWorkBuffer          /*!< WorkBuffer (output)              */
765                      )
766{
767  int i;
768  int L = synQmf->no_channels;
769  int M = L>>1;
770  int shift = 0;
771  FIXP_QMF *RESTRICT tReal = pWorkBuffer;
772  FIXP_QMF *RESTRICT tImag = pWorkBuffer+L;
773
774  if (synQmf->flags & QMF_FLAG_CLDFB){
775    for (i = 0; i < synQmf->lsb; i++) {
776      cplxMult(&tImag[i], &tReal[i],
777                scaleValue(qmfImag[i],scaleFactorLowBand), scaleValue(qmfReal[i],scaleFactorLowBand),
778                synQmf->t_cos[i], synQmf->t_sin[i]);
779    }
780    for (; i < synQmf->usb; i++) {
781      cplxMult(&tImag[i], &tReal[i],
782                scaleValue(qmfImag[i],scaleFactorHighBand), scaleValue(qmfReal[i],scaleFactorHighBand),
783                synQmf->t_cos[i], synQmf->t_sin[i]);
784    }
785  }
786
787  if ( (synQmf->flags & QMF_FLAG_CLDFB) == 0) {
788    scaleValues(&tReal[0],             &qmfReal[0],             synQmf->lsb,             scaleFactorLowBand);
789    scaleValues(&tReal[0+synQmf->lsb], &qmfReal[0+synQmf->lsb], synQmf->usb-synQmf->lsb, scaleFactorHighBand);
790    scaleValues(&tImag[0],             &qmfImag[0],             synQmf->lsb,             scaleFactorLowBand);
791    scaleValues(&tImag[0+synQmf->lsb], &qmfImag[0+synQmf->lsb], synQmf->usb-synQmf->lsb, scaleFactorHighBand);
792  }
793
794  FDKmemclear(&tReal[synQmf->usb], (synQmf->no_channels-synQmf->usb)*sizeof(FIXP_QMF));
795  FDKmemclear(&tImag[synQmf->usb], (synQmf->no_channels-synQmf->usb)*sizeof(FIXP_QMF));
796
797  dct_IV(tReal, L, &shift);
798  dst_IV(tImag, L, &shift);
799
800  if (synQmf->flags & QMF_FLAG_CLDFB){
801    for (i = 0; i < M; i++) {
802      FIXP_QMF r1, i1, r2, i2;
803      r1 = tReal[i];
804      i2 = tImag[L - 1 - i];
805      r2 = tReal[L - i - 1];
806      i1 = tImag[i];
807
808      tReal[i] = (r1 - i1)>>1;
809      tImag[L - 1 - i] = -(r1 + i1)>>1;
810      tReal[L - i - 1] =  (r2 - i2)>>1;
811      tImag[i] = -(r2 + i2)>>1;
812    }
813  } else
814  {
815    /* The array accesses are negative to compensate the missing minus sign in the low and hi band gain. */
816    /* 26 cycles on ARM926 */
817    for (i = 0; i < M; i++) {
818      FIXP_QMF r1, i1, r2, i2;
819      r1 = -tReal[i];
820      i2 = -tImag[L - 1 - i];
821      r2 = -tReal[L - i - 1];
822      i1 = -tImag[i];
823
824      tReal[i] = (r1 - i1)>>1;
825      tImag[L - 1 - i] = -(r1 + i1)>>1;
826      tReal[L - i - 1] =  (r2 - i2)>>1;
827      tImag[i] = -(r2 + i2)>>1;
828    }
829  }
830}
831
832void qmfSynthesisFilteringSlot( HANDLE_QMF_FILTER_BANK  synQmf,
833                                const FIXP_QMF  *realSlot,
834                                const FIXP_QMF  *imagSlot,
835                                const int        scaleFactorLowBand,
836                                const int        scaleFactorHighBand,
837                                INT_PCM         *timeOut,
838                                const int        stride,
839                                FIXP_QMF        *pWorkBuffer)
840{
841    if (!(synQmf->flags & QMF_FLAG_LP))
842      qmfInverseModulationHQ ( synQmf,
843                               realSlot,
844                               imagSlot,
845                               scaleFactorLowBand,
846                               scaleFactorHighBand,
847                               pWorkBuffer
848                             );
849    else
850    {
851      if (synQmf->flags & QMF_FLAG_CLDFB) {
852        qmfInverseModulationLP_odd ( synQmf,
853                                 realSlot,
854                                 scaleFactorLowBand,
855                                 scaleFactorHighBand,
856                                 pWorkBuffer
857                               );
858      } else {
859        qmfInverseModulationLP_even ( synQmf,
860                                 realSlot,
861                                 scaleFactorLowBand,
862                                 scaleFactorHighBand,
863                                 pWorkBuffer
864                               );
865      }
866    }
867
868    if (synQmf->flags & QMF_FLAG_NONSYMMETRIC) {
869        qmfSynPrototypeFirSlot_NonSymmetric (
870                                 synQmf,
871                                 pWorkBuffer,
872                                 pWorkBuffer+synQmf->no_channels,
873                                 timeOut,
874                                 stride
875                               );
876    } else {
877        qmfSynPrototypeFirSlot ( synQmf,
878                                 pWorkBuffer,
879                                 pWorkBuffer+synQmf->no_channels,
880                                 timeOut,
881                                 stride
882                               );
883    }
884}
885
886
887/*!
888 *
889 *
890 * \brief Perform complex-valued subband synthesis of the
891 *        low band and the high band and store the
892 *        time domain data in timeOut
893 *
894 * First step: Calculate the proper scaling factor of current
895 * spectral data in qmfReal/qmfImag, old spectral data in the overlap
896 * range and filter states.
897 *
898 * Second step: Perform Frequency-to-Time mapping with inverse
899 * Modulation slot-wise.
900 *
901 * Third step: Perform FIR-filter slot-wise. To save space for filter
902 * states, the MAC operations are executed directly on the filter states
903 * instead of accumulating several products in the accumulator. The
904 * buffer shift at the end of the function should be replaced by a
905 * modulo operation, which is available on some DSPs.
906 *
907 * Last step: Copy the upper part of the spectral data to the overlap buffer.
908 *
909 * The qmf coefficient table is symmetric. The symmetry is exploited by
910 * shrinking the coefficient table to half the size. The addressing mode
911 * takes care of the symmetries.  If the #define #QMFTABLE_FULL is set,
912 * coefficient addressing works on the full table size. The code will be
913 * slightly faster and slightly more compact.
914 *
915 * Workbuffer requirement: 2 x sizeof(**QmfBufferReal) * synQmf->no_channels
916 */
917void
918qmfSynthesisFiltering( HANDLE_QMF_FILTER_BANK synQmf,       /*!< Handle of Qmf Synthesis Bank  */
919                       FIXP_QMF  **QmfBufferReal,           /*!< Low and High band, real */
920                       FIXP_QMF  **QmfBufferImag,           /*!< Low and High band, imag */
921                       const QMF_SCALE_FACTOR *scaleFactor,
922                       const INT   ov_len,                  /*!< split Slot of overlap and actual slots */
923                       INT_PCM    *timeOut,                 /*!< Pointer to output */
924                       const INT   stride,                  /*!< stride factor of output */
925                       FIXP_QMF   *pWorkBuffer              /*!< pointer to temporal working buffer */
926                      )
927{
928  int i;
929  int L = synQmf->no_channels;
930  SCHAR scaleFactorHighBand;
931  SCHAR scaleFactorLowBand_ov, scaleFactorLowBand_no_ov;
932
933  /* adapt scaling */
934  scaleFactorHighBand = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - scaleFactor->hb_scale;
935  scaleFactorLowBand_ov = - ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - scaleFactor->ov_lb_scale;
936  scaleFactorLowBand_no_ov = - ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - scaleFactor->lb_scale;
937
938  for (i = 0; i < synQmf->no_col; i++)  /* ----- no_col loop ----- */
939  {
940    const FIXP_DBL *QmfBufferImagSlot = NULL;
941
942    SCHAR scaleFactorLowBand = (i<ov_len) ? scaleFactorLowBand_ov : scaleFactorLowBand_no_ov;
943
944    if (!(synQmf->flags & QMF_FLAG_LP))
945        QmfBufferImagSlot = QmfBufferImag[i];
946
947    qmfSynthesisFilteringSlot(  synQmf,
948                                QmfBufferReal[i],
949                                QmfBufferImagSlot,
950                                scaleFactorLowBand,
951                                scaleFactorHighBand,
952                                timeOut+(i*L*stride),
953                                stride,
954                                pWorkBuffer);
955  } /* no_col loop  i  */
956
957}
958
959
960/*!
961 *
962 * \brief Create QMF filter bank instance
963 *
964 * \return 0 if successful
965 *
966 */
967static int
968qmfInitFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf,     /*!< Handle to return */
969                   void *pFilterStates,              /*!< Handle to filter states */
970                   int noCols,                       /*!< Number of timeslots per frame */
971                   int lsb,                          /*!< Lower end of QMF frequency range */
972                   int usb,                          /*!< Upper end of QMF frequency range */
973                   int no_channels,                  /*!< Number of channels (bands) */
974                   UINT flags)                       /*!< flags */
975{
976  FDKmemclear(h_Qmf,sizeof(QMF_FILTER_BANK));
977
978  if (flags & QMF_FLAG_MPSLDFB)
979  {
980    return -1;
981  }
982
983  if ( !(flags & QMF_FLAG_MPSLDFB) && (flags & QMF_FLAG_CLDFB) )
984  {
985    flags |= QMF_FLAG_NONSYMMETRIC;
986    h_Qmf->filterScale = QMF_CLDFB_PFT_SCALE;
987
988    h_Qmf->p_stride = 1;
989    switch (no_channels) {
990      case 64:
991        h_Qmf->t_cos = qmf_phaseshift_cos64_cldfb;
992        h_Qmf->t_sin = qmf_phaseshift_sin64_cldfb;
993        h_Qmf->p_filter = qmf_cldfb_640;
994        h_Qmf->FilterSize = 640;
995        break;
996      case 32:
997        h_Qmf->t_cos = qmf_phaseshift_cos32_cldfb;
998        h_Qmf->t_sin = qmf_phaseshift_sin32_cldfb;
999        h_Qmf->p_filter = qmf_cldfb_320;
1000        h_Qmf->FilterSize = 320;
1001        break;
1002      default:
1003        return -1;
1004    }
1005  }
1006
1007  if ( !(flags & QMF_FLAG_MPSLDFB) && ((flags & QMF_FLAG_CLDFB) == 0) )
1008  {
1009    switch (no_channels) {
1010      case 64:
1011        h_Qmf->p_filter = qmf_64;
1012        h_Qmf->t_cos = qmf_phaseshift_cos64;
1013        h_Qmf->t_sin = qmf_phaseshift_sin64;
1014        h_Qmf->p_stride = 1;
1015        h_Qmf->FilterSize = 640;
1016        h_Qmf->filterScale = 0;
1017        break;
1018      case 32:
1019        h_Qmf->p_filter = qmf_64;
1020        h_Qmf->t_cos = qmf_phaseshift_cos32;
1021        h_Qmf->t_sin = qmf_phaseshift_sin32;
1022        h_Qmf->p_stride = 2;
1023        h_Qmf->FilterSize = 640;
1024        h_Qmf->filterScale = 0;
1025        break;
1026      default:
1027        return -1;
1028    }
1029  }
1030
1031  h_Qmf->flags = flags;
1032
1033  h_Qmf->no_channels = no_channels;
1034  h_Qmf->no_col = noCols;
1035
1036  h_Qmf->lsb = lsb;
1037  h_Qmf->usb = fMin(usb, h_Qmf->no_channels);
1038
1039  h_Qmf->FilterStates = (void*)pFilterStates;
1040
1041  h_Qmf->outScalefactor = ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + h_Qmf->filterScale;
1042
1043  if ( (h_Qmf->p_stride == 2)
1044    || ((flags & QMF_FLAG_CLDFB) && (no_channels == 32)) ) {
1045    h_Qmf->outScalefactor -= 1;
1046  }
1047  h_Qmf->outGain = (FIXP_DBL)0x80000000; /* default init value will be not applied */
1048
1049  return (0);
1050}
1051
1052/*!
1053 *
1054 * \brief Adjust synthesis qmf filter states
1055 *
1056 * \return void
1057 *
1058 */
1059static inline void
1060qmfAdaptFilterStates (HANDLE_QMF_FILTER_BANK synQmf,     /*!< Handle of Qmf Filter Bank */
1061                      int scaleFactorDiff)               /*!< Scale factor difference to be applied */
1062{
1063  if (synQmf == NULL || synQmf->FilterStates == NULL) {
1064    return;
1065  }
1066  scaleValues((FIXP_QSS*)synQmf->FilterStates, synQmf->no_channels*(QMF_NO_POLY*2 - 1), scaleFactorDiff);
1067}
1068
1069/*!
1070 *
1071 * \brief Create QMF filter bank instance
1072 *
1073 * Only the lower bands are obtained (upto anaQmf->lsb). For
1074 * a full bandwidth analysis it is required to set both anaQmf->lsb
1075 * and anaQmf->usb to the amount of QMF bands.
1076 *
1077 * \return 0 if succesful
1078 *
1079 */
1080int
1081qmfInitAnalysisFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf,   /*!< Returns handle */
1082                           FIXP_QAS *pFilterStates,        /*!< Handle to filter states */
1083                           int noCols,                     /*!< Number of timeslots per frame */
1084                           int lsb,                        /*!< lower end of QMF */
1085                           int usb,                        /*!< upper end of QMF */
1086                           int no_channels,                /*!< Number of channels (bands) */
1087                           int flags)                      /*!< Low Power flag */
1088{
1089  int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, no_channels, flags);
1090  if ( !(flags & QMF_FLAG_KEEP_STATES) && (h_Qmf->FilterStates != NULL) ) {
1091    FDKmemclear(h_Qmf->FilterStates, (2*QMF_NO_POLY-1)*h_Qmf->no_channels*sizeof(FIXP_QAS));
1092  }
1093
1094  return err;
1095}
1096
1097/*!
1098 *
1099 * \brief Create QMF filter bank instance
1100 *
1101 * Only the lower bands are obtained (upto anaQmf->lsb). For
1102 * a full bandwidth analysis it is required to set both anaQmf->lsb
1103 * and anaQmf->usb to the amount of QMF bands.
1104 *
1105 * \return 0 if succesful
1106 *
1107 */
1108int
1109qmfInitSynthesisFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf,   /*!< Returns handle */
1110                            FIXP_QSS *pFilterStates,        /*!< Handle to filter states */
1111                            int noCols,                     /*!< Number of timeslots per frame */
1112                            int lsb,                        /*!< lower end of QMF */
1113                            int usb,                        /*!< upper end of QMF */
1114                            int no_channels,                /*!< Number of channels (bands) */
1115                            int flags)                      /*!< Low Power flag */
1116{
1117  int oldOutScale = h_Qmf->outScalefactor;
1118  int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, no_channels, flags);
1119  if ( h_Qmf->FilterStates != NULL ) {
1120    if ( !(flags & QMF_FLAG_KEEP_STATES) ) {
1121      FDKmemclear(h_Qmf->FilterStates, (2*QMF_NO_POLY-1)*h_Qmf->no_channels*sizeof(FIXP_QSS));
1122    } else {
1123      qmfAdaptFilterStates(h_Qmf, oldOutScale-h_Qmf->outScalefactor);
1124    }
1125  }
1126  return err;
1127}
1128
1129
1130
1131
1132/*!
1133 *
1134 * \brief Change scale factor for output data and adjust qmf filter states
1135 *
1136 * \return void
1137 *
1138 */
1139void
1140qmfChangeOutScalefactor (HANDLE_QMF_FILTER_BANK synQmf,     /*!< Handle of Qmf Synthesis Bank */
1141                         int outScalefactor                 /*!< New scaling factor for output data */
1142                        )
1143{
1144  if (synQmf == NULL || synQmf->FilterStates == NULL) {
1145    return;
1146  }
1147
1148  /* Add internal filterbank scale */
1149  outScalefactor += ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + synQmf->filterScale;
1150
1151  if ( (synQmf->p_stride == 2)
1152    || ((synQmf->flags & QMF_FLAG_CLDFB) && (synQmf->no_channels == 32)) ) {
1153    outScalefactor -= 1;
1154  }
1155
1156  /* adjust filter states when scale factor has been changed */
1157  if (synQmf->outScalefactor != outScalefactor)
1158  {
1159    int diff;
1160
1161    if (outScalefactor > (SAMPLE_BITS - 1)) {
1162      outScalefactor = SAMPLE_BITS - 1;
1163    } else if (outScalefactor < (1 - SAMPLE_BITS)) {
1164      outScalefactor = 1 - SAMPLE_BITS;
1165    }
1166
1167    diff = synQmf->outScalefactor - outScalefactor;
1168
1169    qmfAdaptFilterStates(synQmf, diff);
1170
1171    /* save new scale factor */
1172    synQmf->outScalefactor = outScalefactor;
1173  }
1174}
1175
1176/*!
1177 *
1178 * \brief Change gain for output data
1179 *
1180 * \return void
1181 *
1182 */
1183void
1184qmfChangeOutGain (HANDLE_QMF_FILTER_BANK synQmf,     /*!< Handle of Qmf Synthesis Bank */
1185                  FIXP_DBL outputGain                /*!< New gain for output data */
1186                 )
1187{
1188  synQmf->outGain = outputGain;
1189}
1190
1191