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