• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2019 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 /*!
151  *
152  * \brief Perform real-valued forward modulation of the time domain
153  *        data of timeIn and stores the real part of the subband
154  *        samples in rSubband
155  *
156  */
qmfForwardModulationLP_even(HANDLE_QMF_FILTER_BANK anaQmf,FIXP_DBL * timeIn,FIXP_DBL * rSubband)157 static void qmfForwardModulationLP_even(
158     HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank  */
159     FIXP_DBL *timeIn,              /*!< Time Signal */
160     FIXP_DBL *rSubband)            /*!< Real Output */
161 {
162   int i;
163   int L = anaQmf->no_channels;
164   int M = L >> 1;
165   int scale = 0;
166   FIXP_DBL accu;
167 
168   const FIXP_DBL *timeInTmp1 = (FIXP_DBL *)&timeIn[3 * M];
169   const FIXP_DBL *timeInTmp2 = timeInTmp1;
170   FIXP_DBL *rSubbandTmp = rSubband;
171 
172   rSubband[0] = timeIn[3 * M] >> 1;
173 
174   for (i = M - 1; i != 0; i--) {
175     accu = ((*--timeInTmp1) >> 1) + ((*++timeInTmp2) >> 1);
176     *++rSubbandTmp = accu;
177   }
178 
179   timeInTmp1 = &timeIn[2 * M];
180   timeInTmp2 = &timeIn[0];
181   rSubbandTmp = &rSubband[M];
182 
183   for (i = L - M; i != 0; i--) {
184     accu = ((*timeInTmp1--) >> 1) - ((*timeInTmp2++) >> 1);
185     *rSubbandTmp++ = accu;
186   }
187 
188   dct_III(rSubband, timeIn, L, &scale);
189 }
190 
191 #if !defined(FUNCTION_qmfForwardModulationLP_odd)
qmfForwardModulationLP_odd(HANDLE_QMF_FILTER_BANK anaQmf,const FIXP_DBL * timeIn,FIXP_DBL * rSubband)192 static void qmfForwardModulationLP_odd(
193     HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank  */
194     const FIXP_DBL *timeIn,        /*!< Time Signal */
195     FIXP_DBL *rSubband)            /*!< Real Output */
196 {
197   int i;
198   int L = anaQmf->no_channels;
199   int M = L >> 1;
200   int shift = (anaQmf->no_channels >> 6) + 1;
201 
202   for (i = 0; i < M; i++) {
203     rSubband[M + i] = (timeIn[L - 1 - i] >> 1) - (timeIn[i] >> shift);
204     rSubband[M - 1 - i] =
205         (timeIn[L + i] >> 1) + (timeIn[2 * L - 1 - i] >> shift);
206   }
207 
208   dct_IV(rSubband, L, &shift);
209 }
210 #endif /* !defined(FUNCTION_qmfForwardModulationLP_odd) */
211 
212 /*!
213  *
214  * \brief Perform complex-valued forward modulation of the time domain
215  *        data of timeIn and stores the real part of the subband
216  *        samples in rSubband, and the imaginary part in iSubband
217  *
218  *
219  */
220 #if !defined(FUNCTION_qmfForwardModulationHQ)
qmfForwardModulationHQ(HANDLE_QMF_FILTER_BANK anaQmf,const FIXP_DBL * RESTRICT timeIn,FIXP_DBL * RESTRICT rSubband,FIXP_DBL * RESTRICT iSubband)221 static void qmfForwardModulationHQ(
222     HANDLE_QMF_FILTER_BANK anaQmf,   /*!< Handle of Qmf Analysis Bank  */
223     const FIXP_DBL *RESTRICT timeIn, /*!< Time Signal */
224     FIXP_DBL *RESTRICT rSubband,     /*!< Real Output */
225     FIXP_DBL *RESTRICT iSubband      /*!< Imaginary Output */
226 ) {
227   int i;
228   int L = anaQmf->no_channels;
229   int L2 = L << 1;
230   int shift = 0;
231 
232   /* Time advance by one sample, which is equivalent to the complex
233      rotation at the end of the analysis. Works only for STD mode. */
234   if ((L == 64) && !(anaQmf->flags & (QMF_FLAG_CLDFB | QMF_FLAG_MPSLDFB))) {
235     FIXP_DBL x, y;
236 
237     /*rSubband[0] = u[1] + u[0]*/
238     /*iSubband[0] = u[1] - u[0]*/
239     x = timeIn[1] >> 1;
240     y = timeIn[0];
241     rSubband[0] = x + (y >> 1);
242     iSubband[0] = x - (y >> 1);
243 
244     /*rSubband[n] = u[n+1] - u[2M-n], n=1,...,M-1*/
245     /*iSubband[n] = u[n+1] + u[2M-n], n=1,...,M-1*/
246     for (i = 1; i < L; i++) {
247       x = timeIn[i + 1] >> 1; /*u[n+1]  */
248       y = timeIn[L2 - i];     /*u[2M-n] */
249       rSubband[i] = x - (y >> 1);
250       iSubband[i] = x + (y >> 1);
251     }
252   } else {
253     for (i = 0; i < L; i += 2) {
254       FIXP_DBL x0, x1, y0, y1;
255 
256       x0 = timeIn[i + 0] >> 1;
257       x1 = timeIn[i + 1] >> 1;
258       y0 = timeIn[L2 - 1 - i];
259       y1 = timeIn[L2 - 2 - i];
260 
261       rSubband[i + 0] = x0 - (y0 >> 1);
262       rSubband[i + 1] = x1 - (y1 >> 1);
263       iSubband[i + 0] = x0 + (y0 >> 1);
264       iSubband[i + 1] = x1 + (y1 >> 1);
265     }
266   }
267 
268   dct_IV(rSubband, L, &shift);
269   dst_IV(iSubband, L, &shift);
270 
271   /* Do the complex rotation except for the case of 64 bands (in STD mode). */
272   if ((L != 64) || (anaQmf->flags & (QMF_FLAG_CLDFB | QMF_FLAG_MPSLDFB))) {
273     if (anaQmf->flags & QMF_FLAG_MPSLDFB_OPTIMIZE_MODULATION) {
274       FIXP_DBL iBand;
275       for (i = 0; i < fMin(anaQmf->lsb, L); i += 2) {
276         iBand = rSubband[i];
277         rSubband[i] = -iSubband[i];
278         iSubband[i] = iBand;
279 
280         iBand = -rSubband[i + 1];
281         rSubband[i + 1] = iSubband[i + 1];
282         iSubband[i + 1] = iBand;
283       }
284     } else {
285       const FIXP_QTW *sbr_t_cos;
286       const FIXP_QTW *sbr_t_sin;
287       const int len = L; /* was len = fMin(anaQmf->lsb, L) but in case of USAC
288                             the signal above lsb is actually needed in some
289                             cases (HBE?) */
290       sbr_t_cos = anaQmf->t_cos;
291       sbr_t_sin = anaQmf->t_sin;
292 
293       for (i = 0; i < len; i++) {
294         cplxMult(&iSubband[i], &rSubband[i], iSubband[i], rSubband[i],
295                  sbr_t_cos[i], sbr_t_sin[i]);
296       }
297     }
298   }
299 }
300 #endif /* FUNCTION_qmfForwardModulationHQ */
301 
302 /*!
303  *
304  * \brief Perform low power inverse modulation of the subband
305  *        samples stored in rSubband (real part) and iSubband (imaginary
306  *        part) and stores the result in pWorkBuffer.
307  *
308  */
qmfInverseModulationLP_even(HANDLE_QMF_FILTER_BANK synQmf,const FIXP_DBL * qmfReal,const int scaleFactorLowBand,const int scaleFactorHighBand,FIXP_DBL * pTimeOut)309 inline static void qmfInverseModulationLP_even(
310     HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank  */
311     const FIXP_DBL *qmfReal, /*!< Pointer to qmf real subband slot (input) */
312     const int scaleFactorLowBand,  /*!< Scalefactor for Low band */
313     const int scaleFactorHighBand, /*!< Scalefactor for High band */
314     FIXP_DBL *pTimeOut             /*!< Pointer to qmf subband slot (output)*/
315 ) {
316   int i;
317   int L = synQmf->no_channels;
318   int M = L >> 1;
319   int scale = 0;
320   FIXP_DBL tmp;
321   FIXP_DBL *RESTRICT tReal = pTimeOut;
322   FIXP_DBL *RESTRICT tImag = pTimeOut + L;
323 
324   /* Move input to output vector with offset */
325   scaleValuesSaturate(&tReal[0], &qmfReal[0], synQmf->lsb, scaleFactorLowBand);
326   scaleValuesSaturate(&tReal[0 + synQmf->lsb], &qmfReal[0 + synQmf->lsb],
327                       synQmf->usb - synQmf->lsb, scaleFactorHighBand);
328   FDKmemclear(&tReal[0 + synQmf->usb], (L - synQmf->usb) * sizeof(FIXP_DBL));
329 
330   /* Dct type-2 transform */
331   dct_II(tReal, tImag, L, &scale);
332 
333   /* Expand output and replace inplace the output buffers */
334   tImag[0] = tReal[M];
335   tImag[M] = (FIXP_DBL)0;
336   tmp = tReal[0];
337   tReal[0] = tReal[M];
338   tReal[M] = tmp;
339 
340   for (i = 1; i < M / 2; i++) {
341     /* Imag */
342     tmp = tReal[L - i];
343     tImag[M - i] = tmp;
344     tImag[i + M] = -tmp;
345 
346     tmp = tReal[M + i];
347     tImag[i] = tmp;
348     tImag[L - i] = -tmp;
349 
350     /* Real */
351     tReal[M + i] = tReal[i];
352     tReal[L - i] = tReal[M - i];
353     tmp = tReal[i];
354     tReal[i] = tReal[M - i];
355     tReal[M - i] = tmp;
356   }
357   /* Remaining odd terms */
358   tmp = tReal[M + M / 2];
359   tImag[M / 2] = tmp;
360   tImag[M / 2 + M] = -tmp;
361 
362   tReal[M + M / 2] = tReal[M / 2];
363 }
364 
qmfInverseModulationLP_odd(HANDLE_QMF_FILTER_BANK synQmf,const FIXP_DBL * qmfReal,const int scaleFactorLowBand,const int scaleFactorHighBand,FIXP_DBL * pTimeOut)365 inline static void qmfInverseModulationLP_odd(
366     HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank  */
367     const FIXP_DBL *qmfReal, /*!< Pointer to qmf real subband slot (input) */
368     const int scaleFactorLowBand,  /*!< Scalefactor for Low band */
369     const int scaleFactorHighBand, /*!< Scalefactor for High band */
370     FIXP_DBL *pTimeOut             /*!< Pointer to qmf subband slot (output)*/
371 ) {
372   int i;
373   int L = synQmf->no_channels;
374   int M = L >> 1;
375   int shift = 0;
376 
377   /* Move input to output vector with offset */
378   scaleValuesSaturate(pTimeOut + M, qmfReal, synQmf->lsb, scaleFactorLowBand);
379   scaleValuesSaturate(pTimeOut + M + synQmf->lsb, qmfReal + synQmf->lsb,
380                       synQmf->usb - synQmf->lsb, scaleFactorHighBand);
381   FDKmemclear(pTimeOut + M + synQmf->usb, (L - synQmf->usb) * sizeof(FIXP_DBL));
382 
383   dct_IV(pTimeOut + M, L, &shift);
384   for (i = 0; i < M; i++) {
385     pTimeOut[i] = pTimeOut[L - 1 - i];
386     pTimeOut[2 * L - 1 - i] = -pTimeOut[L + i];
387   }
388 }
389 
390 #ifndef FUNCTION_qmfInverseModulationHQ
391 /*!
392  *
393  * \brief Perform complex-valued inverse modulation of the subband
394  *        samples stored in rSubband (real part) and iSubband (imaginary
395  *        part) and stores the result in pWorkBuffer.
396  *
397  */
qmfInverseModulationHQ(HANDLE_QMF_FILTER_BANK synQmf,const FIXP_DBL * qmfReal,const FIXP_DBL * qmfImag,const int scaleFactorLowBand,const int scaleFactorHighBand,FIXP_DBL * pWorkBuffer)398 inline static void qmfInverseModulationHQ(
399     HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank     */
400     const FIXP_DBL *qmfReal,       /*!< Pointer to qmf real subband slot */
401     const FIXP_DBL *qmfImag,       /*!< Pointer to qmf imag subband slot */
402     const int scaleFactorLowBand,  /*!< Scalefactor for Low band         */
403     const int scaleFactorHighBand, /*!< Scalefactor for High band        */
404     FIXP_DBL *pWorkBuffer          /*!< WorkBuffer (output)              */
405 ) {
406   int i;
407   int L = synQmf->no_channels;
408   int M = L >> 1;
409   int shift = 0;
410   FIXP_DBL *RESTRICT tReal = pWorkBuffer;
411   FIXP_DBL *RESTRICT tImag = pWorkBuffer + L;
412 
413   if (synQmf->flags & QMF_FLAG_CLDFB) {
414     for (i = 0; i < synQmf->usb; i++) {
415       cplxMultDiv2(&tImag[i], &tReal[i], qmfImag[i], qmfReal[i],
416                    synQmf->t_cos[i], synQmf->t_sin[i]);
417     }
418     scaleValuesSaturate(&tReal[0], synQmf->lsb, scaleFactorLowBand + 1);
419     scaleValuesSaturate(&tReal[0 + synQmf->lsb], synQmf->usb - synQmf->lsb,
420                         scaleFactorHighBand + 1);
421     scaleValuesSaturate(&tImag[0], synQmf->lsb, scaleFactorLowBand + 1);
422     scaleValuesSaturate(&tImag[0 + synQmf->lsb], synQmf->usb - synQmf->lsb,
423                         scaleFactorHighBand + 1);
424   }
425 
426   if ((synQmf->flags & QMF_FLAG_CLDFB) == 0) {
427     scaleValuesSaturate(&tReal[0], &qmfReal[0], synQmf->lsb,
428                         scaleFactorLowBand);
429     scaleValuesSaturate(&tReal[0 + synQmf->lsb], &qmfReal[0 + synQmf->lsb],
430                         synQmf->usb - synQmf->lsb, scaleFactorHighBand);
431     scaleValuesSaturate(&tImag[0], &qmfImag[0], synQmf->lsb,
432                         scaleFactorLowBand);
433     scaleValuesSaturate(&tImag[0 + synQmf->lsb], &qmfImag[0 + synQmf->lsb],
434                         synQmf->usb - synQmf->lsb, scaleFactorHighBand);
435   }
436 
437   FDKmemclear(&tReal[synQmf->usb],
438               (synQmf->no_channels - synQmf->usb) * sizeof(FIXP_DBL));
439   FDKmemclear(&tImag[synQmf->usb],
440               (synQmf->no_channels - synQmf->usb) * sizeof(FIXP_DBL));
441 
442   dct_IV(tReal, L, &shift);
443   dst_IV(tImag, L, &shift);
444 
445   if (synQmf->flags & QMF_FLAG_CLDFB) {
446     for (i = 0; i < M; i++) {
447       FIXP_DBL r1, i1, r2, i2;
448       r1 = tReal[i];
449       i2 = tImag[L - 1 - i];
450       r2 = tReal[L - i - 1];
451       i1 = tImag[i];
452 
453       tReal[i] = (r1 - i1) >> 1;
454       tImag[L - 1 - i] = -(r1 + i1) >> 1;
455       tReal[L - i - 1] = (r2 - i2) >> 1;
456       tImag[i] = -(r2 + i2) >> 1;
457     }
458   } else {
459     /* The array accesses are negative to compensate the missing minus sign in
460      * the low and hi band gain. */
461     /* 26 cycles on ARM926 */
462     for (i = 0; i < M; i++) {
463       FIXP_DBL r1, i1, r2, i2;
464       r1 = -tReal[i];
465       i2 = -tImag[L - 1 - i];
466       r2 = -tReal[L - i - 1];
467       i1 = -tImag[i];
468 
469       tReal[i] = (r1 - i1) >> 1;
470       tImag[L - 1 - i] = -(r1 + i1) >> 1;
471       tReal[L - i - 1] = (r2 - i2) >> 1;
472       tImag[i] = -(r2 + i2) >> 1;
473     }
474   }
475 }
476 #endif /* #ifndef FUNCTION_qmfInverseModulationHQ */
477 
478 /*!
479  *
480  * \brief Create QMF filter bank instance
481  *
482  * \return 0 if successful
483  *
484  */
qmfInitFilterBank(HANDLE_QMF_FILTER_BANK h_Qmf,void * pFilterStates,int noCols,int lsb,int usb,int no_channels,UINT flags,int synflag)485 static int qmfInitFilterBank(
486     HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Handle to return */
487     void *pFilterStates,          /*!< Handle to filter states */
488     int noCols,                   /*!< Number of timeslots per frame */
489     int lsb,                      /*!< Lower end of QMF frequency range */
490     int usb,                      /*!< Upper end of QMF frequency range */
491     int no_channels,              /*!< Number of channels (bands) */
492     UINT flags,                   /*!< flags */
493     int synflag)                  /*!< 1: synthesis; 0: analysis */
494 {
495   FDKmemclear(h_Qmf, sizeof(QMF_FILTER_BANK));
496 
497   if (flags & QMF_FLAG_MPSLDFB) {
498     flags |= QMF_FLAG_NONSYMMETRIC;
499     flags |= QMF_FLAG_MPSLDFB_OPTIMIZE_MODULATION;
500 
501     h_Qmf->t_cos = NULL;
502     h_Qmf->t_sin = NULL;
503     h_Qmf->filterScale = QMF_MPSLDFB_PFT_SCALE;
504     h_Qmf->p_stride = 1;
505 
506     switch (no_channels) {
507       case 64:
508         h_Qmf->p_filter = qmf_mpsldfb_640;
509         h_Qmf->FilterSize = 640;
510         break;
511       case 32:
512         h_Qmf->p_filter = qmf_mpsldfb_320;
513         h_Qmf->FilterSize = 320;
514         break;
515       default:
516         return -1;
517     }
518   }
519 
520   if (!(flags & QMF_FLAG_MPSLDFB) && (flags & QMF_FLAG_CLDFB)) {
521     flags |= QMF_FLAG_NONSYMMETRIC;
522     h_Qmf->filterScale = QMF_CLDFB_PFT_SCALE;
523 
524     h_Qmf->p_stride = 1;
525     switch (no_channels) {
526       case 64:
527         h_Qmf->t_cos = qmf_phaseshift_cos64_cldfb;
528         h_Qmf->t_sin = qmf_phaseshift_sin64_cldfb;
529         h_Qmf->p_filter = qmf_cldfb_640;
530         h_Qmf->FilterSize = 640;
531         break;
532       case 32:
533         h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos32_cldfb_syn
534                                  : qmf_phaseshift_cos32_cldfb_ana;
535         h_Qmf->t_sin = qmf_phaseshift_sin32_cldfb;
536         h_Qmf->p_filter = qmf_cldfb_320;
537         h_Qmf->FilterSize = 320;
538         break;
539       case 16:
540         h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos16_cldfb_syn
541                                  : qmf_phaseshift_cos16_cldfb_ana;
542         h_Qmf->t_sin = qmf_phaseshift_sin16_cldfb;
543         h_Qmf->p_filter = qmf_cldfb_160;
544         h_Qmf->FilterSize = 160;
545         break;
546       case 8:
547         h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos8_cldfb_syn
548                                  : qmf_phaseshift_cos8_cldfb_ana;
549         h_Qmf->t_sin = qmf_phaseshift_sin8_cldfb;
550         h_Qmf->p_filter = qmf_cldfb_80;
551         h_Qmf->FilterSize = 80;
552         break;
553       default:
554         return -1;
555     }
556   }
557 
558   if (!(flags & QMF_FLAG_MPSLDFB) && ((flags & QMF_FLAG_CLDFB) == 0)) {
559     switch (no_channels) {
560       case 64:
561         h_Qmf->p_filter = qmf_pfilt640;
562         h_Qmf->t_cos = qmf_phaseshift_cos64;
563         h_Qmf->t_sin = qmf_phaseshift_sin64;
564         h_Qmf->p_stride = 1;
565         h_Qmf->FilterSize = 640;
566         h_Qmf->filterScale = 0;
567         break;
568       case 40:
569         if (synflag) {
570           break;
571         } else {
572           h_Qmf->p_filter = qmf_pfilt400; /* Scaling factor 0.8 */
573           h_Qmf->t_cos = qmf_phaseshift_cos40;
574           h_Qmf->t_sin = qmf_phaseshift_sin40;
575           h_Qmf->filterScale = 1;
576           h_Qmf->p_stride = 1;
577           h_Qmf->FilterSize = no_channels * 10;
578         }
579         break;
580       case 32:
581         h_Qmf->p_filter = qmf_pfilt640;
582         if (flags & QMF_FLAG_DOWNSAMPLED) {
583           h_Qmf->t_cos = qmf_phaseshift_cos_downsamp32;
584           h_Qmf->t_sin = qmf_phaseshift_sin_downsamp32;
585         } else {
586           h_Qmf->t_cos = qmf_phaseshift_cos32;
587           h_Qmf->t_sin = qmf_phaseshift_sin32;
588         }
589         h_Qmf->p_stride = 2;
590         h_Qmf->FilterSize = 640;
591         h_Qmf->filterScale = 0;
592         break;
593       case 20:
594         h_Qmf->p_filter = qmf_pfilt200;
595         h_Qmf->p_stride = 1;
596         h_Qmf->FilterSize = 200;
597         h_Qmf->filterScale = 0;
598         break;
599       case 12:
600         h_Qmf->p_filter = qmf_pfilt120;
601         h_Qmf->p_stride = 1;
602         h_Qmf->FilterSize = 120;
603         h_Qmf->filterScale = 0;
604         break;
605       case 8:
606         h_Qmf->p_filter = qmf_pfilt640;
607         h_Qmf->p_stride = 8;
608         h_Qmf->FilterSize = 640;
609         h_Qmf->filterScale = 0;
610         break;
611       case 16:
612         h_Qmf->p_filter = qmf_pfilt640;
613         h_Qmf->t_cos = qmf_phaseshift_cos16;
614         h_Qmf->t_sin = qmf_phaseshift_sin16;
615         h_Qmf->p_stride = 4;
616         h_Qmf->FilterSize = 640;
617         h_Qmf->filterScale = 0;
618         break;
619       case 24:
620         h_Qmf->p_filter = qmf_pfilt240;
621         h_Qmf->t_cos = qmf_phaseshift_cos24;
622         h_Qmf->t_sin = qmf_phaseshift_sin24;
623         h_Qmf->p_stride = 1;
624         h_Qmf->FilterSize = 240;
625         h_Qmf->filterScale = 1;
626         break;
627       default:
628         return -1;
629     }
630   }
631 
632   h_Qmf->synScalefactor = h_Qmf->filterScale;
633   // DCT|DST dependency
634   switch (no_channels) {
635     case 128:
636       h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + 1;
637       break;
638     case 40: {
639       h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1;
640     } break;
641     case 64:
642       h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK;
643       break;
644     case 8:
645       h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 3;
646       break;
647     case 12:
648       h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK;
649       break;
650     case 20:
651       h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + 1;
652       break;
653     case 32:
654       h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1;
655       break;
656     case 16:
657       h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 2;
658       break;
659     case 24:
660       h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1;
661       break;
662     default:
663       return -1;
664   }
665 
666   h_Qmf->flags = flags;
667 
668   h_Qmf->no_channels = no_channels;
669   h_Qmf->no_col = noCols;
670 
671   h_Qmf->lsb = fMin(lsb, h_Qmf->no_channels);
672   h_Qmf->usb = synflag
673                    ? fMin(usb, h_Qmf->no_channels)
674                    : usb; /* was: h_Qmf->usb = fMin(usb, h_Qmf->no_channels); */
675 
676   h_Qmf->FilterStates = (void *)pFilterStates;
677 
678   h_Qmf->outScalefactor =
679       (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + h_Qmf->filterScale) +
680       h_Qmf->synScalefactor;
681 
682   h_Qmf->outGain_m =
683       (FIXP_DBL)0x80000000; /* default init value will be not applied */
684   h_Qmf->outGain_e = 0;
685 
686   return (0);
687 }
688 
689 /*!
690  *
691  * \brief Adjust synthesis qmf filter states
692  *
693  * \return void
694  *
695  */
qmfAdaptFilterStates(HANDLE_QMF_FILTER_BANK synQmf,int scaleFactorDiff)696 static inline void qmfAdaptFilterStates(
697     HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Filter Bank */
698     int scaleFactorDiff)           /*!< Scale factor difference to be applied */
699 {
700   if (synQmf == NULL || synQmf->FilterStates == NULL) {
701     return;
702   }
703   if (scaleFactorDiff > 0) {
704     scaleValuesSaturate((FIXP_QSS *)synQmf->FilterStates,
705                         synQmf->no_channels * (QMF_NO_POLY * 2 - 1),
706                         scaleFactorDiff);
707   } else {
708     scaleValues((FIXP_QSS *)synQmf->FilterStates,
709                 synQmf->no_channels * (QMF_NO_POLY * 2 - 1), scaleFactorDiff);
710   }
711 }
712 
713 /*!
714  *
715  * \brief Create QMF filter bank instance
716  *
717  *
718  * \return 0 if succesful
719  *
720  */
qmfInitSynthesisFilterBank(HANDLE_QMF_FILTER_BANK h_Qmf,FIXP_QSS * pFilterStates,int noCols,int lsb,int usb,int no_channels,int flags)721 int qmfInitSynthesisFilterBank(
722     HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */
723     FIXP_QSS *pFilterStates,      /*!< Handle to filter states */
724     int noCols,                   /*!< Number of timeslots per frame */
725     int lsb,                      /*!< lower end of QMF */
726     int usb,                      /*!< upper end of QMF */
727     int no_channels,              /*!< Number of channels (bands) */
728     int flags)                    /*!< Low Power flag */
729 {
730   int oldOutScale = h_Qmf->outScalefactor;
731   int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb,
732                               no_channels, flags, 1);
733   if (h_Qmf->FilterStates != NULL) {
734     if (!(flags & QMF_FLAG_KEEP_STATES)) {
735       FDKmemclear(
736           h_Qmf->FilterStates,
737           (2 * QMF_NO_POLY - 1) * h_Qmf->no_channels * sizeof(FIXP_QSS));
738     } else {
739       qmfAdaptFilterStates(h_Qmf, oldOutScale - h_Qmf->outScalefactor);
740     }
741   }
742 
743   FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->lsb);
744   FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->usb);
745 
746   return err;
747 }
748 
749 /*!
750  *
751  * \brief Change scale factor for output data and adjust qmf filter states
752  *
753  * \return void
754  *
755  */
qmfChangeOutScalefactor(HANDLE_QMF_FILTER_BANK synQmf,int outScalefactor)756 void qmfChangeOutScalefactor(
757     HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */
758     int outScalefactor             /*!< New scaling factor for output data */
759 ) {
760   if (synQmf == NULL) {
761     return;
762   }
763 
764   /* Add internal filterbank scale */
765   outScalefactor +=
766       (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + synQmf->filterScale) +
767       synQmf->synScalefactor;
768 
769   /* adjust filter states when scale factor has been changed */
770   if (synQmf->outScalefactor != outScalefactor) {
771     int diff;
772 
773     diff = synQmf->outScalefactor - outScalefactor;
774 
775     qmfAdaptFilterStates(synQmf, diff);
776 
777     /* save new scale factor */
778     synQmf->outScalefactor = outScalefactor;
779   }
780 }
781 
782 /*!
783  *
784  * \brief Get scale factor change which was set by qmfChangeOutScalefactor()
785  *
786  * \return scaleFactor
787  *
788  */
qmfGetOutScalefactor(HANDLE_QMF_FILTER_BANK synQmf)789 int qmfGetOutScalefactor(
790     HANDLE_QMF_FILTER_BANK synQmf) /*!< Handle of Qmf Synthesis Bank */
791 {
792   int scaleFactor = synQmf->outScalefactor
793                         ? (synQmf->outScalefactor -
794                            (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK +
795                             synQmf->filterScale + synQmf->synScalefactor))
796                         : 0;
797   return scaleFactor;
798 }
799 
800 /*!
801  *
802  * \brief Change gain for output data
803  *
804  * \return void
805  *
806  */
qmfChangeOutGain(HANDLE_QMF_FILTER_BANK synQmf,FIXP_DBL outputGain,int outputGainScale)807 void qmfChangeOutGain(
808     HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */
809     FIXP_DBL outputGain,           /*!< New gain for output data (mantissa) */
810     int outputGainScale            /*!< New gain for output data (exponent) */
811 ) {
812   synQmf->outGain_m = outputGain;
813   synQmf->outGain_e = outputGainScale;
814 }
815 
816 #define INT_PCM_QMFOUT INT_PCM
817 #define SAMPLE_BITS_QMFOUT SAMPLE_BITS
818 #include "qmf_pcm.h"
819 #if SAMPLE_BITS == 16
820   /* also create a 32 bit output version */
821 #undef INT_PCM_QMFOUT
822 #undef SAMPLE_BITS_QMFOUT
823 #undef QMF_PCM_H
824 #undef FIXP_QAS
825 #undef QAS_BITS
826 #undef INT_PCM_QMFIN
827 #define INT_PCM_QMFOUT LONG
828 #define SAMPLE_BITS_QMFOUT 32
829 #define FIXP_QAS FIXP_DBL
830 #define QAS_BITS 32
831 #define INT_PCM_QMFIN LONG
832 #include "qmf_pcm.h"
833 #endif
834