1 
2 /* -----------------------------------------------------------------------------------------------------------
3 Software License for The Fraunhofer FDK AAC Codec Library for Android
4 
5 � Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V.
6   All rights reserved.
7 
8  1.    INTRODUCTION
9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
12 
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16 of the MPEG specifications.
17 
18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
24 
25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27 applications information and documentation.
28 
29 2.    COPYRIGHT LICENSE
30 
31 Redistribution and use in source and binary forms, with or without modification, are permitted without
32 payment of copyright license fees provided that you satisfy the following conditions:
33 
34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35 your modifications thereto in source code form.
36 
37 You must retain the complete text of this software license in the documentation and/or other materials
38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40 modifications thereto to recipients of copies in binary form.
41 
42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43 prior written permission.
44 
45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46 software or your modifications thereto.
47 
48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49 and 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 
53 3.    NO PATENT LICENSE
54 
55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57 respect to this software.
58 
59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60 by appropriate patent licenses.
61 
62 4.    DISCLAIMER
63 
64 This 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
66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69 or business interruption, however caused and on any theory of liability, whether in contract, strict
70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
71 advised of the possibility of such damage.
72 
73 5.    CONTACT INFORMATION
74 
75 Fraunhofer Institute for Integrated Circuits IIS
76 Attention: Audio and Multimedia Departments - FDK AAC LL
77 Am Wolfsmantel 33
78 91058 Erlangen, Germany
79 
80 www.iis.fraunhofer.de/amm
81 amm-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 */
171 static
172 #ifndef FUNCTION_qmfSynPrototypeFirSlot
qmfSynPrototypeFirSlot(HANDLE_QMF_FILTER_BANK qmf,FIXP_QMF * RESTRICT realSlot,FIXP_QMF * RESTRICT imagSlot,INT_PCM * RESTRICT timeOut,int stride)173 void qmfSynPrototypeFirSlot(
174 #else
175 void 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 */
243 static
qmfSynPrototypeFirSlot_NonSymmetric(HANDLE_QMF_FILTER_BANK qmf,FIXP_QMF * RESTRICT realSlot,FIXP_QMF * RESTRICT imagSlot,INT_PCM * RESTRICT timeOut,int stride)244 void 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 */
309 static
qmfAnaPrototypeFirSlot(FIXP_QMF * analysisBuffer,int no_channels,const FIXP_PFT * p_filter,int p_stride,FIXP_QAS * RESTRICT pFilterStates)310 void 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 */
379 static
qmfAnaPrototypeFirSlot_NonSymmetric(FIXP_QMF * analysisBuffer,int no_channels,const FIXP_PFT * p_filter,int p_stride,FIXP_QAS * RESTRICT pFilterStates)380 void 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  */
416 static void
qmfForwardModulationLP_even(HANDLE_QMF_FILTER_BANK anaQmf,FIXP_QMF * timeIn,FIXP_QMF * rSubband)417 qmfForwardModulationLP_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)
451 static void
qmfForwardModulationLP_odd(HANDLE_QMF_FILTER_BANK anaQmf,const FIXP_QMF * timeIn,FIXP_QMF * rSubband)452 qmfForwardModulationLP_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  */
483 static void
qmfForwardModulationHQ(HANDLE_QMF_FILTER_BANK anaQmf,const FIXP_QMF * RESTRICT timeIn,FIXP_QMF * RESTRICT rSubband,FIXP_QMF * RESTRICT iSubband)484 qmfForwardModulationHQ( 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  */
535 void
qmfAnalysisFilteringSlot(HANDLE_QMF_FILTER_BANK anaQmf,FIXP_QMF * qmfReal,FIXP_QMF * qmfImag,const INT_PCM * RESTRICT timeIn,const int stride,FIXP_QMF * pWorkBuffer)536 qmfAnalysisFilteringSlot( 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 
627 void
qmfAnalysisFiltering(HANDLE_QMF_FILTER_BANK anaQmf,FIXP_QMF ** qmfReal,FIXP_QMF ** qmfImag,QMF_SCALE_FACTOR * scaleFactor,const INT_PCM * timeIn,const int stride,FIXP_QMF * pWorkBuffer)628 qmfAnalysisFiltering( 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  */
665 inline
666 static void
qmfInverseModulationLP_even(HANDLE_QMF_FILTER_BANK synQmf,const FIXP_QMF * qmfReal,const int scaleFactorLowBand,const int scaleFactorHighBand,FIXP_QMF * pTimeOut)667 qmfInverseModulationLP_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 
723 inline
724 static void
qmfInverseModulationLP_odd(HANDLE_QMF_FILTER_BANK synQmf,const FIXP_QMF * qmfReal,const int scaleFactorLowBand,const int scaleFactorHighBand,FIXP_QMF * pTimeOut)725 qmfInverseModulationLP_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  */
757 inline
758 static void
qmfInverseModulationHQ(HANDLE_QMF_FILTER_BANK synQmf,const FIXP_QMF * qmfReal,const FIXP_QMF * qmfImag,const int scaleFactorLowBand,const int scaleFactorHighBand,FIXP_QMF * pWorkBuffer)759 qmfInverseModulationHQ( 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 
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)832 void 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  */
917 void
qmfSynthesisFiltering(HANDLE_QMF_FILTER_BANK synQmf,FIXP_QMF ** QmfBufferReal,FIXP_QMF ** QmfBufferImag,const QMF_SCALE_FACTOR * scaleFactor,const INT ov_len,INT_PCM * timeOut,const INT stride,FIXP_QMF * pWorkBuffer)918 qmfSynthesisFiltering( 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  */
967 static int
qmfInitFilterBank(HANDLE_QMF_FILTER_BANK h_Qmf,void * pFilterStates,int noCols,int lsb,int usb,int no_channels,UINT flags)968 qmfInitFilterBank (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         if (flags & QMF_FLAG_DOWNSAMPLED) {
1021           h_Qmf->t_cos = qmf_phaseshift_cos_downsamp32;
1022           h_Qmf->t_sin = qmf_phaseshift_sin_downsamp32;
1023         }
1024         else {
1025         h_Qmf->t_cos = qmf_phaseshift_cos32;
1026         h_Qmf->t_sin = qmf_phaseshift_sin32;
1027         }
1028         h_Qmf->p_stride = 2;
1029         h_Qmf->FilterSize = 640;
1030         h_Qmf->filterScale = 0;
1031         break;
1032       default:
1033         return -1;
1034     }
1035   }
1036 
1037   h_Qmf->flags = flags;
1038 
1039   h_Qmf->no_channels = no_channels;
1040   h_Qmf->no_col = noCols;
1041 
1042   h_Qmf->lsb = lsb;
1043   h_Qmf->usb = fMin(usb, h_Qmf->no_channels);
1044 
1045   h_Qmf->FilterStates = (void*)pFilterStates;
1046 
1047   h_Qmf->outScalefactor = ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + h_Qmf->filterScale;
1048 
1049   if ( (h_Qmf->p_stride == 2)
1050     || ((flags & QMF_FLAG_CLDFB) && (no_channels == 32)) ) {
1051     h_Qmf->outScalefactor -= 1;
1052   }
1053   h_Qmf->outGain = (FIXP_DBL)0x80000000; /* default init value will be not applied */
1054 
1055   return (0);
1056 }
1057 
1058 /*!
1059  *
1060  * \brief Adjust synthesis qmf filter states
1061  *
1062  * \return void
1063  *
1064  */
1065 static inline void
qmfAdaptFilterStates(HANDLE_QMF_FILTER_BANK synQmf,int scaleFactorDiff)1066 qmfAdaptFilterStates (HANDLE_QMF_FILTER_BANK synQmf,     /*!< Handle of Qmf Filter Bank */
1067                       int scaleFactorDiff)               /*!< Scale factor difference to be applied */
1068 {
1069   if (synQmf == NULL || synQmf->FilterStates == NULL) {
1070     return;
1071   }
1072   scaleValues((FIXP_QSS*)synQmf->FilterStates, synQmf->no_channels*(QMF_NO_POLY*2 - 1), scaleFactorDiff);
1073 }
1074 
1075 /*!
1076  *
1077  * \brief Create QMF filter bank instance
1078  *
1079  * Only the lower bands are obtained (upto anaQmf->lsb). For
1080  * a full bandwidth analysis it is required to set both anaQmf->lsb
1081  * and anaQmf->usb to the amount of QMF bands.
1082  *
1083  * \return 0 if succesful
1084  *
1085  */
1086 int
qmfInitAnalysisFilterBank(HANDLE_QMF_FILTER_BANK h_Qmf,FIXP_QAS * pFilterStates,int noCols,int lsb,int usb,int no_channels,int flags)1087 qmfInitAnalysisFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf,   /*!< Returns handle */
1088                            FIXP_QAS *pFilterStates,        /*!< Handle to filter states */
1089                            int noCols,                     /*!< Number of timeslots per frame */
1090                            int lsb,                        /*!< lower end of QMF */
1091                            int usb,                        /*!< upper end of QMF */
1092                            int no_channels,                /*!< Number of channels (bands) */
1093                            int flags)                      /*!< Low Power flag */
1094 {
1095   int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, no_channels, flags);
1096   if ( !(flags & QMF_FLAG_KEEP_STATES) && (h_Qmf->FilterStates != NULL) ) {
1097     FDKmemclear(h_Qmf->FilterStates, (2*QMF_NO_POLY-1)*h_Qmf->no_channels*sizeof(FIXP_QAS));
1098   }
1099 
1100   return err;
1101 }
1102 
1103 /*!
1104  *
1105  * \brief Create QMF filter bank instance
1106  *
1107  * Only the lower bands are obtained (upto anaQmf->lsb). For
1108  * a full bandwidth analysis it is required to set both anaQmf->lsb
1109  * and anaQmf->usb to the amount of QMF bands.
1110  *
1111  * \return 0 if succesful
1112  *
1113  */
1114 int
qmfInitSynthesisFilterBank(HANDLE_QMF_FILTER_BANK h_Qmf,FIXP_QSS * pFilterStates,int noCols,int lsb,int usb,int no_channels,int flags)1115 qmfInitSynthesisFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf,   /*!< Returns handle */
1116                             FIXP_QSS *pFilterStates,        /*!< Handle to filter states */
1117                             int noCols,                     /*!< Number of timeslots per frame */
1118                             int lsb,                        /*!< lower end of QMF */
1119                             int usb,                        /*!< upper end of QMF */
1120                             int no_channels,                /*!< Number of channels (bands) */
1121                             int flags)                      /*!< Low Power flag */
1122 {
1123   int oldOutScale = h_Qmf->outScalefactor;
1124   int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, no_channels, flags);
1125   if ( h_Qmf->FilterStates != NULL ) {
1126     if ( !(flags & QMF_FLAG_KEEP_STATES) ) {
1127       FDKmemclear(h_Qmf->FilterStates, (2*QMF_NO_POLY-1)*h_Qmf->no_channels*sizeof(FIXP_QSS));
1128     } else {
1129       qmfAdaptFilterStates(h_Qmf, oldOutScale-h_Qmf->outScalefactor);
1130     }
1131   }
1132   return err;
1133 }
1134 
1135 
1136 
1137 
1138 /*!
1139  *
1140  * \brief Change scale factor for output data and adjust qmf filter states
1141  *
1142  * \return void
1143  *
1144  */
1145 void
qmfChangeOutScalefactor(HANDLE_QMF_FILTER_BANK synQmf,int outScalefactor)1146 qmfChangeOutScalefactor (HANDLE_QMF_FILTER_BANK synQmf,     /*!< Handle of Qmf Synthesis Bank */
1147                          int outScalefactor                 /*!< New scaling factor for output data */
1148                         )
1149 {
1150   if (synQmf == NULL || synQmf->FilterStates == NULL) {
1151     return;
1152   }
1153 
1154   /* Add internal filterbank scale */
1155   outScalefactor += ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + synQmf->filterScale;
1156 
1157   if ( (synQmf->p_stride == 2)
1158     || ((synQmf->flags & QMF_FLAG_CLDFB) && (synQmf->no_channels == 32)) ) {
1159     outScalefactor -= 1;
1160   }
1161 
1162   /* adjust filter states when scale factor has been changed */
1163   if (synQmf->outScalefactor != outScalefactor)
1164   {
1165     int diff;
1166 
1167     if (outScalefactor > (SAMPLE_BITS - 1)) {
1168       outScalefactor = SAMPLE_BITS - 1;
1169     } else if (outScalefactor < (1 - SAMPLE_BITS)) {
1170       outScalefactor = 1 - SAMPLE_BITS;
1171     }
1172 
1173     diff = synQmf->outScalefactor - outScalefactor;
1174 
1175     qmfAdaptFilterStates(synQmf, diff);
1176 
1177     /* save new scale factor */
1178     synQmf->outScalefactor = outScalefactor;
1179   }
1180 }
1181 
1182 /*!
1183  *
1184  * \brief Change gain for output data
1185  *
1186  * \return void
1187  *
1188  */
1189 void
qmfChangeOutGain(HANDLE_QMF_FILTER_BANK synQmf,FIXP_DBL outputGain)1190 qmfChangeOutGain (HANDLE_QMF_FILTER_BANK synQmf,     /*!< Handle of Qmf Synthesis Bank */
1191                   FIXP_DBL outputGain                /*!< New gain for output data */
1192                  )
1193 {
1194   synQmf->outGain = outputGain;
1195 }
1196 
1197