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