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