2 /* -----------------------------------------------------------------------------------------------------------
3 Software License for The Fraunhofer FDK AAC Codec Library for Android
5 © Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16 of the MPEG specifications.
18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27 applications information and documentation.
31 Redistribution and use in source and binary forms, with or without modification, are permitted without
32 payment of copyright license fees provided that you satisfy the following conditions:
34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35 your modifications thereto in source code form.
37 You must retain the complete text of this software license in the documentation and/or other materials
38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40 modifications thereto to recipients of copies in binary form.
42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43 prior written permission.
45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46 software or your modifications thereto.
48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49 and the date of any change. For modified versions of the FDK AAC Codec, the term
50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57 respect to this software.
59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60 by appropriate patent licenses.
64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69 or business interruption, however caused and on any theory of liability, whether in contract, strict
70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
71 advised of the possibility of such damage.
73 5. CONTACT INFORMATION
75 Fraunhofer Institute for Integrated Circuits IIS
76 Attention: Audio and Multimedia Departments - FDK AAC LL
78 91058 Erlangen, Germany
80 www.iis.fraunhofer.de/amm
81 amm-info@iis.fraunhofer.de
82 ----------------------------------------------------------------------------------------------------------- */
84 /******************************** Fraunhofer IIS ***************************
86 Author(s): Markus Lohwasser, Josef Hoepfl, Manuel Jander
87 Description: QMF filterbank
89 ******************************************************************************/
93 \brief Complex qmf analysis/synthesis,
94 This module contains the qmf filterbank for analysis [ cplxAnalysisQmfFiltering() ] and
95 synthesis [ cplxSynthesisQmfFiltering() ]. It is a polyphase implementation of a complex
96 exponential modulated filter bank. The analysis part usually runs at half the sample rate
97 than the synthesis part. (So called "dual-rate" mode.)
99 The coefficients of the prototype filter are specified in #sbr_qmf_64_640 (in sbr_rom.cpp).
100 Thus only a 64 channel version (32 on the analysis side) with a 640 tap prototype filter
103 \anchor PolyphaseFiltering <h2>About polyphase filtering</h2>
104 The polyphase implementation of a filterbank requires filtering at the input and output.
105 This is implemented as part of cplxAnalysisQmfFiltering() and cplxSynthesisQmfFiltering().
106 The implementation requires the filter coefficients in a specific structure as described in
107 #sbr_qmf_64_640_qmf (in sbr_rom.cpp).
109 This module comprises the computationally most expensive functions of the SBR decoder. The accuracy of
110 computations is also important and has a direct impact on the overall sound quality. Therefore a special
111 test program is available which can be used to only test the filterbank: main_audio.cpp
113 This modules also uses scaling of data to provide better SNR on fixed-point processors. See #QMF_SCALE_FACTOR (in sbr_scale.h) for details.
114 An interesting note: The function getScalefactor() can constitute a significant amount of computational complexity - very much depending on the
115 bitrate. Since it is a rather small function, effective assembler optimization might be possible.
122 #include "fixpoint_math.h"
125 #ifdef QMFSYN_STATES_16BIT
127 #define FX_DBL2FX_QSS(x) ((FIXP_QSS) ((x)>>(DFRACT_BITS-QSS_BITS-QSSCALE) ))
128 #define FX_QSS2FX_DBL(x) ((FIXP_DBL)((LONG)x)<<(DFRACT_BITS-QSS_BITS-QSSCALE))
131 #define FX_DBL2FX_QSS(x) (x)
132 #define FX_QSS2FX_DBL(x) (x)
137 #include "arm/qmf_arm.cpp"
142 * \brief Algorithmic scaling in sbrForwardModulation()
144 * The scaling in sbrForwardModulation() is caused by:
146 * \li 1 R_SHIFT in sbrForwardModulation()
147 * \li 5/6 R_SHIFT in dct3() if using 32/64 Bands
148 * \li 1 ommited gain of 2.0 in qmfForwardModulation()
150 #define ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK 7
153 * \brief Algorithmic scaling in cplxSynthesisQmfFiltering()
155 * The scaling in cplxSynthesisQmfFiltering() is caused by:
157 * \li 5/6 R_SHIFT in dct2() if using 32/64 Bands
158 * \li 1 ommited gain of 2.0 in qmfInverseModulation()
159 * \li -6 division by 64 in synthesis filterbank
160 * \li x bits external influence
162 #define ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK 1
166 \brief Perform Synthesis Prototype Filtering on a single slot of input data.
168 The filter takes 2 * qmf->no_channels of input data and
169 generates qmf->no_channels time domain output samples.
172 #ifndef FUNCTION_qmfSynPrototypeFirSlot
173 void qmfSynPrototypeFirSlot(
175 void qmfSynPrototypeFirSlot_fallback(
177 HANDLE_QMF_FILTER_BANK qmf
,
178 FIXP_QMF
*RESTRICT realSlot
, /*!< Input: Pointer to real Slot */
179 FIXP_QMF
*RESTRICT imagSlot
, /*!< Input: Pointer to imag Slot */
180 INT_PCM
*RESTRICT timeOut
, /*!< Time domain data */
184 FIXP_QSS
* FilterStates
= (FIXP_QSS
*)qmf
->FilterStates
;
185 int no_channels
= qmf
->no_channels
;
186 const FIXP_PFT
*p_Filter
= qmf
->p_filter
;
187 int p_stride
= qmf
->p_stride
;
189 FIXP_QSS
*RESTRICT sta
= FilterStates
;
190 const FIXP_PFT
*RESTRICT p_flt
, *RESTRICT p_fltm
;
191 int scale
= ((DFRACT_BITS
-SAMPLE_BITS
)-1-qmf
->outScalefactor
);
193 p_flt
= p_Filter
+p_stride
*QMF_NO_POLY
; /* 5-ter von 330 */
194 p_fltm
= p_Filter
+(qmf
->FilterSize
/2)-p_stride
*QMF_NO_POLY
; /* 5 + (320 - 2*5) = 315-ter von 330 */
196 FDK_ASSERT(SAMPLE_BITS
-1-qmf
->outScalefactor
>= 0); // (DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor >= 0);
198 for (j
= no_channels
-1; j
>= 0; j
--) { /* ---- läuft ueber alle Linien eines Slots ---- */
199 FIXP_QMF imag
= imagSlot
[j
]; // no_channels-1 .. 0
200 FIXP_QMF real
= realSlot
[j
]; // ~~"~~
203 FIXP_DBL Are
= FX_QSS2FX_DBL(sta
[0]) + fMultDiv2( p_fltm
[0] , real
);
205 if (qmf
->outGain
!=(FIXP_DBL
)0x80000000) {
206 Are
= fMult(Are
,qmf
->outGain
);
210 tmp
= (INT_PCM
)(SATURATE_SHIFT(fAbs(Are
), scale
, SAMPLE_BITS
));
212 tmp
= (INT_PCM
)(SATURATE_RIGHT_SHIFT(fAbs(Are
), scale
, SAMPLE_BITS
));
214 if (Are
< (FIXP_QMF
)0) {
217 timeOut
[ (j
)*stride
] = tmp
;
220 sta
[0] = sta
[1] + FX_DBL2FX_QSS(fMultDiv2( p_flt
[4] , imag
));
221 sta
[1] = sta
[2] + FX_DBL2FX_QSS(fMultDiv2( p_fltm
[1] , real
));
222 sta
[2] = sta
[3] + FX_DBL2FX_QSS(fMultDiv2( p_flt
[3] , imag
));
223 sta
[3] = sta
[4] + FX_DBL2FX_QSS(fMultDiv2( p_fltm
[2] , real
));
224 sta
[4] = sta
[5] + FX_DBL2FX_QSS(fMultDiv2( p_flt
[2] , imag
));
225 sta
[5] = sta
[6] + FX_DBL2FX_QSS(fMultDiv2( p_fltm
[3] , real
));
226 sta
[6] = sta
[7] + FX_DBL2FX_QSS(fMultDiv2( p_flt
[1] , imag
));
227 sta
[7] = sta
[8] + FX_DBL2FX_QSS(fMultDiv2( p_fltm
[4] , real
));
228 sta
[8] = FX_DBL2FX_QSS(fMultDiv2( p_flt
[0] , imag
));
230 p_flt
+= (p_stride
*QMF_NO_POLY
);
231 p_fltm
-= (p_stride
*QMF_NO_POLY
);
232 sta
+= 9; // = (2*QMF_NO_POLY-1);
236 #ifndef FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric
238 \brief Perform Synthesis Prototype Filtering on a single slot of input data.
240 The filter takes 2 * qmf->no_channels of input data and
241 generates qmf->no_channels time domain output samples.
244 void qmfSynPrototypeFirSlot_NonSymmetric(
245 HANDLE_QMF_FILTER_BANK qmf
,
246 FIXP_QMF
*RESTRICT realSlot
, /*!< Input: Pointer to real Slot */
247 FIXP_QMF
*RESTRICT imagSlot
, /*!< Input: Pointer to imag Slot */
248 INT_PCM
*RESTRICT timeOut
, /*!< Time domain data */
252 FIXP_QSS
* FilterStates
= (FIXP_QSS
*)qmf
->FilterStates
;
253 int no_channels
= qmf
->no_channels
;
254 const FIXP_PFT
*p_Filter
= qmf
->p_filter
;
255 int p_stride
= qmf
->p_stride
;
257 FIXP_QSS
*RESTRICT sta
= FilterStates
;
258 const FIXP_PFT
*RESTRICT p_flt
, *RESTRICT p_fltm
;
259 int scale
= ((DFRACT_BITS
-SAMPLE_BITS
)-1-qmf
->outScalefactor
);
261 p_flt
= p_Filter
; /*!< Pointer to first half of filter coefficients */
262 p_fltm
= &p_flt
[qmf
->FilterSize
/2]; /* at index 320, overall 640 coefficients */
264 FDK_ASSERT(SAMPLE_BITS
-1-qmf
->outScalefactor
>= 0); // (DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor >= 0);
266 for (j
= no_channels
-1; j
>= 0; j
--) { /* ---- läuft ueber alle Linien eines Slots ---- */
268 FIXP_QMF imag
= imagSlot
[j
]; // no_channels-1 .. 0
269 FIXP_QMF real
= realSlot
[j
]; // ~~"~~
272 FIXP_QMF Are
= sta
[0] + FX_DBL2FX_QSS(fMultDiv2( p_fltm
[4] , real
));
275 tmp
= (INT_PCM
)(SATURATE_SHIFT(fAbs(Are
), scale
, SAMPLE_BITS
));
277 tmp
= (INT_PCM
)(SATURATE_RIGHT_SHIFT(fAbs(Are
), scale
, SAMPLE_BITS
));
279 if (Are
< (FIXP_QMF
)0) {
282 timeOut
[j
*stride
] = tmp
;
285 sta
[0] = sta
[1] + FX_DBL2FX_QSS(fMultDiv2( p_flt
[4] , imag
));
286 sta
[1] = sta
[2] + FX_DBL2FX_QSS(fMultDiv2( p_fltm
[3] , real
));
287 sta
[2] = sta
[3] + FX_DBL2FX_QSS(fMultDiv2( p_flt
[3] , imag
));
289 sta
[3] = sta
[4] + FX_DBL2FX_QSS(fMultDiv2( p_fltm
[2] , real
));
290 sta
[4] = sta
[5] + FX_DBL2FX_QSS(fMultDiv2( p_flt
[2] , imag
));
291 sta
[5] = sta
[6] + FX_DBL2FX_QSS(fMultDiv2( p_fltm
[1] , real
));
292 sta
[6] = sta
[7] + FX_DBL2FX_QSS(fMultDiv2( p_flt
[1] , imag
));
294 sta
[7] = sta
[8] + FX_DBL2FX_QSS(fMultDiv2( p_fltm
[0] , real
));
295 sta
[8] = FX_DBL2FX_QSS(fMultDiv2( p_flt
[0] , imag
));
297 p_flt
+= (p_stride
*QMF_NO_POLY
);
298 p_fltm
+= (p_stride
*QMF_NO_POLY
);
299 sta
+= 9; // = (2*QMF_NO_POLY-1);
303 #endif /* FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric */
305 #ifndef FUNCTION_qmfAnaPrototypeFirSlot
307 \brief Perform Analysis Prototype Filtering on a single slot of input data.
310 void qmfAnaPrototypeFirSlot( FIXP_QMF
*analysisBuffer
,
311 int no_channels
, /*!< Number channels of analysis filter */
312 const FIXP_PFT
*p_filter
,
313 int p_stride
, /*!< Stide of analysis filter */
314 FIXP_QAS
*RESTRICT pFilterStates
320 const FIXP_PFT
*RESTRICT p_flt
= p_filter
;
321 FIXP_QMF
*RESTRICT pData_0
= analysisBuffer
+ 2*no_channels
- 1;
322 FIXP_QMF
*RESTRICT pData_1
= analysisBuffer
;
324 FIXP_QAS
*RESTRICT sta_0
= (FIXP_QAS
*)pFilterStates
;
325 FIXP_QAS
*RESTRICT sta_1
= (FIXP_QAS
*)pFilterStates
+ (2*QMF_NO_POLY
*no_channels
) - 1;
326 int pfltStep
= QMF_NO_POLY
* (p_stride
);
327 int staStep1
= no_channels
<<1;
328 int staStep2
= (no_channels
<<3) - 1; /* Rewind one less */
331 accu
= fMultDiv2( p_flt
[0], *sta_1
); sta_1
-= staStep1
;
332 accu
+= fMultDiv2( p_flt
[1], *sta_1
); sta_1
-= staStep1
;
333 accu
+= fMultDiv2( p_flt
[2], *sta_1
); sta_1
-= staStep1
;
334 accu
+= fMultDiv2( p_flt
[3], *sta_1
); sta_1
-= staStep1
;
335 accu
+= fMultDiv2( p_flt
[4], *sta_1
);
336 *pData_1
++ = FX_DBL2FX_QMF(accu
<<1);
341 /* FIR filters 1..63 127..65 */
342 for (k
=0; k
<no_channels
-1; k
++)
344 accu
= fMultDiv2( p_flt
[0], *sta_0
); sta_0
+= staStep1
;
345 accu
+= fMultDiv2( p_flt
[1], *sta_0
); sta_0
+= staStep1
;
346 accu
+= fMultDiv2( p_flt
[2], *sta_0
); sta_0
+= staStep1
;
347 accu
+= fMultDiv2( p_flt
[3], *sta_0
); sta_0
+= staStep1
;
348 accu
+= fMultDiv2( p_flt
[4], *sta_0
);
349 *pData_0
-- = FX_DBL2FX_QMF(accu
<<1);
352 accu
= fMultDiv2( p_flt
[0], *sta_1
); sta_1
-= staStep1
;
353 accu
+= fMultDiv2( p_flt
[1], *sta_1
); sta_1
-= staStep1
;
354 accu
+= fMultDiv2( p_flt
[2], *sta_1
); sta_1
-= staStep1
;
355 accu
+= fMultDiv2( p_flt
[3], *sta_1
); sta_1
-= staStep1
;
356 accu
+= fMultDiv2( p_flt
[4], *sta_1
);
357 *pData_1
++ = FX_DBL2FX_QMF(accu
<<1);
364 accu
= fMultDiv2( p_flt
[0], *sta_0
); sta_0
+= staStep1
;
365 accu
+= fMultDiv2( p_flt
[1], *sta_0
); sta_0
+= staStep1
;
366 accu
+= fMultDiv2( p_flt
[2], *sta_0
); sta_0
+= staStep1
;
367 accu
+= fMultDiv2( p_flt
[3], *sta_0
); sta_0
+= staStep1
;
368 accu
+= fMultDiv2( p_flt
[4], *sta_0
);
369 *pData_0
-- = FX_DBL2FX_QMF(accu
<<1);
372 #endif /* !defined(FUNCTION_qmfAnaPrototypeFirSlot) */
375 #ifndef FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric
377 \brief Perform Analysis Prototype Filtering on a single slot of input data.
380 void qmfAnaPrototypeFirSlot_NonSymmetric(
381 FIXP_QMF
*analysisBuffer
,
382 int no_channels
, /*!< Number channels of analysis filter */
383 const FIXP_PFT
*p_filter
,
384 int p_stride
, /*!< Stide of analysis filter */
385 FIXP_QAS
*RESTRICT pFilterStates
388 const FIXP_PFT
*RESTRICT p_flt
= p_filter
;
391 for (k
= 0; k
< 2*no_channels
; k
++)
393 FIXP_DBL accu
= (FIXP_DBL
)0;
395 p_flt
+= QMF_NO_POLY
* (p_stride
- 1);
400 for (p
= 0; p
< QMF_NO_POLY
; p
++) {
401 accu
+= fMultDiv2(*p_flt
++, pFilterStates
[2*no_channels
* p
]);
403 analysisBuffer
[2*no_channels
- 1 - k
] = FX_DBL2FX_QMF(accu
<<1);
407 #endif /* FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric */
411 * \brief Perform real-valued forward modulation of the time domain
412 * data of timeIn and stores the real part of the subband
413 * samples in rSubband
417 qmfForwardModulationLP_even( HANDLE_QMF_FILTER_BANK anaQmf
, /*!< Handle of Qmf Analysis Bank */
418 FIXP_QMF
*timeIn
, /*!< Time Signal */
419 FIXP_QMF
*rSubband
) /*!< Real Output */
422 int L
= anaQmf
->no_channels
;
427 const FIXP_QMF
*timeInTmp1
= (FIXP_QMF
*) &timeIn
[3 * M
];
428 const FIXP_QMF
*timeInTmp2
= timeInTmp1
;
429 FIXP_QMF
*rSubbandTmp
= rSubband
;
431 rSubband
[0] = timeIn
[3 * M
] >> 1;
433 for (i
= M
-1; i
!= 0; i
--) {
434 accu
= ((*--timeInTmp1
) >> 1) + ((*++timeInTmp2
) >> 1);
435 *++rSubbandTmp
= accu
;
438 timeInTmp1
= &timeIn
[2 * M
];
439 timeInTmp2
= &timeIn
[0];
440 rSubbandTmp
= &rSubband
[M
];
442 for (i
= L
-M
; i
!= 0; i
--) {
443 accu
= ((*timeInTmp1
--) >> 1) - ((*timeInTmp2
++) >> 1);
444 *rSubbandTmp
++ = accu
;
447 dct_III(rSubband
, timeIn
, L
, &scale
);
450 #if !defined(FUNCTION_qmfForwardModulationLP_odd)
452 qmfForwardModulationLP_odd( HANDLE_QMF_FILTER_BANK anaQmf
, /*!< Handle of Qmf Analysis Bank */
453 const FIXP_QMF
*timeIn
, /*!< Time Signal */
454 FIXP_QMF
*rSubband
) /*!< Real Output */
457 int L
= anaQmf
->no_channels
;
459 int shift
= (anaQmf
->no_channels
>>6) + 1;
461 for (i
= 0; i
< M
; i
++) {
462 rSubband
[M
+ i
] = (timeIn
[L
- 1 - i
]>>1) - (timeIn
[i
]>>shift
);
463 rSubband
[M
- 1 - i
] = (timeIn
[L
+ i
]>>1) + (timeIn
[2 * L
- 1 - i
]>>shift
);
466 dct_IV(rSubband
, L
, &shift
);
468 #endif /* !defined(FUNCTION_qmfForwardModulationLP_odd) */
474 * \brief Perform complex-valued forward modulation of the time domain
475 * data of timeIn and stores the real part of the subband
476 * samples in rSubband, and the imaginary part in iSubband
478 * Only the lower bands are obtained (upto anaQmf->lsb). For
479 * a full bandwidth analysis it is required to set both anaQmf->lsb
480 * and anaQmf->usb to the amount of QMF bands.
484 qmfForwardModulationHQ( HANDLE_QMF_FILTER_BANK anaQmf
, /*!< Handle of Qmf Analysis Bank */
485 const FIXP_QMF
*RESTRICT timeIn
, /*!< Time Signal */
486 FIXP_QMF
*RESTRICT rSubband
, /*!< Real Output */
487 FIXP_QMF
*RESTRICT iSubband
/*!< Imaginary Output */
491 int L
= anaQmf
->no_channels
;
495 for (i
= 0; i
< L
; i
+=2) {
496 FIXP_QMF x0
, x1
, y0
, y1
;
499 x1
= timeIn
[i
+1] >> 1;
500 y0
= timeIn
[L2
- 1 - i
] >> 1;
501 y1
= timeIn
[L2
- 2 - i
] >> 1;
503 rSubband
[i
] = x0
- y0
;
504 rSubband
[i
+1] = x1
- y1
;
505 iSubband
[i
] = x0
+ y0
;
506 iSubband
[i
+1] = x1
+ y1
;
509 dct_IV(rSubband
, L
, &shift
);
510 dst_IV(iSubband
, L
, &shift
);
514 const FIXP_QTW
*RESTRICT sbr_t_cos
;
515 const FIXP_QTW
*RESTRICT sbr_t_sin
;
516 sbr_t_cos
= anaQmf
->t_cos
;
517 sbr_t_sin
= anaQmf
->t_sin
;
519 for (i
= 0; i
< anaQmf
->lsb
; i
++) {
520 cplxMult(&iSubband
[i
], &rSubband
[i
], iSubband
[i
], rSubband
[i
], sbr_t_cos
[i
], sbr_t_sin
[i
]);
527 * \brief Perform one QMF slot analysis of the time domain data of timeIn
528 * with specified stride and stores the real part of the subband
529 * samples in rSubband, and the imaginary part in iSubband
531 * Only the lower bands are obtained (upto anaQmf->lsb). For
532 * a full bandwidth analysis it is required to set both anaQmf->lsb
533 * and anaQmf->usb to the amount of QMF bands.
536 qmfAnalysisFilteringSlot( HANDLE_QMF_FILTER_BANK anaQmf
, /*!< Handle of Qmf Synthesis Bank */
537 FIXP_QMF
*qmfReal
, /*!< Low and High band, real */
538 FIXP_QMF
*qmfImag
, /*!< Low and High band, imag */
539 const INT_PCM
*RESTRICT timeIn
, /*!< Pointer to input */
540 const int stride
, /*!< stride factor of input */
541 FIXP_QMF
*pWorkBuffer
/*!< pointer to temporal working buffer */
545 int offset
= anaQmf
->no_channels
*(QMF_NO_POLY
*2-1);
547 Feed time signal into oldest anaQmf->no_channels states
550 FIXP_QAS
*RESTRICT FilterStatesAnaTmp
= ((FIXP_QAS
*)anaQmf
->FilterStates
)+offset
;
552 /* Feed and scale actual time in slot */
553 for(i
=anaQmf
->no_channels
>>1; i
!=0; i
--) {
554 /* Place INT_PCM value left aligned in scaledTimeIn */
555 #if (QAS_BITS==SAMPLE_BITS)
556 *FilterStatesAnaTmp
++ = (FIXP_QAS
)*timeIn
; timeIn
+= stride
;
557 *FilterStatesAnaTmp
++ = (FIXP_QAS
)*timeIn
; timeIn
+= stride
;
558 #elif (QAS_BITS>SAMPLE_BITS)
559 *FilterStatesAnaTmp
++ = (FIXP_QAS
)((*timeIn
)<<(QAS_BITS
-SAMPLE_BITS
)); timeIn
+= stride
;
560 *FilterStatesAnaTmp
++ = (FIXP_QAS
)((*timeIn
)<<(QAS_BITS
-SAMPLE_BITS
)); timeIn
+= stride
;
562 *FilterStatesAnaTmp
++ = (FIXP_QAS
)((*timeIn
)>>(SAMPLE_BITS
-QAS_BITS
)); timeIn
+= stride
;
563 *FilterStatesAnaTmp
++ = (FIXP_QAS
)((*timeIn
)>>(SAMPLE_BITS
-QAS_BITS
)); timeIn
+= stride
;
568 if (anaQmf
->flags
& QMF_FLAG_NONSYMMETRIC
) {
569 qmfAnaPrototypeFirSlot_NonSymmetric(
574 (FIXP_QAS
*)anaQmf
->FilterStates
577 qmfAnaPrototypeFirSlot( pWorkBuffer
,
581 (FIXP_QAS
*)anaQmf
->FilterStates
585 if (anaQmf
->flags
& QMF_FLAG_LP
) {
586 if (anaQmf
->flags
& QMF_FLAG_CLDFB
)
587 qmfForwardModulationLP_odd( anaQmf
,
591 qmfForwardModulationLP_even( anaQmf
,
596 qmfForwardModulationHQ( anaQmf
,
605 Should be realized with modulo adressing on a DSP instead of a true buffer shift
607 FDKmemmove ((FIXP_QAS
*)anaQmf
->FilterStates
, (FIXP_QAS
*)anaQmf
->FilterStates
+anaQmf
->no_channels
, offset
*sizeof(FIXP_QAS
));
613 * \brief Perform complex-valued subband filtering of the time domain
614 * data of timeIn and stores the real part of the subband
615 * samples in rAnalysis, and the imaginary part in iAnalysis
616 * The qmf coefficient table is symmetric. The symmetry is expoited by
617 * shrinking the coefficient table to half the size. The addressing mode
618 * takes care of the symmetries.
620 * Only the lower bands are obtained (upto anaQmf->lsb). For
621 * a full bandwidth analysis it is required to set both anaQmf->lsb
622 * and anaQmf->usb to the amount of QMF bands.
624 * \sa PolyphaseFiltering
628 qmfAnalysisFiltering( HANDLE_QMF_FILTER_BANK anaQmf
, /*!< Handle of Qmf Analysis Bank */
629 FIXP_QMF
**qmfReal
, /*!< Pointer to real subband slots */
630 FIXP_QMF
**qmfImag
, /*!< Pointer to imag subband slots */
631 QMF_SCALE_FACTOR
*scaleFactor
,
632 const INT_PCM
*timeIn
, /*!< Time signal */
634 FIXP_QMF
*pWorkBuffer
/*!< pointer to temporal working buffer */
638 int no_channels
= anaQmf
->no_channels
;
640 scaleFactor
->lb_scale
= -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK
;
641 scaleFactor
->lb_scale
-= anaQmf
->filterScale
;
643 for (i
= 0; i
< anaQmf
->no_col
; i
++)
645 FIXP_QMF
*qmfImagSlot
= NULL
;
647 if (!(anaQmf
->flags
& QMF_FLAG_LP
)) {
648 qmfImagSlot
= qmfImag
[i
];
651 qmfAnalysisFilteringSlot( anaQmf
, qmfReal
[i
], qmfImagSlot
, timeIn
, stride
, pWorkBuffer
);
653 timeIn
+= no_channels
*stride
;
655 } /* no_col loop i */
660 * \brief Perform low power inverse modulation of the subband
661 * samples stored in rSubband (real part) and iSubband (imaginary
662 * part) and stores the result in pWorkBuffer.
667 qmfInverseModulationLP_even( HANDLE_QMF_FILTER_BANK synQmf
, /*!< Handle of Qmf Synthesis Bank */
668 const FIXP_QMF
*qmfReal
, /*!< Pointer to qmf real subband slot (input) */
669 const int scaleFactorLowBand
, /*!< Scalefactor for Low band */
670 const int scaleFactorHighBand
, /*!< Scalefactor for High band */
671 FIXP_QMF
*pTimeOut
/*!< Pointer to qmf subband slot (output)*/
675 int L
= synQmf
->no_channels
;
679 FIXP_QMF
*RESTRICT tReal
= pTimeOut
;
680 FIXP_QMF
*RESTRICT tImag
= pTimeOut
+ L
;
682 /* Move input to output vector with offset */
683 scaleValues(&tReal
[0], &qmfReal
[0], synQmf
->lsb
, scaleFactorLowBand
);
684 scaleValues(&tReal
[0+synQmf
->lsb
], &qmfReal
[0+synQmf
->lsb
], synQmf
->usb
-synQmf
->lsb
, scaleFactorHighBand
);
685 FDKmemclear(&tReal
[0+synQmf
->usb
], (L
-synQmf
->usb
)*sizeof(FIXP_QMF
));
687 /* Dct type-2 transform */
688 dct_II(tReal
, tImag
, L
, &scale
);
690 /* Expand output and replace inplace the output buffers */
692 tImag
[M
] = (FIXP_QMF
)0;
694 tReal
[0] = tReal
[M
];
697 for (i
= 1; i
< M
/2; i
++) {
708 tReal
[M
+ i
] = tReal
[i
];
709 tReal
[L
- i
] = tReal
[M
- i
];
711 tReal
[i
] = tReal
[M
- i
];
715 /* Remaining odd terms */
716 tmp
= tReal
[M
+ M
/2];
718 tImag
[M
/2 + M
] = -tmp
;
720 tReal
[M
+ M
/2] = tReal
[M
/2];
725 qmfInverseModulationLP_odd( HANDLE_QMF_FILTER_BANK synQmf
, /*!< Handle of Qmf Synthesis Bank */
726 const FIXP_QMF
*qmfReal
, /*!< Pointer to qmf real subband slot (input) */
727 const int scaleFactorLowBand
, /*!< Scalefactor for Low band */
728 const int scaleFactorHighBand
, /*!< Scalefactor for High band */
729 FIXP_QMF
*pTimeOut
/*!< Pointer to qmf subband slot (output)*/
733 int L
= synQmf
->no_channels
;
737 /* Move input to output vector with offset */
738 scaleValues(pTimeOut
+M
, qmfReal
, synQmf
->lsb
, scaleFactorLowBand
);
739 scaleValues(pTimeOut
+M
+synQmf
->lsb
, qmfReal
+synQmf
->lsb
, synQmf
->usb
-synQmf
->lsb
, scaleFactorHighBand
);
740 FDKmemclear(pTimeOut
+M
+synQmf
->usb
, (L
-synQmf
->usb
)*sizeof(FIXP_QMF
));
742 dct_IV(pTimeOut
+M
, L
, &shift
);
743 for (i
= 0; i
< M
; i
++) {
744 pTimeOut
[i
] = pTimeOut
[L
- 1 - i
];
745 pTimeOut
[2 * L
- 1 - i
] = -pTimeOut
[L
+ i
];
752 * \brief Perform complex-valued inverse modulation of the subband
753 * samples stored in rSubband (real part) and iSubband (imaginary
754 * part) and stores the result in pWorkBuffer.
759 qmfInverseModulationHQ( HANDLE_QMF_FILTER_BANK synQmf
, /*!< Handle of Qmf Synthesis Bank */
760 const FIXP_QMF
*qmfReal
, /*!< Pointer to qmf real subband slot */
761 const FIXP_QMF
*qmfImag
, /*!< Pointer to qmf imag subband slot */
762 const int scaleFactorLowBand
, /*!< Scalefactor for Low band */
763 const int scaleFactorHighBand
,/*!< Scalefactor for High band */
764 FIXP_QMF
*pWorkBuffer
/*!< WorkBuffer (output) */
768 int L
= synQmf
->no_channels
;
771 FIXP_QMF
*RESTRICT tReal
= pWorkBuffer
;
772 FIXP_QMF
*RESTRICT tImag
= pWorkBuffer
+L
;
774 if (synQmf
->flags
& QMF_FLAG_CLDFB
){
775 for (i
= 0; i
< synQmf
->lsb
; i
++) {
776 cplxMult(&tImag
[i
], &tReal
[i
],
777 scaleValue(qmfImag
[i
],scaleFactorLowBand
), scaleValue(qmfReal
[i
],scaleFactorLowBand
),
778 synQmf
->t_cos
[i
], synQmf
->t_sin
[i
]);
780 for (; i
< synQmf
->usb
; i
++) {
781 cplxMult(&tImag
[i
], &tReal
[i
],
782 scaleValue(qmfImag
[i
],scaleFactorHighBand
), scaleValue(qmfReal
[i
],scaleFactorHighBand
),
783 synQmf
->t_cos
[i
], synQmf
->t_sin
[i
]);
787 if ( (synQmf
->flags
& QMF_FLAG_CLDFB
) == 0) {
788 scaleValues(&tReal
[0], &qmfReal
[0], synQmf
->lsb
, scaleFactorLowBand
);
789 scaleValues(&tReal
[0+synQmf
->lsb
], &qmfReal
[0+synQmf
->lsb
], synQmf
->usb
-synQmf
->lsb
, scaleFactorHighBand
);
790 scaleValues(&tImag
[0], &qmfImag
[0], synQmf
->lsb
, scaleFactorLowBand
);
791 scaleValues(&tImag
[0+synQmf
->lsb
], &qmfImag
[0+synQmf
->lsb
], synQmf
->usb
-synQmf
->lsb
, scaleFactorHighBand
);
794 FDKmemclear(&tReal
[synQmf
->usb
], (synQmf
->no_channels
-synQmf
->usb
)*sizeof(FIXP_QMF
));
795 FDKmemclear(&tImag
[synQmf
->usb
], (synQmf
->no_channels
-synQmf
->usb
)*sizeof(FIXP_QMF
));
797 dct_IV(tReal
, L
, &shift
);
798 dst_IV(tImag
, L
, &shift
);
800 if (synQmf
->flags
& QMF_FLAG_CLDFB
){
801 for (i
= 0; i
< M
; i
++) {
802 FIXP_QMF r1
, i1
, r2
, i2
;
804 i2
= tImag
[L
- 1 - i
];
805 r2
= tReal
[L
- i
- 1];
808 tReal
[i
] = (r1
- i1
)>>1;
809 tImag
[L
- 1 - i
] = -(r1
+ i1
)>>1;
810 tReal
[L
- i
- 1] = (r2
- i2
)>>1;
811 tImag
[i
] = -(r2
+ i2
)>>1;
815 /* The array accesses are negative to compensate the missing minus sign in the low and hi band gain. */
816 /* 26 cycles on ARM926 */
817 for (i
= 0; i
< M
; i
++) {
818 FIXP_QMF r1
, i1
, r2
, i2
;
820 i2
= -tImag
[L
- 1 - i
];
821 r2
= -tReal
[L
- i
- 1];
824 tReal
[i
] = (r1
- i1
)>>1;
825 tImag
[L
- 1 - i
] = -(r1
+ i1
)>>1;
826 tReal
[L
- i
- 1] = (r2
- i2
)>>1;
827 tImag
[i
] = -(r2
+ i2
)>>1;
832 void qmfSynthesisFilteringSlot( HANDLE_QMF_FILTER_BANK synQmf
,
833 const FIXP_QMF
*realSlot
,
834 const FIXP_QMF
*imagSlot
,
835 const int scaleFactorLowBand
,
836 const int scaleFactorHighBand
,
839 FIXP_QMF
*pWorkBuffer
)
841 if (!(synQmf
->flags
& QMF_FLAG_LP
))
842 qmfInverseModulationHQ ( synQmf
,
851 if (synQmf
->flags
& QMF_FLAG_CLDFB
) {
852 qmfInverseModulationLP_odd ( synQmf
,
859 qmfInverseModulationLP_even ( synQmf
,
868 if (synQmf
->flags
& QMF_FLAG_NONSYMMETRIC
) {
869 qmfSynPrototypeFirSlot_NonSymmetric (
872 pWorkBuffer
+synQmf
->no_channels
,
877 qmfSynPrototypeFirSlot ( synQmf
,
879 pWorkBuffer
+synQmf
->no_channels
,
890 * \brief Perform complex-valued subband synthesis of the
891 * low band and the high band and store the
892 * time domain data in timeOut
894 * First step: Calculate the proper scaling factor of current
895 * spectral data in qmfReal/qmfImag, old spectral data in the overlap
896 * range and filter states.
898 * Second step: Perform Frequency-to-Time mapping with inverse
899 * Modulation slot-wise.
901 * Third step: Perform FIR-filter slot-wise. To save space for filter
902 * states, the MAC operations are executed directly on the filter states
903 * instead of accumulating several products in the accumulator. The
904 * buffer shift at the end of the function should be replaced by a
905 * modulo operation, which is available on some DSPs.
907 * Last step: Copy the upper part of the spectral data to the overlap buffer.
909 * The qmf coefficient table is symmetric. The symmetry is exploited by
910 * shrinking the coefficient table to half the size. The addressing mode
911 * takes care of the symmetries. If the #define #QMFTABLE_FULL is set,
912 * coefficient addressing works on the full table size. The code will be
913 * slightly faster and slightly more compact.
915 * Workbuffer requirement: 2 x sizeof(**QmfBufferReal) * synQmf->no_channels
918 qmfSynthesisFiltering( HANDLE_QMF_FILTER_BANK synQmf
, /*!< Handle of Qmf Synthesis Bank */
919 FIXP_QMF
**QmfBufferReal
, /*!< Low and High band, real */
920 FIXP_QMF
**QmfBufferImag
, /*!< Low and High band, imag */
921 const QMF_SCALE_FACTOR
*scaleFactor
,
922 const INT ov_len
, /*!< split Slot of overlap and actual slots */
923 INT_PCM
*timeOut
, /*!< Pointer to output */
924 const INT stride
, /*!< stride factor of output */
925 FIXP_QMF
*pWorkBuffer
/*!< pointer to temporal working buffer */
929 int L
= synQmf
->no_channels
;
930 SCHAR scaleFactorHighBand
;
931 SCHAR scaleFactorLowBand_ov
, scaleFactorLowBand_no_ov
;
934 scaleFactorHighBand
= -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK
- scaleFactor
->hb_scale
;
935 scaleFactorLowBand_ov
= - ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK
- scaleFactor
->ov_lb_scale
;
936 scaleFactorLowBand_no_ov
= - ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK
- scaleFactor
->lb_scale
;
938 for (i
= 0; i
< synQmf
->no_col
; i
++) /* ----- no_col loop ----- */
940 const FIXP_DBL
*QmfBufferImagSlot
= NULL
;
942 SCHAR scaleFactorLowBand
= (i
<ov_len
) ? scaleFactorLowBand_ov
: scaleFactorLowBand_no_ov
;
944 if (!(synQmf
->flags
& QMF_FLAG_LP
))
945 QmfBufferImagSlot
= QmfBufferImag
[i
];
947 qmfSynthesisFilteringSlot( synQmf
,
952 timeOut
+(i
*L
*stride
),
955 } /* no_col loop i */
962 * \brief Create QMF filter bank instance
964 * \return 0 if successful
968 qmfInitFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf
, /*!< Handle to return */
969 void *pFilterStates
, /*!< Handle to filter states */
970 int noCols
, /*!< Number of timeslots per frame */
971 int lsb
, /*!< Lower end of QMF frequency range */
972 int usb
, /*!< Upper end of QMF frequency range */
973 int no_channels
, /*!< Number of channels (bands) */
974 UINT flags
) /*!< flags */
976 FDKmemclear(h_Qmf
,sizeof(QMF_FILTER_BANK
));
978 if (flags
& QMF_FLAG_MPSLDFB
)
983 if ( !(flags
& QMF_FLAG_MPSLDFB
) && (flags
& QMF_FLAG_CLDFB
) )
985 flags
|= QMF_FLAG_NONSYMMETRIC
;
986 h_Qmf
->filterScale
= QMF_CLDFB_PFT_SCALE
;
989 switch (no_channels
) {
991 h_Qmf
->t_cos
= qmf_phaseshift_cos64_cldfb
;
992 h_Qmf
->t_sin
= qmf_phaseshift_sin64_cldfb
;
993 h_Qmf
->p_filter
= qmf_cldfb_640
;
994 h_Qmf
->FilterSize
= 640;
997 h_Qmf
->t_cos
= qmf_phaseshift_cos32_cldfb
;
998 h_Qmf
->t_sin
= qmf_phaseshift_sin32_cldfb
;
999 h_Qmf
->p_filter
= qmf_cldfb_320
;
1000 h_Qmf
->FilterSize
= 320;
1007 if ( !(flags
& QMF_FLAG_MPSLDFB
) && ((flags
& QMF_FLAG_CLDFB
) == 0) )
1009 switch (no_channels
) {
1011 h_Qmf
->p_filter
= qmf_64
;
1012 h_Qmf
->t_cos
= qmf_phaseshift_cos64
;
1013 h_Qmf
->t_sin
= qmf_phaseshift_sin64
;
1014 h_Qmf
->p_stride
= 1;
1015 h_Qmf
->FilterSize
= 640;
1016 h_Qmf
->filterScale
= 0;
1019 h_Qmf
->p_filter
= qmf_64
;
1020 if (flags
& QMF_FLAG_DOWNSAMPLED
) {
1021 h_Qmf
->t_cos
= qmf_phaseshift_cos_downsamp32
;
1022 h_Qmf
->t_sin
= qmf_phaseshift_sin_downsamp32
;
1025 h_Qmf
->t_cos
= qmf_phaseshift_cos32
;
1026 h_Qmf
->t_sin
= qmf_phaseshift_sin32
;
1028 h_Qmf
->p_stride
= 2;
1029 h_Qmf
->FilterSize
= 640;
1030 h_Qmf
->filterScale
= 0;
1037 h_Qmf
->flags
= flags
;
1039 h_Qmf
->no_channels
= no_channels
;
1040 h_Qmf
->no_col
= noCols
;
1043 h_Qmf
->usb
= fMin(usb
, h_Qmf
->no_channels
);
1045 h_Qmf
->FilterStates
= (void*)pFilterStates
;
1047 h_Qmf
->outScalefactor
= ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK
+ ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK
+ h_Qmf
->filterScale
;
1049 if ( (h_Qmf
->p_stride
== 2)
1050 || ((flags
& QMF_FLAG_CLDFB
) && (no_channels
== 32)) ) {
1051 h_Qmf
->outScalefactor
-= 1;
1053 h_Qmf
->outGain
= (FIXP_DBL
)0x80000000; /* default init value will be not applied */
1060 * \brief Adjust synthesis qmf filter states
1066 qmfAdaptFilterStates (HANDLE_QMF_FILTER_BANK synQmf
, /*!< Handle of Qmf Filter Bank */
1067 int scaleFactorDiff
) /*!< Scale factor difference to be applied */
1069 if (synQmf
== NULL
|| synQmf
->FilterStates
== NULL
) {
1072 scaleValues((FIXP_QSS
*)synQmf
->FilterStates
, synQmf
->no_channels
*(QMF_NO_POLY
*2 - 1), scaleFactorDiff
);
1077 * \brief Create QMF filter bank instance
1079 * Only the lower bands are obtained (upto anaQmf->lsb). For
1080 * a full bandwidth analysis it is required to set both anaQmf->lsb
1081 * and anaQmf->usb to the amount of QMF bands.
1083 * \return 0 if succesful
1087 qmfInitAnalysisFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf
, /*!< Returns handle */
1088 FIXP_QAS
*pFilterStates
, /*!< Handle to filter states */
1089 int noCols
, /*!< Number of timeslots per frame */
1090 int lsb
, /*!< lower end of QMF */
1091 int usb
, /*!< upper end of QMF */
1092 int no_channels
, /*!< Number of channels (bands) */
1093 int flags
) /*!< Low Power flag */
1095 int err
= qmfInitFilterBank(h_Qmf
, pFilterStates
, noCols
, lsb
, usb
, no_channels
, flags
);
1096 if ( !(flags
& QMF_FLAG_KEEP_STATES
) && (h_Qmf
->FilterStates
!= NULL
) ) {
1097 FDKmemclear(h_Qmf
->FilterStates
, (2*QMF_NO_POLY
-1)*h_Qmf
->no_channels
*sizeof(FIXP_QAS
));
1105 * \brief Create QMF filter bank instance
1107 * Only the lower bands are obtained (upto anaQmf->lsb). For
1108 * a full bandwidth analysis it is required to set both anaQmf->lsb
1109 * and anaQmf->usb to the amount of QMF bands.
1111 * \return 0 if succesful
1115 qmfInitSynthesisFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf
, /*!< Returns handle */
1116 FIXP_QSS
*pFilterStates
, /*!< Handle to filter states */
1117 int noCols
, /*!< Number of timeslots per frame */
1118 int lsb
, /*!< lower end of QMF */
1119 int usb
, /*!< upper end of QMF */
1120 int no_channels
, /*!< Number of channels (bands) */
1121 int flags
) /*!< Low Power flag */
1123 int oldOutScale
= h_Qmf
->outScalefactor
;
1124 int err
= qmfInitFilterBank(h_Qmf
, pFilterStates
, noCols
, lsb
, usb
, no_channels
, flags
);
1125 if ( h_Qmf
->FilterStates
!= NULL
) {
1126 if ( !(flags
& QMF_FLAG_KEEP_STATES
) ) {
1127 FDKmemclear(h_Qmf
->FilterStates
, (2*QMF_NO_POLY
-1)*h_Qmf
->no_channels
*sizeof(FIXP_QSS
));
1129 qmfAdaptFilterStates(h_Qmf
, oldOutScale
-h_Qmf
->outScalefactor
);
1140 * \brief Change scale factor for output data and adjust qmf filter states
1146 qmfChangeOutScalefactor (HANDLE_QMF_FILTER_BANK synQmf
, /*!< Handle of Qmf Synthesis Bank */
1147 int outScalefactor
/*!< New scaling factor for output data */
1150 if (synQmf
== NULL
|| synQmf
->FilterStates
== NULL
) {
1154 /* Add internal filterbank scale */
1155 outScalefactor
+= ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK
+ ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK
+ synQmf
->filterScale
;
1157 if ( (synQmf
->p_stride
== 2)
1158 || ((synQmf
->flags
& QMF_FLAG_CLDFB
) && (synQmf
->no_channels
== 32)) ) {
1159 outScalefactor
-= 1;
1162 /* adjust filter states when scale factor has been changed */
1163 if (synQmf
->outScalefactor
!= outScalefactor
)
1167 if (outScalefactor
> (SAMPLE_BITS
- 1)) {
1168 outScalefactor
= SAMPLE_BITS
- 1;
1169 } else if (outScalefactor
< (1 - SAMPLE_BITS
)) {
1170 outScalefactor
= 1 - SAMPLE_BITS
;
1173 diff
= synQmf
->outScalefactor
- outScalefactor
;
1175 qmfAdaptFilterStates(synQmf
, diff
);
1177 /* save new scale factor */
1178 synQmf
->outScalefactor
= outScalefactor
;
1184 * \brief Change gain for output data
1190 qmfChangeOutGain (HANDLE_QMF_FILTER_BANK synQmf
, /*!< Handle of Qmf Synthesis Bank */
1191 FIXP_DBL outputGain
/*!< New gain for output data */
1194 synQmf
->outGain
= outputGain
;