Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 :
6 : #include "cnst.h"
7 : #include "stl.h"
8 : //#include "prot_fx.h"
9 : #include "basop_util.h"
10 : #include "stl.h"
11 : #include <memory.h>
12 : #include <assert.h>
13 : #include "rom_com_fx.h"
14 : #include "rom_com.h"
15 : #include "prot_fx.h" /* Function prototypes */
16 : #include "prot_fx_enc.h" /* Function prototypes */
17 :
18 : #define HLM_MIN_NRG_FX 858993459 // ( 32768.0f * 2 * NORM_MDCT_FACTOR / ( 640 * 640 ) ) in Q26
19 :
20 : /** Get TNS filter parameters from autocorrelation.
21 : *
22 : * @param rxx Autocorrelation function/coefficients.
23 : * @param maxOrder Maximum filter order/number of coefficients.
24 : * @param pTnsFilter Pointer to the output filter.
25 : */
26 : static void GetFilterParameters( Word32 rxx[], Word16 maxOrder, STnsFilter *pTnsFilter );
27 :
28 : static void GetFilterParameters_ivas( Word32 rxx[], Word16 maxOrder, STnsFilter *pTnsFilter );
29 :
30 : /** Quantization for reflection coefficients.
31 : *
32 : * @param parCoeff input reflection coefficients.
33 : * @param index output quantized values.
34 : * @param order number of coefficients/values.
35 : */
36 : static void Parcor2Index( Word16 const parCoeff[], Word16 index[], Word16 order );
37 :
38 : /** Linear prediction analysis/synthesis filter definition.
39 : * @param order filter order.
40 : * @param parCoeff filter (PARCOR) coefficients.
41 : * @param state state of the filter. Must be at least of 'order' size.
42 : * @param x the current input value.
43 : * @return the output of the filter.
44 : */
45 : typedef Word32 ( *TLinearPredictionFilter )( Word16 order, Word16 const parCoeff[], Word32 *state, Word32 x );
46 :
47 :
48 : /********************************/
49 : /* Interface functions */
50 : /********************************/
51 :
52 : #define MAX_SUBDIVISIONS 3
53 :
54 372 : Word16 DetectTnsFilt_fx( STnsConfig const *pTnsConfig,
55 : Word32 const pSpectrum[],
56 : STnsData *pTnsData,
57 : Word16 *predictionGain )
58 : {
59 : Word16 facs[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS];
60 : Word16 facs_e[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS]; /* exponents of facs[][] */
61 : Word16 shifts[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS];
62 372 : Word16 iFilter = 0;
63 372 : move16();
64 :
65 372 : ResetTnsData( pTnsData );
66 :
67 372 : IF( pTnsConfig->maxOrder <= 0 )
68 : {
69 0 : return 0;
70 : }
71 :
72 : /* Calculate norms for each spectrum part */
73 744 : FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
74 : {
75 : Word16 idx0;
76 : Word16 idx1;
77 : Word16 nSubdivisions;
78 : Word16 iSubdivisions;
79 : #ifndef ISSUE_1867_replace_overflow_libenc
80 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
81 : Flag Overflow = 0;
82 : move32();
83 : #endif
84 : #endif
85 :
86 372 : move16();
87 372 : move16();
88 372 : move16();
89 372 : idx0 = pTnsConfig->iFilterBorders[iFilter + 1];
90 372 : idx1 = pTnsConfig->iFilterBorders[iFilter];
91 372 : nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
92 :
93 372 : assert( pTnsConfig->pTnsParameters[iFilter].nSubdivisions <= MAX_SUBDIVISIONS );
94 :
95 1488 : FOR( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ )
96 : {
97 : Word16 iStartLine;
98 : Word16 iEndLine;
99 : Word16 tmp, headroom, shift;
100 : Word32 L_tmp, tmp32;
101 :
102 : /* iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions;
103 : iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; */
104 1116 : assert( ( nSubdivisions == 1 ) || ( nSubdivisions == 3 ) );
105 :
106 1116 : tmp = sub( idx1, idx0 );
107 1116 : iStartLine = imult1616( tmp, iSubdivisions );
108 1116 : iEndLine = add( iStartLine, tmp );
109 :
110 1116 : IF( EQ_16( nSubdivisions, 3 ) )
111 : {
112 1116 : iStartLine = mult( iStartLine, 0x2AAB );
113 : }
114 1116 : iStartLine = add( iStartLine, idx0 );
115 :
116 1116 : IF( EQ_16( nSubdivisions, 3 ) )
117 : {
118 1116 : iEndLine = mult( iEndLine, 0x2AAB );
119 : }
120 1116 : iEndLine = add( iEndLine, idx0 );
121 :
122 : /*norms[iFilter][iSubdivisions] = norm2FLOAT(pSpectrum+iStartLine, iEndLine-iStartLine);*/
123 1116 : headroom = getScaleFactor32( &pSpectrum[iStartLine], sub( iEndLine, iStartLine ) );
124 :
125 : /* Calculate norm of spectrum band */
126 1116 : L_tmp = Norm32Norm( pSpectrum + iStartLine, headroom, sub( iEndLine, iStartLine ), &shift );
127 :
128 : /* Check threshold HLM_MIN_NRG */
129 : BASOP_SATURATE_WARNING_OFF_EVS;
130 : #ifdef ISSUE_1867_replace_overflow_libenc
131 1116 : tmp32 = L_sub( L_shl_sat( L_tmp, s_min( 31, sub( shift, 24 - 31 * 2 ) ) ), 3277l /*HLM_MIN_NRG Q7*/ );
132 : #else
133 : tmp32 = L_sub( L_shl_o( L_tmp, s_min( 31, sub( shift, 24 - 31 * 2 ) ), &Overflow ), 3277l /*HLM_MIN_NRG Q7*/ );
134 : #endif
135 : BASOP_SATURATE_WARNING_ON_EVS;
136 :
137 : /* get pre-shift for autocorrelation */
138 1116 : tmp = sub( shift, norm_l( L_tmp ) ); /* exponent for normalized L_tmp */
139 1116 : tmp = shr( sub( 1, tmp ), 1 ); /* pre-shift to apply before autocorrelation */
140 1116 : shifts[iFilter][iSubdivisions] = s_min( tmp, headroom );
141 1116 : move16();
142 :
143 : /* calc normalization factor */
144 1116 : facs[iFilter][iSubdivisions] = 0;
145 1116 : move16();
146 1116 : facs_e[iFilter][iSubdivisions] = 0;
147 1116 : move16();
148 :
149 1116 : if ( tmp32 > 0 )
150 : {
151 1116 : facs[iFilter][iSubdivisions] = 0x7FFF;
152 1116 : move16(); /* normalization not needed for one subdivision */
153 : }
154 :
155 1116 : test();
156 1116 : IF( ( tmp32 > 0 ) && ( GT_16( nSubdivisions, 1 ) ) )
157 : {
158 1116 : move16();
159 1116 : facs_e[iFilter][iSubdivisions] = shl( sub( tmp, shifts[iFilter][iSubdivisions] ), 1 );
160 :
161 1116 : tmp = sub( 1, shl( tmp, 1 ) ); /* exponent of autocorrelation */
162 1116 : L_tmp = L_shl_sat( L_tmp, sub( shift, tmp ) ); /* shift L_tmp to that exponent */
163 :
164 : /* calc factor (with 2 bits headroom for sum of 3 subdivisions) */
165 1116 : move16();
166 1116 : facs[iFilter][iSubdivisions] = div_s( 0x2000, round_fx_sat( L_tmp ) ); /* L_tmp is >= 0x2000000 */
167 : }
168 : }
169 : }
170 : /* Calculate normalized autocorrelation for spectrum subdivision and get TNS filter parameters based on it */
171 744 : FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
172 : {
173 : #define RXX_E ( 3 )
174 : Word32 rxx[TNS_MAX_FILTER_ORDER + 1];
175 : Word16 idx0;
176 : Word16 idx1;
177 : Word16 spectrumLength;
178 : STnsFilter *pFilter;
179 : Word16 nSubdivisions;
180 : Word16 iSubdivisions;
181 : Word16 tmpbuf[325];
182 :
183 372 : set32_fx( rxx, 0, TNS_MAX_FILTER_ORDER + 1 );
184 :
185 372 : move16();
186 372 : move16();
187 372 : move16();
188 372 : idx0 = pTnsConfig->iFilterBorders[iFilter + 1];
189 372 : idx1 = pTnsConfig->iFilterBorders[iFilter];
190 372 : spectrumLength = sub( idx1, idx0 );
191 372 : pFilter = pTnsData->filter + iFilter;
192 372 : nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
193 :
194 1488 : FOR( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ )
195 : {
196 : Word16 iStartLine, n, i;
197 : Word16 iEndLine;
198 : const Word16 *pWindow;
199 : Word16 lag, shift;
200 : Word32 L_tmp;
201 :
202 1116 : IF( facs[iFilter][iSubdivisions] == 0 )
203 : {
204 0 : BREAK;
205 : }
206 :
207 :
208 : /* iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions;
209 : iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; */
210 1116 : assert( ( nSubdivisions == 1 ) || ( nSubdivisions == 3 ) );
211 :
212 1116 : iStartLine = imult1616( spectrumLength, iSubdivisions );
213 1116 : iEndLine = add( iStartLine, spectrumLength );
214 :
215 1116 : IF( EQ_16( nSubdivisions, 3 ) )
216 : {
217 1116 : iStartLine = mult( iStartLine, 0x2AAB );
218 : }
219 1116 : iStartLine = add( iStartLine, idx0 );
220 :
221 1116 : IF( EQ_16( nSubdivisions, 3 ) )
222 : {
223 1116 : iEndLine = mult( iEndLine, 0x2AAB );
224 : }
225 1116 : iEndLine = add( iEndLine, idx0 );
226 :
227 :
228 1116 : move16();
229 1116 : shift = shifts[iFilter][iSubdivisions];
230 :
231 1116 : move16();
232 1116 : pWindow = tnsAcfWindow_fx;
233 :
234 1116 : n = sub( iEndLine, iStartLine );
235 1116 : assert( n < (Word16) ( sizeof( tmpbuf ) / sizeof( Word16 ) ) );
236 233810 : FOR( i = 0; i < n; i++ )
237 : {
238 232694 : tmpbuf[i] = round_fx_sat( L_shl( pSpectrum[iStartLine + i], shift ) );
239 232694 : move16();
240 : }
241 :
242 11160 : FOR( lag = 0; lag <= pTnsConfig->maxOrder; lag++ )
243 : {
244 10044 : n = sub( sub( iEndLine, lag ), iStartLine );
245 :
246 10044 : L_tmp = L_deposit_l( 0 );
247 2064114 : FOR( i = 0; i < n; i++ )
248 : {
249 2054070 : L_tmp = L_mac0_sat( L_tmp, tmpbuf[i], tmpbuf[i + lag] );
250 : }
251 :
252 10044 : IF( lag != 0 )
253 8928 : L_tmp = Mpy_32_16_1( L_tmp, *pWindow++ );
254 :
255 10044 : L_tmp = Mpy_32_16_1( L_tmp, facs[iFilter][iSubdivisions] );
256 10044 : L_tmp = L_shl( L_tmp, facs_e[iFilter][iSubdivisions] );
257 :
258 10044 : rxx[lag] = L_add( rxx[lag], L_tmp );
259 10044 : move32();
260 : }
261 : }
262 :
263 372 : IF( EQ_16( iSubdivisions, nSubdivisions ) ) /* meaning there is no subdivision with low energy */
264 : {
265 372 : pFilter->spectrumLength = spectrumLength;
266 372 : move16();
267 : /* Limit the maximum order to spectrum length/4 */
268 372 : GetFilterParameters( rxx, s_min( pTnsConfig->maxOrder, shr( pFilter->spectrumLength, 2 ) ), pFilter );
269 : }
270 : }
271 :
272 372 : if ( predictionGain )
273 : {
274 372 : assert( pTnsConfig->nMaxFilters == 1 );
275 372 : move16();
276 372 : *predictionGain = pTnsData->filter->predictionGain;
277 : }
278 :
279 : /* We check the filter's decisions in the opposite direction */
280 744 : FOR( iFilter = sub( pTnsConfig->nMaxFilters, 1 ); iFilter >= 0; iFilter-- )
281 : {
282 : STnsFilter *pFilter;
283 : struct TnsParameters const *pTnsParameters;
284 :
285 372 : move16();
286 372 : move16();
287 372 : pFilter = pTnsData->filter + iFilter;
288 372 : pTnsParameters = pTnsConfig->pTnsParameters + iFilter;
289 :
290 372 : IF( s_or( (Word16) GT_16( pFilter->predictionGain, pTnsParameters->minPredictionGain ),
291 : sub( pFilter->avgSqrCoef, pTnsParameters->minAvgSqrCoef ) > 0 ) )
292 : {
293 4 : move16();
294 4 : pTnsData->nFilters = add( pTnsData->nFilters, 1 );
295 : }
296 368 : ELSE IF( pTnsData->nFilters > 0 ) /* If a previous filter is turned on */
297 : {
298 : /* Since TNS filter of order 0 is not allowed we haved to signal in the stream filter of order 1 with the 0th coefficient equal to 0 */
299 0 : ClearTnsFilterCoefficients( pFilter );
300 0 : move16();
301 0 : move16();
302 0 : pFilter->order = 1;
303 0 : pTnsData->nFilters = add( pTnsData->nFilters, 1 );
304 : }
305 : ELSE
306 : {
307 368 : ClearTnsFilterCoefficients( pFilter );
308 : }
309 : }
310 :
311 :
312 372 : return ( pTnsData->nFilters > 0 );
313 : }
314 :
315 1297542 : void CalculateTnsFilt_fx(
316 : STnsConfig const *pTnsConfig, /* i : TNS Configuration struct */
317 : const Word32 pSpectrum[], /* i : MDCT spectrum */
318 : const Word16 pSpectrum_e,
319 : STnsData *pTnsData /* o : TNS data struct */
320 : )
321 : {
322 : Word32 norms[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS];
323 : Word16 norms_exp[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS];
324 : Word16 i, iFilter, idx0, idx1, nSubdivisions, iSubdivisions, spectrumLength;
325 : Word16 iStartLine, iEndLine, lag;
326 : Word16 fac, fac_e, exp;
327 : Word32 rxx[TNS_MAX_FILTER_ORDER + 1];
328 : Word64 W_tmp;
329 : const Word16 *pWindow;
330 : STnsFilter *pFilter;
331 :
332 3892626 : FOR( i = 0; i < TNS_MAX_NUM_OF_FILTERS; i++ )
333 : {
334 2595084 : set32_fx( norms[i], 0, MAX_SUBDIVISIONS );
335 : }
336 :
337 : /* Calculate norms for each spectrum part */
338 3771649 : FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
339 : {
340 2474107 : idx0 = pTnsConfig->iFilterBorders[iFilter + 1];
341 2474107 : move16();
342 2474107 : idx1 = pTnsConfig->iFilterBorders[iFilter];
343 2474107 : move16();
344 2474107 : nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
345 2474107 : move16();
346 :
347 : /* Variable initialization */
348 2474107 : assert( pTnsConfig->pTnsParameters[iFilter].nSubdivisions <= MAX_SUBDIVISIONS );
349 9896428 : FOR( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ )
350 : {
351 7422321 : iStartLine = add( idx0, idiv1616U( i_mult( sub( idx1, idx0 ), iSubdivisions ), nSubdivisions ) );
352 7422321 : iEndLine = add( idx0, idiv1616U( i_mult( sub( idx1, idx0 ), add( iSubdivisions, 1 ) ), nSubdivisions ) );
353 :
354 : /* Variable initialization */
355 7422321 : norms_exp[iFilter][iSubdivisions] = pSpectrum_e;
356 7422321 : move16();
357 7422321 : norms[iFilter][iSubdivisions] = sum2_32_exp_fx( pSpectrum + iStartLine, sub( iEndLine, iStartLine ), &norms_exp[iFilter][iSubdivisions], 8 ); // norms_exp[iFilter][iSubdivisions]
358 7422321 : move32();
359 : }
360 : }
361 :
362 : /* Calculate normalized autocorrelation for spectrum subdivision and get TNS filter parameters based on it */
363 3771649 : FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
364 : {
365 2474107 : idx0 = pTnsConfig->iFilterBorders[iFilter + 1];
366 2474107 : move16();
367 2474107 : idx1 = pTnsConfig->iFilterBorders[iFilter];
368 2474107 : move16();
369 2474107 : spectrumLength = sub( idx1, idx0 );
370 2474107 : pFilter = pTnsData->filter + iFilter;
371 2474107 : nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
372 2474107 : move16();
373 :
374 2474107 : set32_fx( rxx, 0, TNS_MAX_FILTER_ORDER + 1 ); /* WMOPS: This initialization is required */
375 :
376 : /* Variable initialization */
377 2474107 : test();
378 9539460 : FOR( iSubdivisions = 0; ( iSubdivisions < nSubdivisions ) && ( L_shr_sat( norms[iFilter][iSubdivisions], sub( 6, norms_exp[iFilter][iSubdivisions] ) ) > HLM_MIN_NRG_FX ); iSubdivisions++ )
379 : {
380 7065353 : test();
381 7065353 : fac = BASOP_Util_Divide3232_Scale( 1, norms[iFilter][iSubdivisions], &fac_e );
382 7065353 : fac_e = add( sub( Q31, norms_exp[iFilter][iSubdivisions] ), fac_e );
383 7065353 : iStartLine = add( idx0, idiv1616U( i_mult( spectrumLength, iSubdivisions ), nSubdivisions ) );
384 7065353 : iEndLine = add( idx0, idiv1616U( i_mult( spectrumLength, add( iSubdivisions, 1 ) ), nSubdivisions ) );
385 7065353 : pWindow = tnsAcfWindow_fx; // Q15
386 :
387 : /* For additional loop condition */
388 : /* Variable initialization */
389 63588177 : FOR( lag = 1; lag <= pTnsConfig->maxOrder; lag++ )
390 : {
391 56522824 : W_tmp = 0;
392 56522824 : move64();
393 6810898796 : FOR( i = 0; i < iEndLine - iStartLine - lag; i++ )
394 : {
395 6754375972 : W_tmp = W_mac_32_32( W_tmp, pSpectrum[iStartLine + i], pSpectrum[iStartLine + lag + i] );
396 : }
397 56522824 : exp = W_norm( W_tmp );
398 56522824 : W_tmp = W_shl( W_tmp, exp );
399 56522824 : exp = sub( shl( pSpectrum_e, 1 ), exp );
400 56522824 : W_tmp = W_mult_32_32( L_mult( fac, ( *pWindow ) ), W_extract_h( W_tmp ) ); // exp + fac_e
401 56522824 : rxx[lag] = L_add( rxx[lag], W_extract_h( W_shl( W_tmp, sub( add( fac_e, exp ), 2 ) ) ) ); // Q29
402 56522824 : move32();
403 56522824 : pWindow++;
404 : }
405 : }
406 :
407 2474107 : IF( EQ_16( iSubdivisions, nSubdivisions ) ) /* meaning there is no subdivision with low energy */
408 : {
409 : // To be checked
410 2326203 : rxx[0] = L_shl( pTnsConfig->pTnsParameters[iFilter].nSubdivisions, Q29 ); // Q29
411 2326203 : move32();
412 2326203 : pFilter->spectrumLength = spectrumLength;
413 2326203 : move16();
414 : /* Limit the maximum order to spectrum length/4 */
415 2326203 : GetFilterParameters_ivas( rxx, s_min( pTnsConfig->maxOrder, shr( pFilter->spectrumLength, 2 ) ), pFilter );
416 : }
417 : }
418 :
419 1297542 : return;
420 : }
421 :
422 161621 : Word16 DetectTnsFilt_ivas_fx( STnsConfig const *pTnsConfig, /* i : TNS Configuration struct */
423 : Word32 const pSpectrum[], /* i : MDCT spectrum Q=Qx */
424 : STnsData *pTnsData, /* o : TNS data struct */
425 : TRAN_DET_HANDLE hTranDet, /* i : transient detection handle */
426 : Word8 isTCX10, /* i : TCX10 or TCX20? */
427 : Word16 ltp_gain, /* i : LTP gain Q=15 */
428 : Word16 *predictionGain /* o : TNS prediction gain Q=7 */
429 : )
430 : {
431 : Word16 facs[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS];
432 : Word16 facs_e[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS]; /* exponents of facs[][] */
433 : Word16 shifts[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS];
434 161621 : Word16 iFilter = 0;
435 161621 : move16();
436 161621 : ResetTnsData( pTnsData );
437 :
438 161621 : IF( pTnsConfig->maxOrder <= 0 )
439 : {
440 0 : return 0;
441 : }
442 :
443 : /* Calculate norms for each spectrum part */
444 439084 : FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
445 : {
446 : Word16 idx0;
447 : Word16 idx1;
448 : Word16 nSubdivisions;
449 : Word16 iSubdivisions;
450 : #ifndef ISSUE_1867_replace_overflow_libenc
451 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
452 : Flag Overflow = 0;
453 : move32();
454 : #endif
455 : #endif
456 :
457 277463 : move16();
458 277463 : move16();
459 277463 : move16();
460 277463 : idx0 = pTnsConfig->iFilterBorders[iFilter + 1];
461 277463 : idx1 = pTnsConfig->iFilterBorders[iFilter];
462 277463 : nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
463 :
464 277463 : assert( pTnsConfig->pTnsParameters[iFilter].nSubdivisions <= MAX_SUBDIVISIONS );
465 :
466 886404 : FOR( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ )
467 : {
468 : Word16 iStartLine;
469 : Word16 iEndLine;
470 : Word16 tmp, headroom, shift;
471 : Word32 L_tmp, tmp32;
472 :
473 : /* iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions;
474 : iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; */
475 608941 : assert( ( nSubdivisions == 1 ) || ( nSubdivisions == 3 ) );
476 :
477 608941 : tmp = sub( idx1, idx0 );
478 608941 : iStartLine = imult1616( tmp, iSubdivisions );
479 608941 : iEndLine = add( iStartLine, tmp );
480 :
481 608941 : IF( EQ_16( nSubdivisions, 3 ) )
482 : {
483 497217 : iStartLine = mult( iStartLine, 0x2AAB );
484 : }
485 608941 : iStartLine = add( iStartLine, idx0 );
486 :
487 608941 : IF( EQ_16( nSubdivisions, 3 ) )
488 : {
489 497217 : iEndLine = mult( iEndLine, 0x2AAB );
490 : }
491 608941 : iEndLine = add( iEndLine, idx0 );
492 :
493 : /*norms[iFilter][iSubdivisions] = norm2FLOAT(pSpectrum+iStartLine, iEndLine-iStartLine);*/
494 608941 : headroom = getScaleFactor32( &pSpectrum[iStartLine], sub( iEndLine, iStartLine ) );
495 :
496 : /* Calculate norm of spectrum band */
497 608941 : L_tmp = Norm32Norm( pSpectrum + iStartLine, headroom, sub( iEndLine, iStartLine ), &shift );
498 :
499 : /* Check threshold HLM_MIN_NRG */
500 : BASOP_SATURATE_WARNING_OFF_EVS;
501 : #ifdef ISSUE_1867_replace_overflow_libenc
502 608941 : tmp32 = L_sub( L_shl_sat( L_tmp, s_min( 31, sub( shift, 24 - 31 * 2 ) ) ), 3277l /*HLM_MIN_NRG Q7*/ );
503 : #else
504 : tmp32 = L_sub( L_shl_o( L_tmp, s_min( 31, sub( shift, 24 - 31 * 2 ) ), &Overflow ), 3277l /*HLM_MIN_NRG Q7*/ );
505 : #endif
506 : BASOP_SATURATE_WARNING_ON_EVS;
507 :
508 : /* get pre-shift for autocorrelation */
509 608941 : tmp = sub( shift, norm_l( L_tmp ) ); /* exponent for normalized L_tmp */
510 608941 : tmp = shr( sub( 1, tmp ), 1 ); /* pre-shift to apply before autocorrelation */
511 608941 : shifts[iFilter][iSubdivisions] = s_min( tmp, headroom );
512 608941 : move16();
513 :
514 : /* calc normalization factor */
515 608941 : facs[iFilter][iSubdivisions] = 0;
516 608941 : move16();
517 608941 : facs_e[iFilter][iSubdivisions] = 0;
518 608941 : move16();
519 :
520 608941 : if ( tmp32 > 0 )
521 : {
522 608908 : facs[iFilter][iSubdivisions] = 0x7FFF;
523 608908 : move16(); /* normalization not needed for one subdivision */
524 : }
525 :
526 608941 : test();
527 608941 : IF( ( tmp32 > 0 ) && ( GT_16( nSubdivisions, 1 ) ) )
528 : {
529 497184 : move16();
530 497184 : facs_e[iFilter][iSubdivisions] = shl( sub( tmp, shifts[iFilter][iSubdivisions] ), 1 );
531 :
532 497184 : tmp = sub( 1, shl( tmp, 1 ) ); /* exponent of autocorrelation */
533 497184 : L_tmp = L_shl_sat( L_tmp, sub( shift, tmp ) ); /* shift L_tmp to that exponent */
534 :
535 : /* calc factor (with 2 bits headroom for sum of 3 subdivisions) */
536 497184 : move16();
537 497184 : facs[iFilter][iSubdivisions] = div_s( 0x2000, round_fx_sat( L_tmp ) ); /* L_tmp is >= 0x2000000 */
538 : }
539 : }
540 : }
541 : /* Calculate normalized autocorrelation for spectrum subdivision and get TNS filter parameters based on it */
542 439084 : FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
543 : {
544 : #define RXX_E ( 3 )
545 : Word32 rxx[TNS_MAX_FILTER_ORDER + 1];
546 : Word16 idx0;
547 : Word16 idx1;
548 : Word16 spectrumLength;
549 : STnsFilter *pFilter;
550 : Word16 nSubdivisions;
551 : Word16 iSubdivisions;
552 : Word16 tmpbuf[325];
553 :
554 277463 : set32_fx( rxx, 0, TNS_MAX_FILTER_ORDER + 1 );
555 :
556 277463 : move16();
557 277463 : move16();
558 277463 : move16();
559 277463 : idx0 = pTnsConfig->iFilterBorders[iFilter + 1];
560 277463 : idx1 = pTnsConfig->iFilterBorders[iFilter];
561 277463 : spectrumLength = sub( idx1, idx0 );
562 277463 : pFilter = pTnsData->filter + iFilter;
563 277463 : nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
564 :
565 886371 : FOR( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ )
566 : {
567 : Word16 iStartLine, n, i;
568 : Word16 iEndLine;
569 : const Word16 *pWindow;
570 : Word16 lag, shift;
571 : Word32 L_tmp;
572 :
573 608919 : IF( facs[iFilter][iSubdivisions] == 0 )
574 : {
575 11 : BREAK;
576 : }
577 :
578 :
579 : /* iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions;
580 : iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; */
581 608908 : assert( ( nSubdivisions == 1 ) || ( nSubdivisions == 3 ) );
582 :
583 608908 : iStartLine = imult1616( spectrumLength, iSubdivisions );
584 608908 : iEndLine = add( iStartLine, spectrumLength );
585 :
586 608908 : IF( EQ_16( nSubdivisions, 3 ) )
587 : {
588 497184 : iStartLine = mult( iStartLine, 0x2AAB );
589 : }
590 608908 : iStartLine = add( iStartLine, idx0 );
591 :
592 608908 : IF( EQ_16( nSubdivisions, 3 ) )
593 : {
594 497184 : iEndLine = mult( iEndLine, 0x2AAB );
595 : }
596 608908 : iEndLine = add( iEndLine, idx0 );
597 :
598 :
599 608908 : move16();
600 608908 : shift = shifts[iFilter][iSubdivisions];
601 :
602 608908 : move16();
603 608908 : pWindow = tnsAcfWindow_fx;
604 :
605 608908 : n = sub( iEndLine, iStartLine );
606 608908 : assert( n <= (Word16) ( sizeof( tmpbuf ) / sizeof( Word16 ) ) );
607 121783112 : FOR( i = 0; i < n; i++ )
608 : {
609 121174204 : tmpbuf[i] = round_fx_sat( L_shl( pSpectrum[iStartLine + i], shift ) ); // using round_fx_sat to address corner case
610 121174204 : move16();
611 : }
612 :
613 6089080 : FOR( lag = 0; lag <= pTnsConfig->maxOrder; lag++ )
614 : {
615 5480172 : n = sub( sub( iEndLine, lag ), iStartLine );
616 :
617 5480172 : L_tmp = L_deposit_l( 0 );
618 1074127320 : FOR( i = 0; i < n; i++ )
619 : {
620 1068647148 : L_tmp = L_mac0_sat( L_tmp, tmpbuf[i], tmpbuf[i + lag] );
621 : }
622 :
623 5480172 : IF( lag != 0 )
624 : {
625 4871264 : L_tmp = Mpy_32_16_1( L_tmp, *pWindow++ );
626 : }
627 :
628 5480172 : L_tmp = Mpy_32_16_1( L_tmp, facs[iFilter][iSubdivisions] );
629 5480172 : L_tmp = L_shl( L_tmp, facs_e[iFilter][iSubdivisions] );
630 :
631 5480172 : rxx[lag] = L_add( rxx[lag], L_tmp );
632 5480172 : move32();
633 : }
634 : }
635 :
636 277463 : IF( EQ_16( iSubdivisions, nSubdivisions ) ) /* meaning there is no subdivision with low energy */
637 : {
638 277452 : pFilter->spectrumLength = spectrumLength;
639 277452 : move16();
640 : /* Limit the maximum order to spectrum length/4 */
641 277452 : GetFilterParameters( rxx, s_min( pTnsConfig->maxOrder, shr( pFilter->spectrumLength, 2 ) ), pFilter );
642 : }
643 : }
644 :
645 161621 : IF( predictionGain )
646 : {
647 0 : assert( pTnsConfig->nMaxFilters == 1 );
648 0 : move16();
649 0 : *predictionGain = pTnsData->filter->predictionGain;
650 : }
651 :
652 : /* We check the filter's decisions in the opposite direction */
653 439084 : FOR( iFilter = ( pTnsConfig->nMaxFilters - 1 ); iFilter >= 0; iFilter-- )
654 : {
655 : STnsFilter *pFilter;
656 : struct TnsParameters const *pTnsParameters;
657 : Word16 maxEnergyChange;
658 277463 : move16();
659 277463 : move16();
660 277463 : pFilter = pTnsData->filter + iFilter;
661 277463 : pTnsParameters = pTnsConfig->pTnsParameters + iFilter;
662 :
663 277463 : IF( s_or( (Word16) GT_16( pFilter->predictionGain, pTnsParameters->minPredictionGain ),
664 : sub( pFilter->avgSqrCoef, pTnsParameters->minAvgSqrCoef ) > 0 ) )
665 : {
666 : // pTnsData->nFilters > 0 || isTCX10 || ltp_gain < 0.6f || hTranDet == NULL
667 : // .6f = 19660, Q=15
668 20521 : test();
669 20521 : test();
670 20521 : test();
671 20521 : IF( pTnsData->nFilters > 0 || isTCX10 || LT_16( ltp_gain, 19660 ) || hTranDet == NULL )
672 : {
673 20521 : pTnsData->nFilters = add( pTnsData->nFilters, 1 );
674 20521 : move16();
675 : }
676 : ELSE
677 : {
678 0 : maxEnergyChange = GetTCXMaxenergyChange_ivas_fx( hTranDet, isTCX10, NSUBBLOCKS, 3 );
679 0 : IF( sub( maxEnergyChange, shl( pTnsParameters->minEnergyChange, Q3 - Q7 ) ) >= 0 )
680 : {
681 :
682 0 : pTnsData->nFilters = add( pTnsData->nFilters, 1 );
683 0 : move16();
684 : }
685 : ELSE
686 : {
687 0 : ClearTnsFilterCoefficients( pFilter );
688 : }
689 : }
690 : }
691 256942 : ELSE IF( pTnsData->nFilters > 0 ) /* If a previous filter is turned on */
692 : {
693 : /* Since TNS filter of order 0 is not allowed we haved to signal in the stream filter of order 1 with the 0th coefficient equal to 0 */
694 4828 : ClearTnsFilterCoefficients( pFilter );
695 4828 : move16();
696 4828 : move16();
697 4828 : pFilter->order = 1;
698 4828 : pTnsData->nFilters = add( pTnsData->nFilters, 1 );
699 : }
700 : ELSE
701 : {
702 252114 : ClearTnsFilterCoefficients( pFilter );
703 : }
704 : }
705 :
706 161621 : return ( pTnsData->nFilters > 0 );
707 : }
708 :
709 161993 : Word16 EncodeTnsData_fx( STnsConfig const *pTnsConfig, STnsData const *pTnsData, Word16 *stream, Word16 *pnSize, Word16 *pnBits )
710 : {
711 :
712 161993 : move16();
713 161993 : move16();
714 161993 : *pnSize = 0;
715 161993 : *pnBits = 0;
716 :
717 161993 : IF( GT_16( pTnsConfig->nMaxFilters, 1 ) )
718 : {
719 :
720 115842 : IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) )
721 : {
722 4118 : GetParameters( &tnsEnabledSWBTCX10BitMap, 1, pTnsData, &stream, pnSize, pnBits );
723 : }
724 : ELSE
725 : {
726 111724 : GetParameters( &tnsEnabledSWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits );
727 : }
728 : }
729 : ELSE
730 : {
731 46151 : GetParameters( &tnsEnabledWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits );
732 : }
733 :
734 161993 : return TNS_NO_ERROR;
735 : }
736 :
737 1297542 : void EncodeTnsData_ivas_fx(
738 : STnsConfig const *pTnsConfig, /* i : TNS Configuration struct */
739 : STnsData const *pTnsData, /* i : TNS data struct (quantized param) */
740 : Word16 *stream, /* o : internal data stream Q0*/
741 : Word16 *pnSize, /* o : number of written parameters Q0*/
742 : Word16 *pnBits /* o : number of written bits Q0*/
743 : )
744 : {
745 1297542 : *pnSize = 0;
746 1297542 : move16();
747 1297542 : move16();
748 1297542 : *pnBits = 0;
749 :
750 1297542 : IF( GT_16( pTnsConfig->nMaxFilters, 1 ) )
751 : {
752 1176565 : IF( pTnsConfig->allowTnsOnWhite )
753 : {
754 1176565 : IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) )
755 : {
756 42973 : GetParameters_fx( &tnsEnabledOnWhiteSWBTCX10BitMap, 1, pTnsData, &stream, pnSize, pnBits );
757 : }
758 : ELSE
759 : {
760 1133592 : GetParameters_fx( &tnsEnabledOnWhiteSWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits );
761 : }
762 : }
763 : ELSE
764 : {
765 0 : IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) )
766 : {
767 0 : GetParameters_fx( &tnsEnabledSWBTCX10BitMap, 1, pTnsData, &stream, pnSize, pnBits );
768 : }
769 : ELSE
770 : {
771 0 : GetParameters_fx( &tnsEnabledSWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits );
772 : }
773 : }
774 : }
775 : ELSE
776 : {
777 120977 : GetParameters_fx( &tnsEnabledWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits );
778 : }
779 :
780 1297542 : return;
781 : }
782 :
783 372 : Word16 WriteTnsData_fx( STnsConfig const *pTnsConfig, Word16 const *stream, Word16 *pnSize, Encoder_State *st, Word16 *pnBits )
784 : {
785 :
786 372 : IF( GT_16( pTnsConfig->nMaxFilters, 1 ) )
787 : {
788 :
789 0 : IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) )
790 : {
791 0 : WriteToBitstream_fx( &tnsEnabledSWBTCX10BitMap, 1, &stream, pnSize, st->hBstr, pnBits );
792 : }
793 : ELSE
794 : {
795 0 : WriteToBitstream_fx( &tnsEnabledSWBTCX20BitMap, 1, &stream, pnSize, st->hBstr, pnBits );
796 : }
797 : }
798 : ELSE
799 : {
800 372 : WriteToBitstream_fx( &tnsEnabledWBTCX20BitMap, 1, &stream, pnSize, st->hBstr, pnBits );
801 : }
802 :
803 :
804 372 : return TNS_NO_ERROR;
805 : }
806 814662 : Word16 WriteTnsData_ivas_fx( STnsConfig const *pTnsConfig, Word16 const *stream, Word16 *pnSize, BSTR_ENC_HANDLE hBstr, Word16 *pnBits )
807 : {
808 814662 : IF( GT_16( pTnsConfig->nMaxFilters, 1 ) )
809 : {
810 708631 : IF( pTnsConfig->allowTnsOnWhite )
811 : {
812 592789 : IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) )
813 : {
814 29092 : WriteToBitstream_ivas_fx( &tnsEnabledOnWhiteSWBTCX10BitMap, 1, &stream, pnSize, hBstr, pnBits );
815 : }
816 : ELSE
817 : {
818 563697 : WriteToBitstream_ivas_fx( &tnsEnabledOnWhiteSWBTCX20BitMap, 1, &stream, pnSize, hBstr, pnBits );
819 : }
820 : }
821 : ELSE
822 : {
823 115842 : IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) )
824 : {
825 4118 : WriteToBitstream_ivas_fx( &tnsEnabledSWBTCX10BitMap, 1, &stream, pnSize, hBstr, pnBits );
826 : }
827 : ELSE
828 : {
829 111724 : WriteToBitstream_ivas_fx( &tnsEnabledSWBTCX20BitMap, 1, &stream, pnSize, hBstr, pnBits );
830 : }
831 : }
832 : }
833 : ELSE
834 : {
835 106031 : WriteToBitstream_ivas_fx( &tnsEnabledWBTCX20BitMap, 1, &stream, pnSize, hBstr, pnBits );
836 : }
837 :
838 814662 : return TNS_NO_ERROR;
839 : }
840 : /*********************************************************************************************/
841 : /* Definitions of functions used in the mapping between TNS parameters and a bitstream. */
842 : /*********************************************************************************************/
843 :
844 : /* Helper functions for Hufmann table coding */
845 :
846 : /********************************/
847 : /* Private functions */
848 : /********************************/
849 2326203 : static void GetFilterParameters_ivas( Word32 rxx[], Word16 maxOrder, STnsFilter *pTnsFilter )
850 : {
851 : Word16 i;
852 : Word16 parCoeff[TNS_MAX_FILTER_ORDER + 1];
853 : Word32 rxx_0;
854 : Word32 L_tmp;
855 : #if TNS_COEF_RES == 5
856 : Word16 const *values = tnsCoeff5;
857 : #elif TNS_COEF_RES == 4
858 2326203 : Word16 const *values = tnsCoeff4;
859 : #elif TNS_COEF_RES == 3
860 : Word16 const *values = tnsCoeff3;
861 : #endif
862 2326203 : Word16 *indexes = pTnsFilter->coefIndex;
863 :
864 2326203 : rxx_0 = rxx[0];
865 2326203 : move32();
866 : /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */
867 2326203 : L_tmp = E_LPC_schur_ivas( rxx, parCoeff, maxOrder );
868 : BASOP_SATURATE_WARNING_OFF_EVS /* Allow saturation, this value is compared against a threshold. */
869 2326203 : Word16 temp_e = 0;
870 2326203 : move16();
871 2326203 : Word16 temp = BASOP_Util_Divide3232_Scale( rxx_0, L_tmp, &temp_e );
872 2326203 : pTnsFilter->predictionGain32 = L_deposit_h( temp );
873 2326203 : move32();
874 2326203 : pTnsFilter->predictionGain_e = temp_e;
875 2326203 : move16();
876 2326203 : pTnsFilter->predictionGain = shl_sat( temp, sub( temp_e, PRED_GAIN_E ) ); // Q7
877 2326203 : move16();
878 : BASOP_SATURATE_WARNING_ON_EVS
879 : /* non-linear quantization of TNS lattice coefficients with given resolution */
880 2326203 : Parcor2Index( parCoeff, indexes, maxOrder );
881 :
882 : /* reduce filter order by truncating trailing zeros */
883 2326203 : i = sub( maxOrder, 1 );
884 :
885 2326203 : test();
886 12988778 : WHILE( ( i >= 0 ) && ( indexes[i] == 0 ) )
887 : {
888 10662575 : i = sub( i, 1 );
889 : }
890 :
891 :
892 2326203 : pTnsFilter->order = add( i, 1 );
893 2326203 : move16();
894 :
895 : /* compute avg(coef*coef) */
896 2326203 : L_tmp = L_deposit_l( 0 );
897 :
898 10273252 : FOR( i = pTnsFilter->order - 1; i >= 0; i-- )
899 : {
900 : Word16 value;
901 :
902 7947049 : value = shr( values[indexes[i] + INDEX_SHIFT], 1 );
903 :
904 7947049 : L_tmp = L_mac0( L_tmp, value, value );
905 : }
906 :
907 2326203 : pTnsFilter->avgSqrCoef = round_fx( L_tmp );
908 2326203 : move16();
909 : /* assert(maxOrder == 8);
910 : pTnsFilter->avgSqrCoef = shr(pTnsFilter->avgSqrCoef, 3); */
911 2326203 : }
912 277824 : static void GetFilterParameters( Word32 rxx[], Word16 maxOrder, STnsFilter *pTnsFilter )
913 : {
914 : Word16 i;
915 : Word16 parCoeff[TNS_MAX_FILTER_ORDER];
916 : Word32 epsP[TNS_MAX_FILTER_ORDER + 1], L_tmp;
917 : #if TNS_COEF_RES == 5
918 : Word16 const *values = tnsCoeff5;
919 : #elif TNS_COEF_RES == 4
920 277824 : Word16 const *values = tnsCoeff4;
921 : #elif TNS_COEF_RES == 3
922 : Word16 const *values = tnsCoeff3;
923 : #endif
924 277824 : Word16 *indexes = pTnsFilter->coefIndex;
925 :
926 :
927 : /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */
928 277824 : L_tmp = E_LPC_schur( rxx, parCoeff, epsP, maxOrder );
929 : BASOP_SATURATE_WARNING_OFF_EVS /* Allow saturation, this value is compared against a threshold. */
930 277824 : pTnsFilter->predictionGain = divide3232( L_shr( epsP[0], PRED_GAIN_E ), L_tmp );
931 : BASOP_SATURATE_WARNING_ON_EVS
932 : /* non-linear quantization of TNS lattice coefficients with given resolution */
933 277824 : Parcor2Index( parCoeff, indexes, maxOrder );
934 :
935 : /* reduce filter order by truncating trailing zeros */
936 277824 : i = sub( maxOrder, 1 );
937 :
938 277824 : test();
939 1490290 : WHILE( ( i >= 0 ) && ( indexes[i] == 0 ) )
940 : {
941 1212466 : test();
942 1212466 : i = sub( i, 1 );
943 : }
944 :
945 277824 : move16();
946 277824 : pTnsFilter->order = add( i, 1 );
947 :
948 : /* compute avg(coef*coef) */
949 277824 : L_tmp = L_deposit_l( 0 );
950 :
951 1287950 : FOR( i = pTnsFilter->order - 1; i >= 0; i-- )
952 : {
953 : Word16 value;
954 :
955 1010126 : value = shr( values[indexes[i] + INDEX_SHIFT], 1 );
956 :
957 1010126 : L_tmp = L_mac0( L_tmp, value, value );
958 : }
959 277824 : move16();
960 277824 : pTnsFilter->avgSqrCoef = round_fx( L_tmp );
961 :
962 : /* assert(maxOrder == 8);
963 : pTnsFilter->avgSqrCoef = shr(pTnsFilter->avgSqrCoef, 3); */
964 277824 : }
965 :
966 2604027 : static void Parcor2Index( const Word16 parCoeff[] /*Q15*/, Word16 index[], Word16 order )
967 : {
968 : Word16 nValues;
969 : Word16 const *values;
970 : Word16 i;
971 : Word16 iIndex;
972 : Word16 x;
973 :
974 :
975 2604027 : move16();
976 2604027 : nValues = 1 << TNS_COEF_RES;
977 : #if TNS_COEF_RES == 5
978 : values = tnsCoeff5;
979 : #elif TNS_COEF_RES == 4
980 2604027 : values = tnsCoeff4;
981 : #elif TNS_COEF_RES == 3
982 : values = tnsCoeff3;
983 : #endif
984 :
985 23436243 : FOR( i = 0; i < order; i++ )
986 : {
987 20832216 : move16();
988 20832216 : move16();
989 20832216 : iIndex = 1;
990 20832216 : x = parCoeff[i];
991 :
992 : /* parCoeff is in the range of -1.0 ... 1.0 by definition */
993 : /* assert((x >= FL2WORD16(-1.0f)) && (x <= FL2WORD16(1.0f))); */
994 :
995 20832216 : test();
996 188137347 : WHILE( ( iIndex < nValues ) && ( x > add( shr( values[iIndex - 1], 1 ), shr( values[iIndex], 1 ) ) ) )
997 : {
998 167305131 : test();
999 167305131 : iIndex = add( iIndex, 1 );
1000 : }
1001 20832216 : index[i] = sub( iIndex, 1 + INDEX_SHIFT );
1002 20832216 : move16();
1003 : }
1004 2604027 : }
|