/src/aac/libSBRdec/src/lpp_tran.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* ----------------------------------------------------------------------------- |
2 | | Software License for The Fraunhofer FDK AAC Codec Library for Android |
3 | | |
4 | | © Copyright 1995 - 2021 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 | | /**************************** SBR decoder library ****************************** |
96 | | |
97 | | Author(s): |
98 | | |
99 | | Description: |
100 | | |
101 | | *******************************************************************************/ |
102 | | |
103 | | /*! |
104 | | \file |
105 | | \brief Low Power Profile Transposer |
106 | | This module provides the transposer. The main entry point is lppTransposer(). |
107 | | The function generates high frequency content by copying data from the low |
108 | | band (provided by core codec) into the high band. This process is also |
109 | | referred to as "patching". The function also implements spectral whitening by |
110 | | means of inverse filtering based on LPC coefficients. |
111 | | |
112 | | Together with the QMF filterbank the transposer can be tested using a supplied |
113 | | test program. See main_audio.cpp for details. This module does use fractional |
114 | | arithmetic and the accuracy of the computations has an impact on the overall |
115 | | sound quality. The module also needs to take into account the different |
116 | | scaling of spectral data. |
117 | | |
118 | | \sa lppTransposer(), main_audio.cpp, sbr_scale.h, \ref documentationOverview |
119 | | */ |
120 | | |
121 | | #if __has_include(<android/ndk-version.h>) |
122 | | #include <android/ndk-version.h> |
123 | | #endif |
124 | | |
125 | | #if defined __ANDROID__ && !defined __ANDROID_NDK__ |
126 | | #include "log/log.h" |
127 | | #endif |
128 | | |
129 | | #include "lpp_tran.h" |
130 | | |
131 | | #include "sbr_ram.h" |
132 | | #include "sbr_rom.h" |
133 | | |
134 | | #include "genericStds.h" |
135 | | #include "autocorr2nd.h" |
136 | | |
137 | | #include "HFgen_preFlat.h" |
138 | | |
139 | 0 | #define LPC_SCALE_FACTOR 2 |
140 | | |
141 | | /*! |
142 | | * |
143 | | * \brief Get bandwidth expansion factor from filtering level |
144 | | * |
145 | | * Returns a filter parameter (bandwidth expansion factor) depending on |
146 | | * the desired filtering level signalled in the bitstream. |
147 | | * When switching the filtering level from LOW to OFF, an additional |
148 | | * level is being inserted to achieve a smooth transition. |
149 | | */ |
150 | | |
151 | | static FIXP_DBL mapInvfMode(INVF_MODE mode, INVF_MODE prevMode, |
152 | 0 | WHITENING_FACTORS whFactors) { |
153 | 0 | switch (mode) { |
154 | 0 | case INVF_LOW_LEVEL: |
155 | 0 | if (prevMode == INVF_OFF) |
156 | 0 | return whFactors.transitionLevel; |
157 | 0 | else |
158 | 0 | return whFactors.lowLevel; |
159 | | |
160 | 0 | case INVF_MID_LEVEL: |
161 | 0 | return whFactors.midLevel; |
162 | | |
163 | 0 | case INVF_HIGH_LEVEL: |
164 | 0 | return whFactors.highLevel; |
165 | | |
166 | 0 | default: |
167 | 0 | if (prevMode == INVF_LOW_LEVEL) |
168 | 0 | return whFactors.transitionLevel; |
169 | 0 | else |
170 | 0 | return whFactors.off; |
171 | 0 | } |
172 | 0 | } |
173 | | |
174 | | /*! |
175 | | * |
176 | | * \brief Perform inverse filtering level emphasis |
177 | | * |
178 | | * Retrieve bandwidth expansion factor and apply smoothing for each filter band |
179 | | * |
180 | | */ |
181 | | |
182 | | static void inverseFilteringLevelEmphasis( |
183 | | HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ |
184 | | UCHAR nInvfBands, /*!< Number of bands for inverse filtering */ |
185 | | INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ |
186 | | INVF_MODE *sbr_invf_mode_prev, /*!< Previous inverse filtering modes */ |
187 | | FIXP_DBL *bwVector /*!< Resulting filtering levels */ |
188 | 0 | ) { |
189 | 0 | for (int i = 0; i < nInvfBands; i++) { |
190 | 0 | FIXP_DBL accu; |
191 | 0 | FIXP_DBL bwTmp = mapInvfMode(sbr_invf_mode[i], sbr_invf_mode_prev[i], |
192 | 0 | hLppTrans->pSettings->whFactors); |
193 | |
|
194 | 0 | if (bwTmp < hLppTrans->bwVectorOld[i]) { |
195 | 0 | accu = fMultDiv2(FL2FXCONST_DBL(0.75f), bwTmp) + |
196 | 0 | fMultDiv2(FL2FXCONST_DBL(0.25f), hLppTrans->bwVectorOld[i]); |
197 | 0 | } else { |
198 | 0 | accu = fMultDiv2(FL2FXCONST_DBL(0.90625f), bwTmp) + |
199 | 0 | fMultDiv2(FL2FXCONST_DBL(0.09375f), hLppTrans->bwVectorOld[i]); |
200 | 0 | } |
201 | |
|
202 | 0 | if (accu<FL2FXCONST_DBL(0.015625f)>> 1) { |
203 | 0 | bwVector[i] = FL2FXCONST_DBL(0.0f); |
204 | 0 | } else { |
205 | 0 | bwVector[i] = fixMin(accu << 1, FL2FXCONST_DBL(0.99609375f)); |
206 | 0 | } |
207 | 0 | } |
208 | 0 | } |
209 | | |
210 | | /* Resulting autocorrelation determinant exponent */ |
211 | | #define ACDET_EXP \ |
212 | | (2 * (DFRACT_BITS + sbrScaleFactor->lb_scale + 10 - ac.det_scale)) |
213 | | #define AC_EXP (-sbrScaleFactor->lb_scale + LPC_SCALE_FACTOR) |
214 | | #define ALPHA_EXP (-sbrScaleFactor->lb_scale + LPC_SCALE_FACTOR + 1) |
215 | | /* Resulting transposed QMF values exponent 16 bit normalized samplebits |
216 | | * assumed. */ |
217 | | #define QMFOUT_EXP ((SAMPLE_BITS - 15) - sbrScaleFactor->lb_scale) |
218 | | |
219 | | static inline void calc_qmfBufferReal(FIXP_DBL **qmfBufferReal, |
220 | | const FIXP_DBL *const lowBandReal, |
221 | | const int startSample, |
222 | | const int stopSample, const UCHAR hiBand, |
223 | | const int dynamicScale, |
224 | 0 | const FIXP_SGL a0r, const FIXP_SGL a1r) { |
225 | 0 | const int dynscale = fixMax(0, dynamicScale - 1) + 1; |
226 | 0 | const int rescale = -fixMin(0, dynamicScale - 1) + 1; |
227 | 0 | const int descale = |
228 | 0 | fixMin(DFRACT_BITS - 1, LPC_SCALE_FACTOR + dynamicScale + rescale); |
229 | |
|
230 | 0 | for (int i = 0; i < stopSample - startSample; i++) { |
231 | 0 | FIXP_DBL accu; |
232 | |
|
233 | 0 | accu = fMultDiv2(a1r, lowBandReal[i]) + fMultDiv2(a0r, lowBandReal[i + 1]); |
234 | 0 | accu = (lowBandReal[i + 2] >> descale) + (accu >> dynscale); |
235 | |
|
236 | 0 | qmfBufferReal[i + startSample][hiBand] = |
237 | 0 | SATURATE_LEFT_SHIFT(accu, rescale, DFRACT_BITS); |
238 | 0 | } |
239 | 0 | } |
240 | | |
241 | | /*! |
242 | | * |
243 | | * \brief Perform transposition by patching of subband samples. |
244 | | * This function serves as the main entry point into the module. The function |
245 | | * determines the areas for the patching process (these are the source range as |
246 | | * well as the target range) and implements spectral whitening by means of |
247 | | * inverse filtering. The function autoCorrelation2nd() is an auxiliary function |
248 | | * for calculating the LPC coefficients for the filtering. The actual |
249 | | * calculation of the LPC coefficients and the implementation of the filtering |
250 | | * are done as part of lppTransposer(). |
251 | | * |
252 | | * Note that the filtering is done on all available QMF subsamples, whereas the |
253 | | * patching is only done on those QMF subsamples that will be used in the next |
254 | | * QMF synthesis. The filtering is also implemented before the patching includes |
255 | | * further dependencies on parameters from the SBR data. |
256 | | * |
257 | | */ |
258 | | |
259 | | void lppTransposer( |
260 | | HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ |
261 | | QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ |
262 | | FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband |
263 | | samples (source) */ |
264 | | |
265 | | FIXP_DBL *degreeAlias, /*!< Vector for results of aliasing estimation */ |
266 | | FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of |
267 | | subband samples (source) */ |
268 | | const int useLP, const int fPreWhitening, const int v_k_master0, |
269 | | const int timeStep, /*!< Time step of envelope */ |
270 | | const int firstSlotOffs, /*!< Start position in time */ |
271 | | const int lastSlotOffs, /*!< Number of overlap-slots into next frame */ |
272 | | const int nInvfBands, /*!< Number of bands for inverse filtering */ |
273 | | INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ |
274 | | INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */ |
275 | 0 | ) { |
276 | 0 | INT bwIndex[MAX_NUM_PATCHES]; |
277 | 0 | FIXP_DBL bwVector[MAX_NUM_PATCHES]; /*!< pole moving factors */ |
278 | 0 | FIXP_DBL preWhiteningGains[(64) / 2]; |
279 | 0 | int preWhiteningGains_exp[(64) / 2]; |
280 | |
|
281 | 0 | int i; |
282 | 0 | int loBand, start, stop; |
283 | 0 | TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings; |
284 | 0 | PATCH_PARAM *patchParam = pSettings->patchParam; |
285 | 0 | int patch; |
286 | |
|
287 | 0 | FIXP_SGL alphar[LPC_ORDER], a0r, a1r; |
288 | 0 | FIXP_SGL alphai[LPC_ORDER], a0i = 0, a1i = 0; |
289 | 0 | FIXP_SGL bw = FL2FXCONST_SGL(0.0f); |
290 | |
|
291 | 0 | int autoCorrLength; |
292 | |
|
293 | 0 | FIXP_DBL k1, k1_below = 0, k1_below2 = 0; |
294 | |
|
295 | 0 | ACORR_COEFS ac; |
296 | 0 | int startSample; |
297 | 0 | int stopSample; |
298 | 0 | int stopSampleClear; |
299 | |
|
300 | 0 | int comLowBandScale; |
301 | 0 | int ovLowBandShift; |
302 | 0 | int lowBandShift; |
303 | | /* int ovHighBandShift;*/ |
304 | |
|
305 | 0 | alphai[0] = FL2FXCONST_SGL(0.0f); |
306 | 0 | alphai[1] = FL2FXCONST_SGL(0.0f); |
307 | |
|
308 | 0 | startSample = firstSlotOffs * timeStep; |
309 | 0 | stopSample = pSettings->nCols + lastSlotOffs * timeStep; |
310 | 0 | FDK_ASSERT((lastSlotOffs * timeStep) <= pSettings->overlap); |
311 | | |
312 | 0 | inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode, |
313 | 0 | sbr_invf_mode_prev, bwVector); |
314 | |
|
315 | 0 | stopSampleClear = stopSample; |
316 | |
|
317 | 0 | autoCorrLength = pSettings->nCols + pSettings->overlap; |
318 | |
|
319 | 0 | if (pSettings->noOfPatches > 0) { |
320 | | /* Set upper subbands to zero: |
321 | | This is required in case that the patches do not cover the complete |
322 | | highband (because the last patch would be too short). Possible |
323 | | optimization: Clearing bands up to usb would be sufficient here. */ |
324 | 0 | int targetStopBand = |
325 | 0 | patchParam[pSettings->noOfPatches - 1].targetStartBand + |
326 | 0 | patchParam[pSettings->noOfPatches - 1].numBandsInPatch; |
327 | |
|
328 | 0 | int memSize = ((64) - targetStopBand) * sizeof(FIXP_DBL); |
329 | |
|
330 | 0 | if (!useLP) { |
331 | 0 | for (i = startSample; i < stopSampleClear; i++) { |
332 | 0 | FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); |
333 | 0 | FDKmemclear(&qmfBufferImag[i][targetStopBand], memSize); |
334 | 0 | } |
335 | 0 | } else { |
336 | 0 | for (i = startSample; i < stopSampleClear; i++) { |
337 | 0 | FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); |
338 | 0 | } |
339 | 0 | } |
340 | 0 | } |
341 | | #if defined __ANDROID__ && !defined __ANDROID_NDK__ |
342 | | else { |
343 | | // Safetynet logging |
344 | | android_errorWriteLog(0x534e4554, "112160868"); |
345 | | } |
346 | | #endif |
347 | | |
348 | | /* init bwIndex for each patch */ |
349 | 0 | FDKmemclear(bwIndex, sizeof(bwIndex)); |
350 | | |
351 | | /* |
352 | | Calc common low band scale factor |
353 | | */ |
354 | 0 | comLowBandScale = |
355 | 0 | fixMin(sbrScaleFactor->ov_lb_scale, sbrScaleFactor->lb_scale); |
356 | |
|
357 | 0 | ovLowBandShift = sbrScaleFactor->ov_lb_scale - comLowBandScale; |
358 | 0 | lowBandShift = sbrScaleFactor->lb_scale - comLowBandScale; |
359 | | /* ovHighBandShift = firstSlotOffs == 0 ? ovLowBandShift:0;*/ |
360 | |
|
361 | 0 | if (fPreWhitening) { |
362 | 0 | sbrDecoder_calculateGainVec( |
363 | 0 | qmfBufferReal, qmfBufferImag, |
364 | 0 | DFRACT_BITS - 1 - 16 - |
365 | 0 | sbrScaleFactor->ov_lb_scale, /* convert scale to exponent */ |
366 | 0 | DFRACT_BITS - 1 - 16 - |
367 | 0 | sbrScaleFactor->lb_scale, /* convert scale to exponent */ |
368 | 0 | pSettings->overlap, preWhiteningGains, preWhiteningGains_exp, |
369 | 0 | v_k_master0, startSample, stopSample); |
370 | 0 | } |
371 | | |
372 | | /* outer loop over bands to do analysis only once for each band */ |
373 | |
|
374 | 0 | if (!useLP) { |
375 | 0 | start = pSettings->lbStartPatching; |
376 | 0 | stop = pSettings->lbStopPatching; |
377 | 0 | } else { |
378 | 0 | start = fixMax(1, pSettings->lbStartPatching - 2); |
379 | 0 | stop = patchParam[0].targetStartBand; |
380 | 0 | } |
381 | |
|
382 | 0 | for (loBand = start; loBand < stop; loBand++) { |
383 | 0 | FIXP_DBL lowBandReal[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; |
384 | 0 | FIXP_DBL *plowBandReal = lowBandReal; |
385 | 0 | FIXP_DBL **pqmfBufferReal = |
386 | 0 | qmfBufferReal + firstSlotOffs * timeStep /* + pSettings->overlap */; |
387 | 0 | FIXP_DBL lowBandImag[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; |
388 | 0 | FIXP_DBL *plowBandImag = lowBandImag; |
389 | 0 | FIXP_DBL **pqmfBufferImag = |
390 | 0 | qmfBufferImag + firstSlotOffs * timeStep /* + pSettings->overlap */; |
391 | 0 | int resetLPCCoeffs = 0; |
392 | 0 | int dynamicScale = DFRACT_BITS - 1 - LPC_SCALE_FACTOR; |
393 | 0 | int acDetScale = 0; /* scaling of autocorrelation determinant */ |
394 | |
|
395 | 0 | for (i = 0; |
396 | 0 | i < LPC_ORDER + firstSlotOffs * timeStep /*+pSettings->overlap*/; |
397 | 0 | i++) { |
398 | 0 | *plowBandReal++ = hLppTrans->lpcFilterStatesRealLegSBR[i][loBand]; |
399 | 0 | if (!useLP) |
400 | 0 | *plowBandImag++ = hLppTrans->lpcFilterStatesImagLegSBR[i][loBand]; |
401 | 0 | } |
402 | | |
403 | | /* |
404 | | Take old slope length qmf slot source values out of (overlap)qmf buffer |
405 | | */ |
406 | 0 | if (!useLP) { |
407 | 0 | for (i = 0; |
408 | 0 | i < pSettings->nCols + pSettings->overlap - firstSlotOffs * timeStep; |
409 | 0 | i++) { |
410 | 0 | *plowBandReal++ = (*pqmfBufferReal++)[loBand]; |
411 | 0 | *plowBandImag++ = (*pqmfBufferImag++)[loBand]; |
412 | 0 | } |
413 | 0 | } else { |
414 | | /* pSettings->overlap is always even */ |
415 | 0 | FDK_ASSERT((pSettings->overlap & 1) == 0); |
416 | 0 | for (i = 0; i < ((pSettings->nCols + pSettings->overlap - |
417 | 0 | firstSlotOffs * timeStep) >> |
418 | 0 | 1); |
419 | 0 | i++) { |
420 | 0 | *plowBandReal++ = (*pqmfBufferReal++)[loBand]; |
421 | 0 | *plowBandReal++ = (*pqmfBufferReal++)[loBand]; |
422 | 0 | } |
423 | 0 | if (pSettings->nCols & 1) { |
424 | 0 | *plowBandReal++ = (*pqmfBufferReal++)[loBand]; |
425 | 0 | } |
426 | 0 | } |
427 | | |
428 | | /* |
429 | | Determine dynamic scaling value. |
430 | | */ |
431 | 0 | dynamicScale = |
432 | 0 | fixMin(dynamicScale, |
433 | 0 | getScalefactor(lowBandReal, LPC_ORDER + pSettings->overlap) + |
434 | 0 | ovLowBandShift); |
435 | 0 | dynamicScale = |
436 | 0 | fixMin(dynamicScale, |
437 | 0 | getScalefactor(&lowBandReal[LPC_ORDER + pSettings->overlap], |
438 | 0 | pSettings->nCols) + |
439 | 0 | lowBandShift); |
440 | 0 | if (!useLP) { |
441 | 0 | dynamicScale = |
442 | 0 | fixMin(dynamicScale, |
443 | 0 | getScalefactor(lowBandImag, LPC_ORDER + pSettings->overlap) + |
444 | 0 | ovLowBandShift); |
445 | 0 | dynamicScale = |
446 | 0 | fixMin(dynamicScale, |
447 | 0 | getScalefactor(&lowBandImag[LPC_ORDER + pSettings->overlap], |
448 | 0 | pSettings->nCols) + |
449 | 0 | lowBandShift); |
450 | 0 | } |
451 | |
|
452 | 0 | if (dynamicScale == 0) { |
453 | | /* In this special case the available headroom bits as well as |
454 | | ovLowBandShift and lowBandShift are zero. The spectrum is limited to |
455 | | prevent -1.0, so negative values for dynamicScale can be avoided. */ |
456 | 0 | for (i = 0; i < (LPC_ORDER + pSettings->overlap + pSettings->nCols); |
457 | 0 | i++) { |
458 | 0 | lowBandReal[i] = fixMax(lowBandReal[i], (FIXP_DBL)0x80000001); |
459 | 0 | } |
460 | 0 | if (!useLP) { |
461 | 0 | for (i = 0; i < (LPC_ORDER + pSettings->overlap + pSettings->nCols); |
462 | 0 | i++) { |
463 | 0 | lowBandImag[i] = fixMax(lowBandImag[i], (FIXP_DBL)0x80000001); |
464 | 0 | } |
465 | 0 | } |
466 | 0 | } else { |
467 | 0 | dynamicScale = |
468 | 0 | fixMax(0, dynamicScale - |
469 | 0 | 1); /* one additional bit headroom to prevent -1.0 */ |
470 | 0 | } |
471 | | |
472 | | /* |
473 | | Scale temporal QMF buffer. |
474 | | */ |
475 | 0 | scaleValues(&lowBandReal[0], LPC_ORDER + pSettings->overlap, |
476 | 0 | dynamicScale - ovLowBandShift); |
477 | 0 | scaleValues(&lowBandReal[LPC_ORDER + pSettings->overlap], pSettings->nCols, |
478 | 0 | dynamicScale - lowBandShift); |
479 | |
|
480 | 0 | if (!useLP) { |
481 | 0 | scaleValues(&lowBandImag[0], LPC_ORDER + pSettings->overlap, |
482 | 0 | dynamicScale - ovLowBandShift); |
483 | 0 | scaleValues(&lowBandImag[LPC_ORDER + pSettings->overlap], |
484 | 0 | pSettings->nCols, dynamicScale - lowBandShift); |
485 | 0 | } |
486 | |
|
487 | 0 | if (!useLP) { |
488 | 0 | acDetScale += autoCorr2nd_cplx(&ac, lowBandReal + LPC_ORDER, |
489 | 0 | lowBandImag + LPC_ORDER, autoCorrLength); |
490 | 0 | } else { |
491 | 0 | acDetScale += |
492 | 0 | autoCorr2nd_real(&ac, lowBandReal + LPC_ORDER, autoCorrLength); |
493 | 0 | } |
494 | | |
495 | | /* Examine dynamic of determinant in autocorrelation. */ |
496 | 0 | acDetScale += 2 * (comLowBandScale + dynamicScale); |
497 | 0 | acDetScale *= 2; /* two times reflection coefficent scaling */ |
498 | 0 | acDetScale += ac.det_scale; /* ac scaling of determinant */ |
499 | | |
500 | | /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */ |
501 | 0 | if (acDetScale > 126) { |
502 | 0 | resetLPCCoeffs = 1; |
503 | 0 | } |
504 | |
|
505 | 0 | alphar[1] = FL2FXCONST_SGL(0.0f); |
506 | 0 | if (!useLP) alphai[1] = FL2FXCONST_SGL(0.0f); |
507 | |
|
508 | 0 | if (ac.det != FL2FXCONST_DBL(0.0f)) { |
509 | 0 | FIXP_DBL tmp, absTmp, absDet; |
510 | |
|
511 | 0 | absDet = fixp_abs(ac.det); |
512 | |
|
513 | 0 | if (!useLP) { |
514 | 0 | tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) - |
515 | 0 | ((fMultDiv2(ac.r01i, ac.r12i) + fMultDiv2(ac.r02r, ac.r11r)) >> |
516 | 0 | (LPC_SCALE_FACTOR - 1)); |
517 | 0 | } else { |
518 | 0 | tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) - |
519 | 0 | (fMultDiv2(ac.r02r, ac.r11r) >> (LPC_SCALE_FACTOR - 1)); |
520 | 0 | } |
521 | 0 | absTmp = fixp_abs(tmp); |
522 | | |
523 | | /* |
524 | | Quick check: is first filter coeff >= 1(4) |
525 | | */ |
526 | 0 | { |
527 | 0 | INT scale; |
528 | 0 | FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); |
529 | 0 | scale = scale + ac.det_scale; |
530 | |
|
531 | 0 | if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) { |
532 | 0 | resetLPCCoeffs = 1; |
533 | 0 | } else { |
534 | 0 | alphar[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale)); |
535 | 0 | if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { |
536 | 0 | alphar[1] = -alphar[1]; |
537 | 0 | } |
538 | 0 | } |
539 | 0 | } |
540 | |
|
541 | 0 | if (!useLP) { |
542 | 0 | tmp = (fMultDiv2(ac.r01i, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) + |
543 | 0 | ((fMultDiv2(ac.r01r, ac.r12i) - |
544 | 0 | (FIXP_DBL)fMultDiv2(ac.r02i, ac.r11r)) >> |
545 | 0 | (LPC_SCALE_FACTOR - 1)); |
546 | |
|
547 | 0 | absTmp = fixp_abs(tmp); |
548 | | |
549 | | /* |
550 | | Quick check: is second filter coeff >= 1(4) |
551 | | */ |
552 | 0 | { |
553 | 0 | INT scale; |
554 | 0 | FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); |
555 | 0 | scale = scale + ac.det_scale; |
556 | |
|
557 | 0 | if ((scale > 0) && |
558 | 0 | (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL >> |
559 | 0 | scale)) { |
560 | 0 | resetLPCCoeffs = 1; |
561 | 0 | } else { |
562 | 0 | alphai[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale)); |
563 | 0 | if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { |
564 | 0 | alphai[1] = -alphai[1]; |
565 | 0 | } |
566 | 0 | } |
567 | 0 | } |
568 | 0 | } |
569 | 0 | } |
570 | |
|
571 | 0 | alphar[0] = FL2FXCONST_SGL(0.0f); |
572 | 0 | if (!useLP) alphai[0] = FL2FXCONST_SGL(0.0f); |
573 | |
|
574 | 0 | if (ac.r11r != FL2FXCONST_DBL(0.0f)) { |
575 | | /* ac.r11r is always >=0 */ |
576 | 0 | FIXP_DBL tmp, absTmp; |
577 | |
|
578 | 0 | if (!useLP) { |
579 | 0 | tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) + |
580 | 0 | (fMultDiv2(alphar[1], ac.r12r) + fMultDiv2(alphai[1], ac.r12i)); |
581 | 0 | } else { |
582 | 0 | if (ac.r01r >= FL2FXCONST_DBL(0.0f)) |
583 | 0 | tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) + |
584 | 0 | fMultDiv2(alphar[1], ac.r12r); |
585 | 0 | else |
586 | 0 | tmp = -((-ac.r01r) >> (LPC_SCALE_FACTOR + 1)) + |
587 | 0 | fMultDiv2(alphar[1], ac.r12r); |
588 | 0 | } |
589 | |
|
590 | 0 | absTmp = fixp_abs(tmp); |
591 | | |
592 | | /* |
593 | | Quick check: is first filter coeff >= 1(4) |
594 | | */ |
595 | |
|
596 | 0 | if (absTmp >= (ac.r11r >> 1)) { |
597 | 0 | resetLPCCoeffs = 1; |
598 | 0 | } else { |
599 | 0 | INT scale; |
600 | 0 | FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); |
601 | 0 | alphar[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1)); |
602 | |
|
603 | 0 | if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) |
604 | 0 | alphar[0] = -alphar[0]; |
605 | 0 | } |
606 | |
|
607 | 0 | if (!useLP) { |
608 | 0 | tmp = (ac.r01i >> (LPC_SCALE_FACTOR + 1)) + |
609 | 0 | (fMultDiv2(alphai[1], ac.r12r) - fMultDiv2(alphar[1], ac.r12i)); |
610 | |
|
611 | 0 | absTmp = fixp_abs(tmp); |
612 | | |
613 | | /* |
614 | | Quick check: is second filter coeff >= 1(4) |
615 | | */ |
616 | 0 | if (absTmp >= (ac.r11r >> 1)) { |
617 | 0 | resetLPCCoeffs = 1; |
618 | 0 | } else { |
619 | 0 | INT scale; |
620 | 0 | FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); |
621 | 0 | alphai[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1)); |
622 | 0 | if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) |
623 | 0 | alphai[0] = -alphai[0]; |
624 | 0 | } |
625 | 0 | } |
626 | 0 | } |
627 | |
|
628 | 0 | if (!useLP) { |
629 | | /* Now check the quadratic criteria */ |
630 | 0 | if ((fMultDiv2(alphar[0], alphar[0]) + fMultDiv2(alphai[0], alphai[0])) >= |
631 | 0 | FL2FXCONST_DBL(0.5f)) |
632 | 0 | resetLPCCoeffs = 1; |
633 | 0 | if ((fMultDiv2(alphar[1], alphar[1]) + fMultDiv2(alphai[1], alphai[1])) >= |
634 | 0 | FL2FXCONST_DBL(0.5f)) |
635 | 0 | resetLPCCoeffs = 1; |
636 | 0 | } |
637 | |
|
638 | 0 | if (resetLPCCoeffs) { |
639 | 0 | alphar[0] = FL2FXCONST_SGL(0.0f); |
640 | 0 | alphar[1] = FL2FXCONST_SGL(0.0f); |
641 | 0 | if (!useLP) { |
642 | 0 | alphai[0] = FL2FXCONST_SGL(0.0f); |
643 | 0 | alphai[1] = FL2FXCONST_SGL(0.0f); |
644 | 0 | } |
645 | 0 | } |
646 | |
|
647 | 0 | if (useLP) { |
648 | | /* Aliasing detection */ |
649 | 0 | if (ac.r11r == FL2FXCONST_DBL(0.0f)) { |
650 | 0 | k1 = FL2FXCONST_DBL(0.0f); |
651 | 0 | } else { |
652 | 0 | if (fixp_abs(ac.r01r) >= fixp_abs(ac.r11r)) { |
653 | 0 | if (fMultDiv2(ac.r01r, ac.r11r) < FL2FX_DBL(0.0f)) { |
654 | 0 | k1 = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_SGL(1.0f)*/; |
655 | 0 | } else { |
656 | | /* Since this value is squared later, it must not ever become -1.0f. |
657 | | */ |
658 | 0 | k1 = (FIXP_DBL)(MINVAL_DBL + 1) /*FL2FXCONST_SGL(-1.0f)*/; |
659 | 0 | } |
660 | 0 | } else { |
661 | 0 | INT scale; |
662 | 0 | FIXP_DBL result = |
663 | 0 | fDivNorm(fixp_abs(ac.r01r), fixp_abs(ac.r11r), &scale); |
664 | 0 | k1 = scaleValueSaturate(result, scale); |
665 | |
|
666 | 0 | if (!((ac.r01r < FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))) { |
667 | 0 | k1 = -k1; |
668 | 0 | } |
669 | 0 | } |
670 | 0 | } |
671 | 0 | if ((loBand > 1) && (loBand < v_k_master0)) { |
672 | | /* Check if the gain should be locked */ |
673 | 0 | FIXP_DBL deg = |
674 | 0 | /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - fPow2(k1_below); |
675 | 0 | degreeAlias[loBand] = FL2FXCONST_DBL(0.0f); |
676 | 0 | if (((loBand & 1) == 0) && (k1 < FL2FXCONST_DBL(0.0f))) { |
677 | 0 | if (k1_below < FL2FXCONST_DBL(0.0f)) { /* 2-Ch Aliasing Detection */ |
678 | 0 | degreeAlias[loBand] = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/; |
679 | 0 | if (k1_below2 > |
680 | 0 | FL2FXCONST_DBL(0.0f)) { /* 3-Ch Aliasing Detection */ |
681 | 0 | degreeAlias[loBand - 1] = deg; |
682 | 0 | } |
683 | 0 | } else if (k1_below2 > |
684 | 0 | FL2FXCONST_DBL(0.0f)) { /* 3-Ch Aliasing Detection */ |
685 | 0 | degreeAlias[loBand] = deg; |
686 | 0 | } |
687 | 0 | } |
688 | 0 | if (((loBand & 1) == 1) && (k1 > FL2FXCONST_DBL(0.0f))) { |
689 | 0 | if (k1_below > FL2FXCONST_DBL(0.0f)) { /* 2-CH Aliasing Detection */ |
690 | 0 | degreeAlias[loBand] = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/; |
691 | 0 | if (k1_below2 < |
692 | 0 | FL2FXCONST_DBL(0.0f)) { /* 3-CH Aliasing Detection */ |
693 | 0 | degreeAlias[loBand - 1] = deg; |
694 | 0 | } |
695 | 0 | } else if (k1_below2 < |
696 | 0 | FL2FXCONST_DBL(0.0f)) { /* 3-CH Aliasing Detection */ |
697 | 0 | degreeAlias[loBand] = deg; |
698 | 0 | } |
699 | 0 | } |
700 | 0 | } |
701 | | /* remember k1 values of the 2 QMF channels below the current channel */ |
702 | 0 | k1_below2 = k1_below; |
703 | 0 | k1_below = k1; |
704 | 0 | } |
705 | |
|
706 | 0 | patch = 0; |
707 | |
|
708 | 0 | while (patch < pSettings->noOfPatches) { /* inner loop over every patch */ |
709 | |
|
710 | 0 | int hiBand = loBand + patchParam[patch].targetBandOffs; |
711 | |
|
712 | 0 | if (loBand < patchParam[patch].sourceStartBand || |
713 | 0 | loBand >= patchParam[patch].sourceStopBand |
714 | | //|| hiBand >= hLppTrans->pSettings->noChannels |
715 | 0 | ) { |
716 | | /* Lowband not in current patch - proceed */ |
717 | 0 | patch++; |
718 | 0 | continue; |
719 | 0 | } |
720 | | |
721 | 0 | FDK_ASSERT(hiBand < (64)); |
722 | | |
723 | | /* bwIndex[patch] is already initialized with value from previous band |
724 | | * inside this patch */ |
725 | 0 | while (hiBand >= pSettings->bwBorders[bwIndex[patch]] && |
726 | 0 | bwIndex[patch] < MAX_NUM_PATCHES - 1) { |
727 | 0 | bwIndex[patch]++; |
728 | 0 | } |
729 | | |
730 | | /* |
731 | | Filter Step 2: add the left slope with the current filter to the buffer |
732 | | pure source values are already in there |
733 | | */ |
734 | 0 | bw = FX_DBL2FX_SGL(bwVector[bwIndex[patch]]); |
735 | |
|
736 | 0 | a0r = FX_DBL2FX_SGL( |
737 | 0 | fMult(bw, alphar[0])); /* Apply current bandwidth expansion factor */ |
738 | |
|
739 | 0 | if (!useLP) a0i = FX_DBL2FX_SGL(fMult(bw, alphai[0])); |
740 | 0 | bw = FX_DBL2FX_SGL(fPow2(bw)); |
741 | 0 | a1r = FX_DBL2FX_SGL(fMult(bw, alphar[1])); |
742 | 0 | if (!useLP) a1i = FX_DBL2FX_SGL(fMult(bw, alphai[1])); |
743 | | |
744 | | /* |
745 | | Filter Step 3: insert the middle part which won't be windowed |
746 | | */ |
747 | 0 | if (bw <= FL2FXCONST_SGL(0.0f)) { |
748 | 0 | if (!useLP) { |
749 | 0 | int descale = |
750 | 0 | fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); |
751 | 0 | for (i = startSample; i < stopSample; i++) { |
752 | 0 | FIXP_DBL accu1, accu2; |
753 | 0 | accu1 = lowBandReal[LPC_ORDER + i] >> descale; |
754 | 0 | accu2 = lowBandImag[LPC_ORDER + i] >> descale; |
755 | 0 | if (fPreWhitening) { |
756 | 0 | accu1 = scaleValueSaturate( |
757 | 0 | fMultDiv2(accu1, preWhiteningGains[loBand]), |
758 | 0 | preWhiteningGains_exp[loBand] + 1); |
759 | 0 | accu2 = scaleValueSaturate( |
760 | 0 | fMultDiv2(accu2, preWhiteningGains[loBand]), |
761 | 0 | preWhiteningGains_exp[loBand] + 1); |
762 | 0 | } |
763 | 0 | qmfBufferReal[i][hiBand] = accu1; |
764 | 0 | qmfBufferImag[i][hiBand] = accu2; |
765 | 0 | } |
766 | 0 | } else { |
767 | 0 | int descale = |
768 | 0 | fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); |
769 | 0 | for (i = startSample; i < stopSample; i++) { |
770 | 0 | qmfBufferReal[i][hiBand] = lowBandReal[LPC_ORDER + i] >> descale; |
771 | 0 | } |
772 | 0 | } |
773 | 0 | } else { /* bw <= 0 */ |
774 | |
|
775 | 0 | if (!useLP) { |
776 | 0 | const int dynscale = fixMax(0, dynamicScale - 2) + 1; |
777 | 0 | const int rescale = -fixMin(0, dynamicScale - 2) + 1; |
778 | 0 | const int descale = fixMin(DFRACT_BITS - 1, |
779 | 0 | LPC_SCALE_FACTOR + dynamicScale + rescale); |
780 | |
|
781 | 0 | for (i = startSample; i < stopSample; i++) { |
782 | 0 | FIXP_DBL accu1, accu2; |
783 | |
|
784 | 0 | accu1 = ((fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) - |
785 | 0 | fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1])) >> |
786 | 0 | 1) + |
787 | 0 | ((fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) - |
788 | 0 | fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >> |
789 | 0 | 1); |
790 | 0 | accu2 = ((fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) + |
791 | 0 | fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1])) >> |
792 | 0 | 1) + |
793 | 0 | ((fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) + |
794 | 0 | fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >> |
795 | 0 | 1); |
796 | |
|
797 | 0 | accu1 = |
798 | 0 | (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 >> dynscale); |
799 | 0 | accu2 = |
800 | 0 | (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 >> dynscale); |
801 | 0 | if (fPreWhitening) { |
802 | 0 | qmfBufferReal[i][hiBand] = scaleValueSaturate( |
803 | 0 | fMultDiv2(accu1, preWhiteningGains[loBand]), |
804 | 0 | preWhiteningGains_exp[loBand] + 1 + rescale); |
805 | 0 | qmfBufferImag[i][hiBand] = scaleValueSaturate( |
806 | 0 | fMultDiv2(accu2, preWhiteningGains[loBand]), |
807 | 0 | preWhiteningGains_exp[loBand] + 1 + rescale); |
808 | 0 | } else { |
809 | 0 | qmfBufferReal[i][hiBand] = |
810 | 0 | SATURATE_LEFT_SHIFT(accu1, rescale, DFRACT_BITS); |
811 | 0 | qmfBufferImag[i][hiBand] = |
812 | 0 | SATURATE_LEFT_SHIFT(accu2, rescale, DFRACT_BITS); |
813 | 0 | } |
814 | 0 | } |
815 | 0 | } else { |
816 | 0 | FDK_ASSERT(dynamicScale >= 0); |
817 | 0 | calc_qmfBufferReal( |
818 | 0 | qmfBufferReal, &(lowBandReal[LPC_ORDER + startSample - 2]), |
819 | 0 | startSample, stopSample, hiBand, dynamicScale, a0r, a1r); |
820 | 0 | } |
821 | 0 | } /* bw <= 0 */ |
822 | | |
823 | 0 | patch++; |
824 | |
|
825 | 0 | } /* inner loop over patches */ |
826 | | |
827 | | /* |
828 | | * store the unmodified filter coefficients if there is |
829 | | * an overlapping envelope |
830 | | *****************************************************************/ |
831 | |
|
832 | 0 | } /* outer loop over bands (loBand) */ |
833 | | |
834 | 0 | if (useLP) { |
835 | 0 | for (loBand = pSettings->lbStartPatching; |
836 | 0 | loBand < pSettings->lbStopPatching; loBand++) { |
837 | 0 | patch = 0; |
838 | 0 | while (patch < pSettings->noOfPatches) { |
839 | 0 | UCHAR hiBand = loBand + patchParam[patch].targetBandOffs; |
840 | |
|
841 | 0 | if (loBand < patchParam[patch].sourceStartBand || |
842 | 0 | loBand >= patchParam[patch].sourceStopBand || |
843 | 0 | hiBand >= (64) /* Highband out of range (biterror) */ |
844 | 0 | ) { |
845 | | /* Lowband not in current patch or highband out of range (might be |
846 | | * caused by biterrors)- proceed */ |
847 | 0 | patch++; |
848 | 0 | continue; |
849 | 0 | } |
850 | | |
851 | 0 | if (hiBand != patchParam[patch].targetStartBand) |
852 | 0 | degreeAlias[hiBand] = degreeAlias[loBand]; |
853 | |
|
854 | 0 | patch++; |
855 | 0 | } |
856 | 0 | } /* end for loop */ |
857 | 0 | } |
858 | |
|
859 | 0 | for (i = 0; i < nInvfBands; i++) { |
860 | 0 | hLppTrans->bwVectorOld[i] = bwVector[i]; |
861 | 0 | } |
862 | | |
863 | | /* |
864 | | set high band scale factor |
865 | | */ |
866 | 0 | sbrScaleFactor->hb_scale = comLowBandScale - (LPC_SCALE_FACTOR); |
867 | 0 | } |
868 | | |
869 | | void lppTransposerHBE( |
870 | | HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ |
871 | | HANDLE_HBE_TRANSPOSER hQmfTransposer, |
872 | | QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ |
873 | | FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband |
874 | | samples (source) */ |
875 | | FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of |
876 | | subband samples (source) */ |
877 | | const int timeStep, /*!< Time step of envelope */ |
878 | | const int firstSlotOffs, /*!< Start position in time */ |
879 | | const int lastSlotOffs, /*!< Number of overlap-slots into next frame */ |
880 | | const int nInvfBands, /*!< Number of bands for inverse filtering */ |
881 | | INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ |
882 | | INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */ |
883 | 0 | ) { |
884 | 0 | INT bwIndex; |
885 | 0 | FIXP_DBL bwVector[MAX_NUM_PATCHES_HBE]; /*!< pole moving factors */ |
886 | |
|
887 | 0 | int i; |
888 | 0 | int loBand, start, stop; |
889 | 0 | TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings; |
890 | 0 | PATCH_PARAM *patchParam = pSettings->patchParam; |
891 | |
|
892 | 0 | FIXP_SGL alphar[LPC_ORDER], a0r, a1r; |
893 | 0 | FIXP_SGL alphai[LPC_ORDER], a0i = 0, a1i = 0; |
894 | 0 | FIXP_SGL bw = FL2FXCONST_SGL(0.0f); |
895 | |
|
896 | 0 | int autoCorrLength; |
897 | |
|
898 | 0 | ACORR_COEFS ac; |
899 | 0 | int startSample; |
900 | 0 | int stopSample; |
901 | 0 | int stopSampleClear; |
902 | |
|
903 | 0 | int comBandScale; |
904 | 0 | int ovLowBandShift; |
905 | 0 | int lowBandShift; |
906 | | /* int ovHighBandShift;*/ |
907 | |
|
908 | 0 | alphai[0] = FL2FXCONST_SGL(0.0f); |
909 | 0 | alphai[1] = FL2FXCONST_SGL(0.0f); |
910 | |
|
911 | 0 | startSample = firstSlotOffs * timeStep; |
912 | 0 | stopSample = pSettings->nCols + lastSlotOffs * timeStep; |
913 | |
|
914 | 0 | inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode, |
915 | 0 | sbr_invf_mode_prev, bwVector); |
916 | |
|
917 | 0 | stopSampleClear = stopSample; |
918 | |
|
919 | 0 | autoCorrLength = pSettings->nCols + pSettings->overlap; |
920 | |
|
921 | 0 | if (pSettings->noOfPatches > 0) { |
922 | | /* Set upper subbands to zero: |
923 | | This is required in case that the patches do not cover the complete |
924 | | highband (because the last patch would be too short). Possible |
925 | | optimization: Clearing bands up to usb would be sufficient here. */ |
926 | 0 | int targetStopBand = |
927 | 0 | patchParam[pSettings->noOfPatches - 1].targetStartBand + |
928 | 0 | patchParam[pSettings->noOfPatches - 1].numBandsInPatch; |
929 | |
|
930 | 0 | int memSize = ((64) - targetStopBand) * sizeof(FIXP_DBL); |
931 | |
|
932 | 0 | for (i = startSample; i < stopSampleClear; i++) { |
933 | 0 | FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); |
934 | 0 | FDKmemclear(&qmfBufferImag[i][targetStopBand], memSize); |
935 | 0 | } |
936 | 0 | } |
937 | | #if defined __ANDROID__ && !defined __ANDROID_NDK__ |
938 | | else { |
939 | | // Safetynet logging |
940 | | android_errorWriteLog(0x534e4554, "112160868"); |
941 | | } |
942 | | #endif |
943 | | |
944 | | /* |
945 | | Calc common low band scale factor |
946 | | */ |
947 | 0 | comBandScale = sbrScaleFactor->hb_scale; |
948 | |
|
949 | 0 | ovLowBandShift = sbrScaleFactor->hb_scale - comBandScale; |
950 | 0 | lowBandShift = sbrScaleFactor->hb_scale - comBandScale; |
951 | | /* ovHighBandShift = firstSlotOffs == 0 ? ovLowBandShift:0;*/ |
952 | | |
953 | | /* outer loop over bands to do analysis only once for each band */ |
954 | |
|
955 | 0 | start = hQmfTransposer->startBand; |
956 | 0 | stop = hQmfTransposer->stopBand; |
957 | |
|
958 | 0 | for (loBand = start; loBand < stop; loBand++) { |
959 | 0 | bwIndex = 0; |
960 | |
|
961 | 0 | FIXP_DBL lowBandReal[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; |
962 | 0 | FIXP_DBL lowBandImag[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; |
963 | |
|
964 | 0 | int resetLPCCoeffs = 0; |
965 | 0 | int dynamicScale = DFRACT_BITS - 1 - LPC_SCALE_FACTOR; |
966 | 0 | int acDetScale = 0; /* scaling of autocorrelation determinant */ |
967 | |
|
968 | 0 | for (i = 0; i < LPC_ORDER; i++) { |
969 | 0 | lowBandReal[i] = hLppTrans->lpcFilterStatesRealHBE[i][loBand]; |
970 | 0 | lowBandImag[i] = hLppTrans->lpcFilterStatesImagHBE[i][loBand]; |
971 | 0 | } |
972 | |
|
973 | 0 | for (; i < LPC_ORDER + firstSlotOffs * timeStep; i++) { |
974 | 0 | lowBandReal[i] = hLppTrans->lpcFilterStatesRealHBE[i][loBand]; |
975 | 0 | lowBandImag[i] = hLppTrans->lpcFilterStatesImagHBE[i][loBand]; |
976 | 0 | } |
977 | | |
978 | | /* |
979 | | Take old slope length qmf slot source values out of (overlap)qmf buffer |
980 | | */ |
981 | 0 | for (i = firstSlotOffs * timeStep; |
982 | 0 | i < pSettings->nCols + pSettings->overlap; i++) { |
983 | 0 | lowBandReal[i + LPC_ORDER] = qmfBufferReal[i][loBand]; |
984 | 0 | lowBandImag[i + LPC_ORDER] = qmfBufferImag[i][loBand]; |
985 | 0 | } |
986 | | |
987 | | /* store unmodified values to buffer */ |
988 | 0 | for (i = 0; i < LPC_ORDER + pSettings->overlap; i++) { |
989 | 0 | hLppTrans->lpcFilterStatesRealHBE[i][loBand] = |
990 | 0 | qmfBufferReal[pSettings->nCols - LPC_ORDER + i][loBand]; |
991 | 0 | hLppTrans->lpcFilterStatesImagHBE[i][loBand] = |
992 | 0 | qmfBufferImag[pSettings->nCols - LPC_ORDER + i][loBand]; |
993 | 0 | } |
994 | | |
995 | | /* |
996 | | Determine dynamic scaling value. |
997 | | */ |
998 | 0 | dynamicScale = |
999 | 0 | fixMin(dynamicScale, |
1000 | 0 | getScalefactor(lowBandReal, LPC_ORDER + pSettings->overlap) + |
1001 | 0 | ovLowBandShift); |
1002 | 0 | dynamicScale = |
1003 | 0 | fixMin(dynamicScale, |
1004 | 0 | getScalefactor(&lowBandReal[LPC_ORDER + pSettings->overlap], |
1005 | 0 | pSettings->nCols) + |
1006 | 0 | lowBandShift); |
1007 | 0 | dynamicScale = |
1008 | 0 | fixMin(dynamicScale, |
1009 | 0 | getScalefactor(lowBandImag, LPC_ORDER + pSettings->overlap) + |
1010 | 0 | ovLowBandShift); |
1011 | 0 | dynamicScale = |
1012 | 0 | fixMin(dynamicScale, |
1013 | 0 | getScalefactor(&lowBandImag[LPC_ORDER + pSettings->overlap], |
1014 | 0 | pSettings->nCols) + |
1015 | 0 | lowBandShift); |
1016 | |
|
1017 | 0 | dynamicScale = |
1018 | 0 | dynamicScale - 1; /* one additional bit headroom to prevent -1.0 */ |
1019 | | |
1020 | | /* |
1021 | | Scale temporal QMF buffer. |
1022 | | */ |
1023 | 0 | scaleValues(&lowBandReal[0], LPC_ORDER + pSettings->overlap, |
1024 | 0 | dynamicScale - ovLowBandShift); |
1025 | 0 | scaleValues(&lowBandReal[LPC_ORDER + pSettings->overlap], pSettings->nCols, |
1026 | 0 | dynamicScale - lowBandShift); |
1027 | 0 | scaleValues(&lowBandImag[0], LPC_ORDER + pSettings->overlap, |
1028 | 0 | dynamicScale - ovLowBandShift); |
1029 | 0 | scaleValues(&lowBandImag[LPC_ORDER + pSettings->overlap], pSettings->nCols, |
1030 | 0 | dynamicScale - lowBandShift); |
1031 | |
|
1032 | 0 | acDetScale += autoCorr2nd_cplx(&ac, lowBandReal + LPC_ORDER, |
1033 | 0 | lowBandImag + LPC_ORDER, autoCorrLength); |
1034 | | |
1035 | | /* Examine dynamic of determinant in autocorrelation. */ |
1036 | 0 | acDetScale += 2 * (comBandScale + dynamicScale); |
1037 | 0 | acDetScale *= 2; /* two times reflection coefficent scaling */ |
1038 | 0 | acDetScale += ac.det_scale; /* ac scaling of determinant */ |
1039 | | |
1040 | | /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */ |
1041 | 0 | if (acDetScale > 126) { |
1042 | 0 | resetLPCCoeffs = 1; |
1043 | 0 | } |
1044 | |
|
1045 | 0 | alphar[1] = FL2FXCONST_SGL(0.0f); |
1046 | 0 | alphai[1] = FL2FXCONST_SGL(0.0f); |
1047 | |
|
1048 | 0 | if (ac.det != FL2FXCONST_DBL(0.0f)) { |
1049 | 0 | FIXP_DBL tmp, absTmp, absDet; |
1050 | |
|
1051 | 0 | absDet = fixp_abs(ac.det); |
1052 | |
|
1053 | 0 | tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) - |
1054 | 0 | ((fMultDiv2(ac.r01i, ac.r12i) + fMultDiv2(ac.r02r, ac.r11r)) >> |
1055 | 0 | (LPC_SCALE_FACTOR - 1)); |
1056 | 0 | absTmp = fixp_abs(tmp); |
1057 | | |
1058 | | /* |
1059 | | Quick check: is first filter coeff >= 1(4) |
1060 | | */ |
1061 | 0 | { |
1062 | 0 | INT scale; |
1063 | 0 | FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); |
1064 | 0 | scale = scale + ac.det_scale; |
1065 | |
|
1066 | 0 | if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) { |
1067 | 0 | resetLPCCoeffs = 1; |
1068 | 0 | } else { |
1069 | 0 | alphar[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale)); |
1070 | 0 | if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { |
1071 | 0 | alphar[1] = -alphar[1]; |
1072 | 0 | } |
1073 | 0 | } |
1074 | 0 | } |
1075 | |
|
1076 | 0 | tmp = (fMultDiv2(ac.r01i, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) + |
1077 | 0 | ((fMultDiv2(ac.r01r, ac.r12i) - |
1078 | 0 | (FIXP_DBL)fMultDiv2(ac.r02i, ac.r11r)) >> |
1079 | 0 | (LPC_SCALE_FACTOR - 1)); |
1080 | |
|
1081 | 0 | absTmp = fixp_abs(tmp); |
1082 | | |
1083 | | /* |
1084 | | Quick check: is second filter coeff >= 1(4) |
1085 | | */ |
1086 | 0 | { |
1087 | 0 | INT scale; |
1088 | 0 | FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); |
1089 | 0 | scale = scale + ac.det_scale; |
1090 | |
|
1091 | 0 | if ((scale > 0) && |
1092 | 0 | (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL >> scale)) { |
1093 | 0 | resetLPCCoeffs = 1; |
1094 | 0 | } else { |
1095 | 0 | alphai[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale)); |
1096 | 0 | if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { |
1097 | 0 | alphai[1] = -alphai[1]; |
1098 | 0 | } |
1099 | 0 | } |
1100 | 0 | } |
1101 | 0 | } |
1102 | |
|
1103 | 0 | alphar[0] = FL2FXCONST_SGL(0.0f); |
1104 | 0 | alphai[0] = FL2FXCONST_SGL(0.0f); |
1105 | |
|
1106 | 0 | if (ac.r11r != FL2FXCONST_DBL(0.0f)) { |
1107 | | /* ac.r11r is always >=0 */ |
1108 | 0 | FIXP_DBL tmp, absTmp; |
1109 | |
|
1110 | 0 | tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) + |
1111 | 0 | (fMultDiv2(alphar[1], ac.r12r) + fMultDiv2(alphai[1], ac.r12i)); |
1112 | |
|
1113 | 0 | absTmp = fixp_abs(tmp); |
1114 | | |
1115 | | /* |
1116 | | Quick check: is first filter coeff >= 1(4) |
1117 | | */ |
1118 | |
|
1119 | 0 | if (absTmp >= (ac.r11r >> 1)) { |
1120 | 0 | resetLPCCoeffs = 1; |
1121 | 0 | } else { |
1122 | 0 | INT scale; |
1123 | 0 | FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); |
1124 | 0 | alphar[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1)); |
1125 | |
|
1126 | 0 | if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) |
1127 | 0 | alphar[0] = -alphar[0]; |
1128 | 0 | } |
1129 | |
|
1130 | 0 | tmp = (ac.r01i >> (LPC_SCALE_FACTOR + 1)) + |
1131 | 0 | (fMultDiv2(alphai[1], ac.r12r) - fMultDiv2(alphar[1], ac.r12i)); |
1132 | |
|
1133 | 0 | absTmp = fixp_abs(tmp); |
1134 | | |
1135 | | /* |
1136 | | Quick check: is second filter coeff >= 1(4) |
1137 | | */ |
1138 | 0 | if (absTmp >= (ac.r11r >> 1)) { |
1139 | 0 | resetLPCCoeffs = 1; |
1140 | 0 | } else { |
1141 | 0 | INT scale; |
1142 | 0 | FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); |
1143 | 0 | alphai[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1)); |
1144 | 0 | if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) { |
1145 | 0 | alphai[0] = -alphai[0]; |
1146 | 0 | } |
1147 | 0 | } |
1148 | 0 | } |
1149 | | |
1150 | | /* Now check the quadratic criteria */ |
1151 | 0 | if ((fMultDiv2(alphar[0], alphar[0]) + fMultDiv2(alphai[0], alphai[0])) >= |
1152 | 0 | FL2FXCONST_DBL(0.5f)) { |
1153 | 0 | resetLPCCoeffs = 1; |
1154 | 0 | } |
1155 | 0 | if ((fMultDiv2(alphar[1], alphar[1]) + fMultDiv2(alphai[1], alphai[1])) >= |
1156 | 0 | FL2FXCONST_DBL(0.5f)) { |
1157 | 0 | resetLPCCoeffs = 1; |
1158 | 0 | } |
1159 | |
|
1160 | 0 | if (resetLPCCoeffs) { |
1161 | 0 | alphar[0] = FL2FXCONST_SGL(0.0f); |
1162 | 0 | alphar[1] = FL2FXCONST_SGL(0.0f); |
1163 | 0 | alphai[0] = FL2FXCONST_SGL(0.0f); |
1164 | 0 | alphai[1] = FL2FXCONST_SGL(0.0f); |
1165 | 0 | } |
1166 | |
|
1167 | 0 | while (bwIndex < MAX_NUM_PATCHES - 1 && |
1168 | 0 | loBand >= pSettings->bwBorders[bwIndex]) { |
1169 | 0 | bwIndex++; |
1170 | 0 | } |
1171 | | |
1172 | | /* |
1173 | | Filter Step 2: add the left slope with the current filter to the buffer |
1174 | | pure source values are already in there |
1175 | | */ |
1176 | 0 | bw = FX_DBL2FX_SGL(bwVector[bwIndex]); |
1177 | |
|
1178 | 0 | a0r = FX_DBL2FX_SGL( |
1179 | 0 | fMult(bw, alphar[0])); /* Apply current bandwidth expansion factor */ |
1180 | 0 | a0i = FX_DBL2FX_SGL(fMult(bw, alphai[0])); |
1181 | 0 | bw = FX_DBL2FX_SGL(fPow2(bw)); |
1182 | 0 | a1r = FX_DBL2FX_SGL(fMult(bw, alphar[1])); |
1183 | 0 | a1i = FX_DBL2FX_SGL(fMult(bw, alphai[1])); |
1184 | | |
1185 | | /* |
1186 | | Filter Step 3: insert the middle part which won't be windowed |
1187 | | */ |
1188 | 0 | if (bw <= FL2FXCONST_SGL(0.0f)) { |
1189 | 0 | int descale = fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); |
1190 | 0 | for (i = startSample; i < stopSample; i++) { |
1191 | 0 | qmfBufferReal[i][loBand] = lowBandReal[LPC_ORDER + i] >> descale; |
1192 | 0 | qmfBufferImag[i][loBand] = lowBandImag[LPC_ORDER + i] >> descale; |
1193 | 0 | } |
1194 | 0 | } else { /* bw <= 0 */ |
1195 | |
|
1196 | 0 | int descale = fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); |
1197 | 0 | dynamicScale += |
1198 | 0 | 1; /* prevent negativ scale factor due to 'one additional bit |
1199 | | headroom' */ |
1200 | |
|
1201 | 0 | for (i = startSample; i < stopSample; i++) { |
1202 | 0 | FIXP_DBL accu1, accu2; |
1203 | |
|
1204 | 0 | accu1 = (fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) - |
1205 | 0 | fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1]) + |
1206 | 0 | fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) - |
1207 | 0 | fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >> |
1208 | 0 | dynamicScale; |
1209 | 0 | accu2 = (fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) + |
1210 | 0 | fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1]) + |
1211 | 0 | fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) + |
1212 | 0 | fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >> |
1213 | 0 | dynamicScale; |
1214 | |
|
1215 | 0 | qmfBufferReal[i][loBand] = |
1216 | 0 | (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 << (1 + 1)); |
1217 | 0 | qmfBufferImag[i][loBand] = |
1218 | 0 | (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 << (1 + 1)); |
1219 | 0 | } |
1220 | 0 | } /* bw <= 0 */ |
1221 | | |
1222 | | /* |
1223 | | * store the unmodified filter coefficients if there is |
1224 | | * an overlapping envelope |
1225 | | *****************************************************************/ |
1226 | |
|
1227 | 0 | } /* outer loop over bands (loBand) */ |
1228 | |
|
1229 | 0 | for (i = 0; i < nInvfBands; i++) { |
1230 | 0 | hLppTrans->bwVectorOld[i] = bwVector[i]; |
1231 | 0 | } |
1232 | | |
1233 | | /* |
1234 | | set high band scale factor |
1235 | | */ |
1236 | 0 | sbrScaleFactor->hb_scale = comBandScale - (LPC_SCALE_FACTOR); |
1237 | 0 | } |
1238 | | |
1239 | | /*! |
1240 | | * |
1241 | | * \brief Initialize one low power transposer instance |
1242 | | * |
1243 | | * |
1244 | | */ |
1245 | | SBR_ERROR |
1246 | | createLppTransposer( |
1247 | | HANDLE_SBR_LPP_TRANS hs, /*!< Handle of low power transposer */ |
1248 | | TRANSPOSER_SETTINGS *pSettings, /*!< Pointer to settings */ |
1249 | | const int highBandStartSb, /*!< ? */ |
1250 | | UCHAR *v_k_master, /*!< Master table */ |
1251 | | const int numMaster, /*!< Valid entries in master table */ |
1252 | | const int usb, /*!< Highband area stop subband */ |
1253 | | const int timeSlots, /*!< Number of time slots */ |
1254 | | const int nCols, /*!< Number of colums (codec qmf bank) */ |
1255 | | UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */ |
1256 | | const int noNoiseBands, /*!< Number of noise bands */ |
1257 | | UINT fs, /*!< Sample Frequency */ |
1258 | | const int chan, /*!< Channel number */ |
1259 | 0 | const int overlap) { |
1260 | | /* FB inverse filtering settings */ |
1261 | 0 | hs->pSettings = pSettings; |
1262 | |
|
1263 | 0 | pSettings->nCols = nCols; |
1264 | 0 | pSettings->overlap = overlap; |
1265 | |
|
1266 | 0 | switch (timeSlots) { |
1267 | 0 | case 15: |
1268 | 0 | case 16: |
1269 | 0 | break; |
1270 | | |
1271 | 0 | default: |
1272 | 0 | return SBRDEC_UNSUPPORTED_CONFIG; /* Unimplemented */ |
1273 | 0 | } |
1274 | | |
1275 | 0 | if (chan == 0) { |
1276 | | /* Init common data only once */ |
1277 | 0 | hs->pSettings->nCols = nCols; |
1278 | |
|
1279 | 0 | return resetLppTransposer(hs, highBandStartSb, v_k_master, numMaster, |
1280 | 0 | noiseBandTable, noNoiseBands, usb, fs); |
1281 | 0 | } |
1282 | 0 | return SBRDEC_OK; |
1283 | 0 | } |
1284 | | |
1285 | | static int findClosestEntry(UCHAR goalSb, UCHAR *v_k_master, UCHAR numMaster, |
1286 | 0 | UCHAR direction) { |
1287 | 0 | int index; |
1288 | |
|
1289 | 0 | if (goalSb <= v_k_master[0]) return v_k_master[0]; |
1290 | | |
1291 | 0 | if (goalSb >= v_k_master[numMaster]) return v_k_master[numMaster]; |
1292 | | |
1293 | 0 | if (direction) { |
1294 | 0 | index = 0; |
1295 | 0 | while (v_k_master[index] < goalSb) { |
1296 | 0 | index++; |
1297 | 0 | } |
1298 | 0 | } else { |
1299 | 0 | index = numMaster; |
1300 | 0 | while (v_k_master[index] > goalSb) { |
1301 | 0 | index--; |
1302 | 0 | } |
1303 | 0 | } |
1304 | |
|
1305 | 0 | return v_k_master[index]; |
1306 | 0 | } |
1307 | | |
1308 | | /*! |
1309 | | * |
1310 | | * \brief Reset memory for one lpp transposer instance |
1311 | | * |
1312 | | * \return SBRDEC_OK on success, SBRDEC_UNSUPPORTED_CONFIG on error |
1313 | | */ |
1314 | | SBR_ERROR |
1315 | | resetLppTransposer( |
1316 | | HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ |
1317 | | UCHAR highBandStartSb, /*!< High band area: start subband */ |
1318 | | UCHAR *v_k_master, /*!< Master table */ |
1319 | | UCHAR numMaster, /*!< Valid entries in master table */ |
1320 | | UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */ |
1321 | | UCHAR noNoiseBands, /*!< Number of noise bands */ |
1322 | | UCHAR usb, /*!< High band area: stop subband */ |
1323 | | UINT fs /*!< SBR output sampling frequency */ |
1324 | 0 | ) { |
1325 | 0 | TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings; |
1326 | 0 | PATCH_PARAM *patchParam = pSettings->patchParam; |
1327 | |
|
1328 | 0 | int i, patch; |
1329 | 0 | int targetStopBand; |
1330 | 0 | int sourceStartBand; |
1331 | 0 | int patchDistance; |
1332 | 0 | int numBandsInPatch; |
1333 | |
|
1334 | 0 | int lsb = v_k_master[0]; /* Start subband expressed in "non-critical" sampling |
1335 | | terms*/ |
1336 | 0 | int xoverOffset = highBandStartSb - |
1337 | 0 | lsb; /* Calculate distance in QMF bands between k0 and kx */ |
1338 | 0 | int startFreqHz; |
1339 | |
|
1340 | 0 | int desiredBorder; |
1341 | |
|
1342 | 0 | usb = fixMin(usb, v_k_master[numMaster]); /* Avoid endless loops (compare with |
1343 | | float code). */ |
1344 | | |
1345 | | /* |
1346 | | * Plausibility check |
1347 | | */ |
1348 | |
|
1349 | 0 | if (pSettings->nCols == 64) { |
1350 | 0 | if (lsb < 4) { |
1351 | | /* 4:1 SBR Requirement k0 >= 4 missed! */ |
1352 | 0 | return SBRDEC_UNSUPPORTED_CONFIG; |
1353 | 0 | } |
1354 | 0 | } else if (lsb - SHIFT_START_SB < 4) { |
1355 | 0 | return SBRDEC_UNSUPPORTED_CONFIG; |
1356 | 0 | } |
1357 | | |
1358 | | /* |
1359 | | * Initialize the patching parameter |
1360 | | */ |
1361 | | /* ISO/IEC 14496-3 (Figure 4.48): goalSb = round( 2.048e6 / fs ) */ |
1362 | 0 | desiredBorder = (((2048000 * 2) / fs) + 1) >> 1; |
1363 | |
|
1364 | 0 | desiredBorder = findClosestEntry(desiredBorder, v_k_master, numMaster, |
1365 | 0 | 1); /* Adapt region to master-table */ |
1366 | | |
1367 | | /* First patch */ |
1368 | 0 | sourceStartBand = SHIFT_START_SB + xoverOffset; |
1369 | 0 | targetStopBand = lsb + xoverOffset; /* upperBand */ |
1370 | | |
1371 | | /* Even (odd) numbered channel must be patched to even (odd) numbered channel |
1372 | | */ |
1373 | 0 | patch = 0; |
1374 | 0 | while (targetStopBand < usb) { |
1375 | | /* Too many patches? |
1376 | | Allow MAX_NUM_PATCHES+1 patches here. |
1377 | | we need to check later again, since patch might be the highest patch |
1378 | | AND contain less than 3 bands => actual number of patches will be reduced |
1379 | | by 1. |
1380 | | */ |
1381 | 0 | if (patch > MAX_NUM_PATCHES) { |
1382 | 0 | return SBRDEC_UNSUPPORTED_CONFIG; |
1383 | 0 | } |
1384 | | |
1385 | 0 | patchParam[patch].guardStartBand = targetStopBand; |
1386 | 0 | patchParam[patch].targetStartBand = targetStopBand; |
1387 | |
|
1388 | 0 | numBandsInPatch = |
1389 | 0 | desiredBorder - targetStopBand; /* Get the desired range of the patch */ |
1390 | |
|
1391 | 0 | if (numBandsInPatch >= lsb - sourceStartBand) { |
1392 | | /* Desired number bands are not available -> patch whole source range */ |
1393 | 0 | patchDistance = |
1394 | 0 | targetStopBand - sourceStartBand; /* Get the targetOffset */ |
1395 | 0 | patchDistance = |
1396 | 0 | patchDistance & ~1; /* Rounding off odd numbers and make all even */ |
1397 | 0 | numBandsInPatch = |
1398 | 0 | lsb - (targetStopBand - |
1399 | 0 | patchDistance); /* Update number of bands to be patched */ |
1400 | 0 | numBandsInPatch = findClosestEntry(targetStopBand + numBandsInPatch, |
1401 | 0 | v_k_master, numMaster, 0) - |
1402 | 0 | targetStopBand; /* Adapt region to master-table */ |
1403 | 0 | } |
1404 | |
|
1405 | 0 | if (pSettings->nCols == 64) { |
1406 | 0 | if (numBandsInPatch == 0 && sourceStartBand == SHIFT_START_SB) { |
1407 | 0 | return SBRDEC_UNSUPPORTED_CONFIG; |
1408 | 0 | } |
1409 | 0 | } |
1410 | | |
1411 | | /* Desired number bands are available -> get the minimal even patching |
1412 | | * distance */ |
1413 | 0 | patchDistance = |
1414 | 0 | numBandsInPatch + targetStopBand - lsb; /* Get minimal distance */ |
1415 | 0 | patchDistance = (patchDistance + 1) & |
1416 | 0 | ~1; /* Rounding up odd numbers and make all even */ |
1417 | |
|
1418 | 0 | if (numBandsInPatch > 0) { |
1419 | 0 | patchParam[patch].sourceStartBand = targetStopBand - patchDistance; |
1420 | 0 | patchParam[patch].targetBandOffs = patchDistance; |
1421 | 0 | patchParam[patch].numBandsInPatch = numBandsInPatch; |
1422 | 0 | patchParam[patch].sourceStopBand = |
1423 | 0 | patchParam[patch].sourceStartBand + numBandsInPatch; |
1424 | |
|
1425 | 0 | targetStopBand += patchParam[patch].numBandsInPatch; |
1426 | 0 | patch++; |
1427 | 0 | } |
1428 | | |
1429 | | /* All patches but first */ |
1430 | 0 | sourceStartBand = SHIFT_START_SB; |
1431 | | |
1432 | | /* Check if we are close to desiredBorder */ |
1433 | 0 | if (desiredBorder - targetStopBand < 3) /* MPEG doc */ |
1434 | 0 | { |
1435 | 0 | desiredBorder = usb; |
1436 | 0 | } |
1437 | 0 | } |
1438 | | |
1439 | 0 | patch--; |
1440 | | |
1441 | | /* If highest patch contains less than three subband: skip it */ |
1442 | 0 | if ((patch > 0) && (patchParam[patch].numBandsInPatch < 3)) { |
1443 | 0 | patch--; |
1444 | 0 | targetStopBand = |
1445 | 0 | patchParam[patch].targetStartBand + patchParam[patch].numBandsInPatch; |
1446 | 0 | } |
1447 | | |
1448 | | /* now check if we don't have one too many */ |
1449 | 0 | if (patch >= MAX_NUM_PATCHES) { |
1450 | 0 | return SBRDEC_UNSUPPORTED_CONFIG; |
1451 | 0 | } |
1452 | | |
1453 | 0 | pSettings->noOfPatches = patch + 1; |
1454 | | |
1455 | | /* Check lowest and highest source subband */ |
1456 | 0 | pSettings->lbStartPatching = targetStopBand; |
1457 | 0 | pSettings->lbStopPatching = 0; |
1458 | 0 | for (patch = 0; patch < pSettings->noOfPatches; patch++) { |
1459 | 0 | pSettings->lbStartPatching = |
1460 | 0 | fixMin(pSettings->lbStartPatching, patchParam[patch].sourceStartBand); |
1461 | 0 | pSettings->lbStopPatching = |
1462 | 0 | fixMax(pSettings->lbStopPatching, patchParam[patch].sourceStopBand); |
1463 | 0 | } |
1464 | |
|
1465 | 0 | for (i = 0; i < noNoiseBands; i++) { |
1466 | 0 | pSettings->bwBorders[i] = noiseBandTable[i + 1]; |
1467 | 0 | } |
1468 | 0 | for (; i < MAX_NUM_NOISE_VALUES; i++) { |
1469 | 0 | pSettings->bwBorders[i] = 255; |
1470 | 0 | } |
1471 | | |
1472 | | /* |
1473 | | * Choose whitening factors |
1474 | | */ |
1475 | |
|
1476 | 0 | startFreqHz = |
1477 | 0 | ((lsb + xoverOffset) * fs) >> 7; /* Shift does a division by 2*(64) */ |
1478 | |
|
1479 | 0 | for (i = 1; i < NUM_WHFACTOR_TABLE_ENTRIES; i++) { |
1480 | 0 | if (startFreqHz < FDK_sbrDecoder_sbr_whFactorsIndex[i]) break; |
1481 | 0 | } |
1482 | 0 | i--; |
1483 | |
|
1484 | 0 | pSettings->whFactors.off = FDK_sbrDecoder_sbr_whFactorsTable[i][0]; |
1485 | 0 | pSettings->whFactors.transitionLevel = |
1486 | 0 | FDK_sbrDecoder_sbr_whFactorsTable[i][1]; |
1487 | 0 | pSettings->whFactors.lowLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][2]; |
1488 | 0 | pSettings->whFactors.midLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][3]; |
1489 | 0 | pSettings->whFactors.highLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][4]; |
1490 | |
|
1491 | 0 | return SBRDEC_OK; |
1492 | 0 | } |