/src/fdk-aac/libSBRenc/src/nf_est.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 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten |
5 | | Forschung e.V. All rights reserved. |
6 | | |
7 | | 1. INTRODUCTION |
8 | | The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software |
9 | | that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding |
10 | | scheme for digital audio. This FDK AAC Codec software is intended to be used on |
11 | | a wide variety of Android devices. |
12 | | |
13 | | AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient |
14 | | general perceptual audio codecs. AAC-ELD is considered the best-performing |
15 | | full-bandwidth communications codec by independent studies and is widely |
16 | | deployed. AAC has been standardized by ISO and IEC as part of the MPEG |
17 | | specifications. |
18 | | |
19 | | Patent licenses for necessary patent claims for the FDK AAC Codec (including |
20 | | those of Fraunhofer) may be obtained through Via Licensing |
21 | | (www.vialicensing.com) or through the respective patent owners individually for |
22 | | the purpose of encoding or decoding bit streams in products that are compliant |
23 | | with the ISO/IEC MPEG audio standards. Please note that most manufacturers of |
24 | | Android devices already license these patent claims through Via Licensing or |
25 | | directly from the patent owners, and therefore FDK AAC Codec software may |
26 | | already be covered under those patent licenses when it is used for those |
27 | | licensed purposes only. |
28 | | |
29 | | Commercially-licensed AAC software libraries, including floating-point versions |
30 | | with enhanced sound quality, are also available from Fraunhofer. Users are |
31 | | encouraged to check the Fraunhofer website for additional applications |
32 | | information and documentation. |
33 | | |
34 | | 2. COPYRIGHT LICENSE |
35 | | |
36 | | Redistribution and use in source and binary forms, with or without modification, |
37 | | are permitted without payment of copyright license fees provided that you |
38 | | satisfy the following conditions: |
39 | | |
40 | | You must retain the complete text of this software license in redistributions of |
41 | | the FDK AAC Codec or your modifications thereto in source code form. |
42 | | |
43 | | You must retain the complete text of this software license in the documentation |
44 | | and/or other materials provided with redistributions of the FDK AAC Codec or |
45 | | your modifications thereto in binary form. You must make available free of |
46 | | charge copies of the complete source code of the FDK AAC Codec and your |
47 | | modifications thereto to recipients of copies in binary form. |
48 | | |
49 | | The name of Fraunhofer may not be used to endorse or promote products derived |
50 | | from this library without prior written permission. |
51 | | |
52 | | You may not charge copyright license fees for anyone to use, copy or distribute |
53 | | the FDK AAC Codec software or your modifications thereto. |
54 | | |
55 | | Your modified versions of the FDK AAC Codec must carry prominent notices stating |
56 | | that you changed the software and the date of any change. For modified versions |
57 | | of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" |
58 | | must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK |
59 | | AAC Codec Library for Android." |
60 | | |
61 | | 3. NO PATENT LICENSE |
62 | | |
63 | | NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without |
64 | | limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. |
65 | | Fraunhofer provides no warranty of patent non-infringement with respect to this |
66 | | software. |
67 | | |
68 | | You may use this FDK AAC Codec software or modifications thereto only for |
69 | | purposes that are authorized by appropriate patent licenses. |
70 | | |
71 | | 4. DISCLAIMER |
72 | | |
73 | | This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright |
74 | | holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, |
75 | | including but not limited to the implied warranties of merchantability and |
76 | | fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
77 | | CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, |
78 | | or consequential damages, including but not limited to procurement of substitute |
79 | | goods or services; loss of use, data, or profits, or business interruption, |
80 | | however caused and on any theory of liability, whether in contract, strict |
81 | | liability, or tort (including negligence), arising in any way out of the use of |
82 | | this software, even if advised of the possibility of such damage. |
83 | | |
84 | | 5. CONTACT INFORMATION |
85 | | |
86 | | Fraunhofer Institute for Integrated Circuits IIS |
87 | | Attention: Audio and Multimedia Departments - FDK AAC LL |
88 | | Am Wolfsmantel 33 |
89 | | 91058 Erlangen, Germany |
90 | | |
91 | | www.iis.fraunhofer.de/amm |
92 | | amm-info@iis.fraunhofer.de |
93 | | ----------------------------------------------------------------------------- */ |
94 | | |
95 | | /**************************** SBR encoder library ****************************** |
96 | | |
97 | | Author(s): |
98 | | |
99 | | Description: |
100 | | |
101 | | *******************************************************************************/ |
102 | | |
103 | | #include "nf_est.h" |
104 | | |
105 | | #include "sbr_misc.h" |
106 | | |
107 | | #include "genericStds.h" |
108 | | |
109 | | /* smoothFilter[4] = {0.05857864376269f, 0.2f, 0.34142135623731f, 0.4f}; */ |
110 | | static const FIXP_DBL smoothFilter[4] = {0x077f813d, 0x19999995, 0x2bb3b1f5, |
111 | | 0x33333335}; |
112 | | |
113 | | /* static const INT smoothFilterLength = 4; */ |
114 | | |
115 | | static const FIXP_DBL QuantOffset = (INT)0xfc000000; /* ld64(0.25) */ |
116 | | |
117 | | #ifndef min |
118 | 0 | #define min(a, b) (a < b ? a : b) |
119 | | #endif |
120 | | |
121 | | #ifndef max |
122 | | #define max(a, b) (a > b ? a : b) |
123 | | #endif |
124 | | |
125 | 0 | #define NOISE_FLOOR_OFFSET_SCALING (4) |
126 | | |
127 | | /**************************************************************************/ |
128 | | /*! |
129 | | \brief The function applies smoothing to the noise levels. |
130 | | |
131 | | |
132 | | |
133 | | \return none |
134 | | |
135 | | */ |
136 | | /**************************************************************************/ |
137 | | static void smoothingOfNoiseLevels( |
138 | | FIXP_DBL *NoiseLevels, /*!< pointer to noise-floor levels.*/ |
139 | | INT nEnvelopes, /*!< Number of noise floor envelopes.*/ |
140 | | INT noNoiseBands, /*!< Number of noise bands for every noise floor envelope. |
141 | | */ |
142 | | FIXP_DBL prevNoiseLevels[NF_SMOOTHING_LENGTH] |
143 | | [MAX_NUM_NOISE_VALUES], /*!< Previous noise floor |
144 | | envelopes. */ |
145 | | const FIXP_DBL * |
146 | | pSmoothFilter, /*!< filter used for smoothing the noise floor levels. */ |
147 | | INT transientFlag) /*!< flag indicating if a transient is present*/ |
148 | | |
149 | 0 | { |
150 | 0 | INT i, band, env; |
151 | 0 | FIXP_DBL accu; |
152 | |
|
153 | 0 | for (env = 0; env < nEnvelopes; env++) { |
154 | 0 | if (transientFlag) { |
155 | 0 | for (i = 0; i < NF_SMOOTHING_LENGTH; i++) { |
156 | 0 | FDKmemcpy(prevNoiseLevels[i], NoiseLevels + env * noNoiseBands, |
157 | 0 | noNoiseBands * sizeof(FIXP_DBL)); |
158 | 0 | } |
159 | 0 | } else { |
160 | 0 | for (i = 1; i < NF_SMOOTHING_LENGTH; i++) { |
161 | 0 | FDKmemcpy(prevNoiseLevels[i - 1], prevNoiseLevels[i], |
162 | 0 | noNoiseBands * sizeof(FIXP_DBL)); |
163 | 0 | } |
164 | 0 | FDKmemcpy(prevNoiseLevels[NF_SMOOTHING_LENGTH - 1], |
165 | 0 | NoiseLevels + env * noNoiseBands, |
166 | 0 | noNoiseBands * sizeof(FIXP_DBL)); |
167 | 0 | } |
168 | |
|
169 | 0 | for (band = 0; band < noNoiseBands; band++) { |
170 | 0 | accu = FL2FXCONST_DBL(0.0f); |
171 | 0 | for (i = 0; i < NF_SMOOTHING_LENGTH; i++) { |
172 | 0 | accu += fMultDiv2(pSmoothFilter[i], prevNoiseLevels[i][band]); |
173 | 0 | } |
174 | 0 | FDK_ASSERT((band + env * noNoiseBands) < MAX_NUM_NOISE_VALUES); |
175 | 0 | NoiseLevels[band + env * noNoiseBands] = accu << 1; |
176 | 0 | } |
177 | 0 | } |
178 | 0 | } |
179 | | |
180 | | /**************************************************************************/ |
181 | | /*! |
182 | | \brief Does the noise floor level estiamtion. |
183 | | |
184 | | The noiseLevel samples are scaled by the factor 0.25 |
185 | | |
186 | | \return none |
187 | | |
188 | | */ |
189 | | /**************************************************************************/ |
190 | | static void qmfBasedNoiseFloorDetection( |
191 | | FIXP_DBL *noiseLevel, /*!< Pointer to vector to |
192 | | store the noise levels |
193 | | in.*/ |
194 | | FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the quota |
195 | | values of the original. */ |
196 | | SCHAR *indexVector, /*!< Index vector to obtain the |
197 | | patched data. */ |
198 | | INT startIndex, /*!< Start index. */ |
199 | | INT stopIndex, /*!< Stop index. */ |
200 | | INT startChannel, /*!< Start channel of the current |
201 | | noise floor band.*/ |
202 | | INT stopChannel, /*!< Stop channel of the current |
203 | | noise floor band. */ |
204 | | FIXP_DBL ana_max_level, /*!< Maximum level of the |
205 | | adaptive noise.*/ |
206 | | FIXP_DBL noiseFloorOffset, /*!< Noise floor offset. */ |
207 | | INT missingHarmonicFlag, /*!< Flag indicating if a |
208 | | strong tonal component |
209 | | is missing.*/ |
210 | | FIXP_DBL weightFac, /*!< Weightening factor for the |
211 | | difference between orig and sbr. |
212 | | */ |
213 | | INVF_MODE diffThres, /*!< Threshold value to control the |
214 | | inverse filtering decision.*/ |
215 | | INVF_MODE inverseFilteringLevel) /*!< Inverse filtering |
216 | | level of the current |
217 | | band.*/ |
218 | 0 | { |
219 | 0 | INT scale, l, k; |
220 | 0 | FIXP_DBL meanOrig = FL2FXCONST_DBL(0.0f), meanSbr = FL2FXCONST_DBL(0.0f), |
221 | 0 | diff; |
222 | 0 | FIXP_DBL invIndex = GetInvInt(stopIndex - startIndex); |
223 | 0 | FIXP_DBL invChannel = GetInvInt(stopChannel - startChannel); |
224 | 0 | FIXP_DBL accu; |
225 | | |
226 | | /* |
227 | | Calculate the mean value, over the current time segment, for the original, the |
228 | | HFR and the difference, over all channels in the current frequency range. |
229 | | */ |
230 | |
|
231 | 0 | if (missingHarmonicFlag == 1) { |
232 | 0 | for (l = startChannel; l < stopChannel; l++) { |
233 | | /* tonalityOrig */ |
234 | 0 | accu = FL2FXCONST_DBL(0.0f); |
235 | 0 | for (k = startIndex; k < stopIndex; k++) { |
236 | 0 | accu += fMultDiv2(quotaMatrixOrig[k][l], invIndex); |
237 | 0 | } |
238 | 0 | meanOrig = fixMax(meanOrig, (accu << 1)); |
239 | | |
240 | | /* tonalitySbr */ |
241 | 0 | accu = FL2FXCONST_DBL(0.0f); |
242 | 0 | for (k = startIndex; k < stopIndex; k++) { |
243 | 0 | accu += fMultDiv2(quotaMatrixOrig[k][indexVector[l]], invIndex); |
244 | 0 | } |
245 | 0 | meanSbr = fixMax(meanSbr, (accu << 1)); |
246 | 0 | } |
247 | 0 | } else { |
248 | 0 | for (l = startChannel; l < stopChannel; l++) { |
249 | | /* tonalityOrig */ |
250 | 0 | accu = FL2FXCONST_DBL(0.0f); |
251 | 0 | for (k = startIndex; k < stopIndex; k++) { |
252 | 0 | accu += fMultDiv2(quotaMatrixOrig[k][l], invIndex); |
253 | 0 | } |
254 | 0 | meanOrig += fMult((accu << 1), invChannel); |
255 | | |
256 | | /* tonalitySbr */ |
257 | 0 | accu = FL2FXCONST_DBL(0.0f); |
258 | 0 | for (k = startIndex; k < stopIndex; k++) { |
259 | 0 | accu += fMultDiv2(quotaMatrixOrig[k][indexVector[l]], invIndex); |
260 | 0 | } |
261 | 0 | meanSbr += fMult((accu << 1), invChannel); |
262 | 0 | } |
263 | 0 | } |
264 | | |
265 | | /* Small fix to avoid noise during silent passages.*/ |
266 | 0 | if (meanOrig <= FL2FXCONST_DBL(0.000976562f * RELAXATION_FLOAT) && |
267 | 0 | meanSbr <= FL2FXCONST_DBL(0.000976562f * RELAXATION_FLOAT)) { |
268 | 0 | meanOrig = FL2FXCONST_DBL(101.5936673f * RELAXATION_FLOAT); |
269 | 0 | meanSbr = FL2FXCONST_DBL(101.5936673f * RELAXATION_FLOAT); |
270 | 0 | } |
271 | |
|
272 | 0 | meanOrig = fixMax(meanOrig, RELAXATION); |
273 | 0 | meanSbr = fixMax(meanSbr, RELAXATION); |
274 | |
|
275 | 0 | if (missingHarmonicFlag == 1 || inverseFilteringLevel == INVF_MID_LEVEL || |
276 | 0 | inverseFilteringLevel == INVF_LOW_LEVEL || |
277 | 0 | inverseFilteringLevel == INVF_OFF || inverseFilteringLevel <= diffThres) { |
278 | 0 | diff = RELAXATION; |
279 | 0 | } else { |
280 | 0 | accu = fDivNorm(meanSbr, meanOrig, &scale); |
281 | |
|
282 | 0 | diff = fixMax(RELAXATION, fMult(RELAXATION_FRACT, fMult(weightFac, accu)) >> |
283 | 0 | (RELAXATION_SHIFT - scale)); |
284 | 0 | } |
285 | | |
286 | | /* |
287 | | * noise Level is now a positive value, i.e. |
288 | | * the more harmonic the signal is the higher noise level, |
289 | | * this makes no sense so we change the sign. |
290 | | *********************************************************/ |
291 | 0 | accu = fDivNorm(diff, meanOrig, &scale); |
292 | 0 | scale -= 2; |
293 | |
|
294 | 0 | if ((scale > 0) && (accu > ((FIXP_DBL)MAXVAL_DBL) >> scale)) { |
295 | 0 | *noiseLevel = (FIXP_DBL)MAXVAL_DBL; |
296 | 0 | } else { |
297 | 0 | *noiseLevel = scaleValue(accu, scale); |
298 | 0 | } |
299 | | |
300 | | /* |
301 | | * Add a noise floor offset to compensate for bias in the detector |
302 | | *****************************************************************/ |
303 | 0 | if (!missingHarmonicFlag) { |
304 | 0 | *noiseLevel = fixMin(fMult(*noiseLevel, noiseFloorOffset), |
305 | 0 | (FIXP_DBL)MAXVAL_DBL >> NOISE_FLOOR_OFFSET_SCALING) |
306 | 0 | << NOISE_FLOOR_OFFSET_SCALING; |
307 | 0 | } |
308 | | |
309 | | /* |
310 | | * check to see that we don't exceed the maximum allowed level |
311 | | **************************************************************/ |
312 | 0 | *noiseLevel = |
313 | 0 | fixMin(*noiseLevel, |
314 | 0 | ana_max_level); /* ana_max_level is scaled with factor 0.25 */ |
315 | 0 | } |
316 | | |
317 | | /**************************************************************************/ |
318 | | /*! |
319 | | \brief Does the noise floor level estiamtion. |
320 | | The function calls the Noisefloor estimation function |
321 | | for the time segments decided based upon the transient |
322 | | information. The block is always divided into one or two segments. |
323 | | |
324 | | |
325 | | \return none |
326 | | |
327 | | */ |
328 | | /**************************************************************************/ |
329 | | void FDKsbrEnc_sbrNoiseFloorEstimateQmf( |
330 | | HANDLE_SBR_NOISE_FLOOR_ESTIMATE |
331 | | h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct |
332 | | */ |
333 | | const SBR_FRAME_INFO |
334 | | *frame_info, /*!< Time frequency grid of the current frame. */ |
335 | | FIXP_DBL |
336 | | *noiseLevels, /*!< Pointer to vector to store the noise levels in.*/ |
337 | | FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the quota values of the |
338 | | original. */ |
339 | | SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ |
340 | | INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component |
341 | | will be missing. */ |
342 | | INT startIndex, /*!< Start index. */ |
343 | | UINT numberOfEstimatesPerFrame, /*!< The number of tonality estimates per |
344 | | frame. */ |
345 | | int transientFrame, /*!< A flag indicating if a transient is present. */ |
346 | | INVF_MODE *pInvFiltLevels, /*!< Pointer to the vector holding the inverse |
347 | | filtering levels. */ |
348 | | UINT sbrSyntaxFlags) |
349 | | |
350 | 0 | { |
351 | 0 | INT nNoiseEnvelopes, startPos[2], stopPos[2], env, band; |
352 | |
|
353 | 0 | INT noNoiseBands = h_sbrNoiseFloorEstimate->noNoiseBands; |
354 | 0 | INT *freqBandTable = h_sbrNoiseFloorEstimate->freqBandTableQmf; |
355 | |
|
356 | 0 | nNoiseEnvelopes = frame_info->nNoiseEnvelopes; |
357 | |
|
358 | 0 | startPos[0] = startIndex; |
359 | |
|
360 | 0 | if (nNoiseEnvelopes == 1) { |
361 | 0 | stopPos[0] = startIndex + min(numberOfEstimatesPerFrame, 2); |
362 | 0 | } else { |
363 | 0 | stopPos[0] = startIndex + 1; |
364 | 0 | startPos[1] = startIndex + 1; |
365 | 0 | stopPos[1] = startIndex + min(numberOfEstimatesPerFrame, 2); |
366 | 0 | } |
367 | | |
368 | | /* |
369 | | * Estimate the noise floor. |
370 | | **************************************/ |
371 | 0 | for (env = 0; env < nNoiseEnvelopes; env++) { |
372 | 0 | for (band = 0; band < noNoiseBands; band++) { |
373 | 0 | FDK_ASSERT((band + env * noNoiseBands) < MAX_NUM_NOISE_VALUES); |
374 | 0 | qmfBasedNoiseFloorDetection( |
375 | 0 | &noiseLevels[band + env * noNoiseBands], quotaMatrixOrig, indexVector, |
376 | 0 | startPos[env], stopPos[env], freqBandTable[band], |
377 | 0 | freqBandTable[band + 1], h_sbrNoiseFloorEstimate->ana_max_level, |
378 | 0 | h_sbrNoiseFloorEstimate->noiseFloorOffset[band], missingHarmonicsFlag, |
379 | 0 | h_sbrNoiseFloorEstimate->weightFac, |
380 | 0 | h_sbrNoiseFloorEstimate->diffThres, pInvFiltLevels[band]); |
381 | 0 | } |
382 | 0 | } |
383 | | |
384 | | /* |
385 | | * Smoothing of the values. |
386 | | **************************/ |
387 | 0 | smoothingOfNoiseLevels(noiseLevels, nNoiseEnvelopes, |
388 | 0 | h_sbrNoiseFloorEstimate->noNoiseBands, |
389 | 0 | h_sbrNoiseFloorEstimate->prevNoiseLevels, |
390 | 0 | h_sbrNoiseFloorEstimate->smoothFilter, transientFrame); |
391 | | |
392 | | /* quantisation*/ |
393 | 0 | for (env = 0; env < nNoiseEnvelopes; env++) { |
394 | 0 | for (band = 0; band < noNoiseBands; band++) { |
395 | 0 | FDK_ASSERT((band + env * noNoiseBands) < MAX_NUM_NOISE_VALUES); |
396 | 0 | noiseLevels[band + env * noNoiseBands] = |
397 | 0 | (FIXP_DBL)NOISE_FLOOR_OFFSET_64 - |
398 | 0 | (FIXP_DBL)CalcLdData(noiseLevels[band + env * noNoiseBands] + |
399 | 0 | (FIXP_DBL)1) + |
400 | 0 | QuantOffset; |
401 | 0 | } |
402 | 0 | } |
403 | 0 | } |
404 | | |
405 | | /**************************************************************************/ |
406 | | /*! |
407 | | \brief |
408 | | |
409 | | |
410 | | \return errorCode, noError if successful |
411 | | |
412 | | */ |
413 | | /**************************************************************************/ |
414 | | static INT downSampleLoRes(INT *v_result, /*!< */ |
415 | | INT num_result, /*!< */ |
416 | | const UCHAR *freqBandTableRef, /*!< */ |
417 | | INT num_Ref) /*!< */ |
418 | 0 | { |
419 | 0 | INT step; |
420 | 0 | INT i, j; |
421 | 0 | INT org_length, result_length; |
422 | 0 | INT v_index[MAX_FREQ_COEFFS / 2]; |
423 | | |
424 | | /* init */ |
425 | 0 | org_length = num_Ref; |
426 | 0 | result_length = num_result; |
427 | |
|
428 | 0 | v_index[0] = 0; /* Always use left border */ |
429 | 0 | i = 0; |
430 | 0 | while (org_length > 0) /* Create downsample vector */ |
431 | 0 | { |
432 | 0 | i++; |
433 | 0 | step = org_length / result_length; /* floor; */ |
434 | 0 | org_length = org_length - step; |
435 | 0 | result_length--; |
436 | 0 | v_index[i] = v_index[i - 1] + step; |
437 | 0 | } |
438 | |
|
439 | 0 | if (i != num_result) /* Should never happen */ |
440 | 0 | return (1); /* error downsampling */ |
441 | | |
442 | 0 | for (j = 0; j <= i; |
443 | 0 | j++) /* Use downsample vector to index LoResolution vector. */ |
444 | 0 | { |
445 | 0 | v_result[j] = freqBandTableRef[v_index[j]]; |
446 | 0 | } |
447 | |
|
448 | 0 | return (0); |
449 | 0 | } |
450 | | |
451 | | /**************************************************************************/ |
452 | | /*! |
453 | | \brief Initialize an instance of the noise floor level estimation module. |
454 | | |
455 | | |
456 | | \return errorCode, noError if successful |
457 | | |
458 | | */ |
459 | | /**************************************************************************/ |
460 | | INT FDKsbrEnc_InitSbrNoiseFloorEstimate( |
461 | | HANDLE_SBR_NOISE_FLOOR_ESTIMATE |
462 | | h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct |
463 | | */ |
464 | | INT ana_max_level, /*!< Maximum level of the adaptive noise. */ |
465 | | const UCHAR *freqBandTable, /*!< Frequency band table. */ |
466 | | INT nSfb, /*!< Number of frequency bands. */ |
467 | | INT noiseBands, /*!< Number of noise bands per octave. */ |
468 | | INT noiseFloorOffset, /*!< Noise floor offset. */ |
469 | | INT timeSlots, /*!< Number of time slots in a frame. */ |
470 | | UINT useSpeechConfig /*!< Flag: adapt tuning parameters according to speech |
471 | | */ |
472 | 0 | ) { |
473 | 0 | INT i, qexp, qtmp; |
474 | 0 | FIXP_DBL tmp, exp; |
475 | |
|
476 | 0 | FDKmemclear(h_sbrNoiseFloorEstimate, sizeof(SBR_NOISE_FLOOR_ESTIMATE)); |
477 | |
|
478 | 0 | h_sbrNoiseFloorEstimate->smoothFilter = smoothFilter; |
479 | 0 | if (useSpeechConfig) { |
480 | 0 | h_sbrNoiseFloorEstimate->weightFac = (FIXP_DBL)MAXVAL_DBL; |
481 | 0 | h_sbrNoiseFloorEstimate->diffThres = INVF_LOW_LEVEL; |
482 | 0 | } else { |
483 | 0 | h_sbrNoiseFloorEstimate->weightFac = FL2FXCONST_DBL(0.25f); |
484 | 0 | h_sbrNoiseFloorEstimate->diffThres = INVF_MID_LEVEL; |
485 | 0 | } |
486 | |
|
487 | 0 | h_sbrNoiseFloorEstimate->timeSlots = timeSlots; |
488 | 0 | h_sbrNoiseFloorEstimate->noiseBands = noiseBands; |
489 | | |
490 | | /* h_sbrNoiseFloorEstimate->ana_max_level is scaled by 0.25 */ |
491 | 0 | switch (ana_max_level) { |
492 | 0 | case 6: |
493 | 0 | h_sbrNoiseFloorEstimate->ana_max_level = (FIXP_DBL)MAXVAL_DBL; |
494 | 0 | break; |
495 | 0 | case 3: |
496 | 0 | h_sbrNoiseFloorEstimate->ana_max_level = FL2FXCONST_DBL(0.5); |
497 | 0 | break; |
498 | 0 | case -3: |
499 | 0 | h_sbrNoiseFloorEstimate->ana_max_level = FL2FXCONST_DBL(0.125); |
500 | 0 | break; |
501 | 0 | default: |
502 | | /* Should not enter here */ |
503 | 0 | h_sbrNoiseFloorEstimate->ana_max_level = (FIXP_DBL)MAXVAL_DBL; |
504 | 0 | break; |
505 | 0 | } |
506 | | |
507 | | /* |
508 | | calculate number of noise bands and allocate |
509 | | */ |
510 | 0 | if (FDKsbrEnc_resetSbrNoiseFloorEstimate(h_sbrNoiseFloorEstimate, |
511 | 0 | freqBandTable, nSfb)) |
512 | 0 | return (1); |
513 | | |
514 | 0 | if (noiseFloorOffset == 0) { |
515 | 0 | tmp = ((FIXP_DBL)MAXVAL_DBL) >> NOISE_FLOOR_OFFSET_SCALING; |
516 | 0 | } else { |
517 | | /* noiseFloorOffset has to be smaller than 12, because |
518 | | the result of the calculation below must be smaller than 1: |
519 | | (2^(noiseFloorOffset/3))*2^4<1 */ |
520 | 0 | FDK_ASSERT(noiseFloorOffset < 12); |
521 | | |
522 | | /* Assumes the noise floor offset in tuning table are in q31 */ |
523 | | /* Change the qformat here when non-zero values would be filled */ |
524 | 0 | exp = fDivNorm((FIXP_DBL)noiseFloorOffset, 3, &qexp); |
525 | 0 | tmp = fPow(2, DFRACT_BITS - 1, exp, qexp, &qtmp); |
526 | 0 | tmp = scaleValue(tmp, qtmp - NOISE_FLOOR_OFFSET_SCALING); |
527 | 0 | } |
528 | | |
529 | 0 | for (i = 0; i < h_sbrNoiseFloorEstimate->noNoiseBands; i++) { |
530 | 0 | h_sbrNoiseFloorEstimate->noiseFloorOffset[i] = tmp; |
531 | 0 | } |
532 | |
|
533 | 0 | return (0); |
534 | 0 | } |
535 | | |
536 | | /**************************************************************************/ |
537 | | /*! |
538 | | \brief Resets the current instance of the noise floor estiamtion |
539 | | module. |
540 | | |
541 | | |
542 | | \return errorCode, noError if successful |
543 | | |
544 | | */ |
545 | | /**************************************************************************/ |
546 | | INT FDKsbrEnc_resetSbrNoiseFloorEstimate( |
547 | | HANDLE_SBR_NOISE_FLOOR_ESTIMATE |
548 | | h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct |
549 | | */ |
550 | | const UCHAR *freqBandTable, /*!< Frequency band table. */ |
551 | | INT nSfb /*!< Number of bands in the frequency band table. */ |
552 | 0 | ) { |
553 | 0 | INT k2, kx; |
554 | | |
555 | | /* |
556 | | * Calculate number of noise bands |
557 | | ***********************************/ |
558 | 0 | k2 = freqBandTable[nSfb]; |
559 | 0 | kx = freqBandTable[0]; |
560 | 0 | if (h_sbrNoiseFloorEstimate->noiseBands == 0) { |
561 | 0 | h_sbrNoiseFloorEstimate->noNoiseBands = 1; |
562 | 0 | } else { |
563 | | /* |
564 | | * Calculate number of noise bands 1,2 or 3 bands/octave |
565 | | ********************************************************/ |
566 | 0 | FIXP_DBL tmp, ratio, lg2; |
567 | 0 | INT ratio_e, qlg2, nNoiseBands; |
568 | |
|
569 | 0 | ratio = fDivNorm(k2, kx, &ratio_e); |
570 | 0 | lg2 = fLog2(ratio, ratio_e, &qlg2); |
571 | 0 | tmp = fMult((FIXP_DBL)(h_sbrNoiseFloorEstimate->noiseBands << 24), lg2); |
572 | 0 | tmp = scaleValue(tmp, qlg2 - 23); |
573 | |
|
574 | 0 | nNoiseBands = (INT)((tmp + (FIXP_DBL)1) >> 1); |
575 | |
|
576 | 0 | if (nNoiseBands > MAX_NUM_NOISE_COEFFS) { |
577 | 0 | nNoiseBands = MAX_NUM_NOISE_COEFFS; |
578 | 0 | } |
579 | |
|
580 | 0 | if (nNoiseBands == 0) { |
581 | 0 | nNoiseBands = 1; |
582 | 0 | } |
583 | |
|
584 | 0 | h_sbrNoiseFloorEstimate->noNoiseBands = nNoiseBands; |
585 | 0 | } |
586 | |
|
587 | 0 | return (downSampleLoRes(h_sbrNoiseFloorEstimate->freqBandTableQmf, |
588 | 0 | h_sbrNoiseFloorEstimate->noNoiseBands, freqBandTable, |
589 | 0 | nSfb)); |
590 | 0 | } |
591 | | |
592 | | /**************************************************************************/ |
593 | | /*! |
594 | | \brief Deletes the current instancce of the noise floor level |
595 | | estimation module. |
596 | | |
597 | | |
598 | | \return none |
599 | | |
600 | | */ |
601 | | /**************************************************************************/ |
602 | | void FDKsbrEnc_deleteSbrNoiseFloorEstimate( |
603 | | HANDLE_SBR_NOISE_FLOOR_ESTIMATE |
604 | | h_sbrNoiseFloorEstimate) /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct |
605 | | */ |
606 | 0 | { |
607 | 0 | if (h_sbrNoiseFloorEstimate) { |
608 | | /* |
609 | | nothing to do |
610 | | */ |
611 | 0 | } |
612 | 0 | } |