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