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