Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #include <assert.h>
6 : #include <stdint.h>
7 : #include "options.h"
8 : #include "cnst.h"
9 : #include "rom_com.h"
10 : #include "rom_enc.h"
11 : #include "basop_util.h"
12 : #include "prot_fx.h" /* Function prototypes */
13 : #include "prot_fx_enc.h" /* Function prototypes */
14 :
15 :
16 : /*
17 : * E_GAIN_norm_corr
18 : *
19 : * Parameters:
20 : * exc I: excitation buffer (Q_new)
21 : * xn I: target signal (Q_new+shift-1)
22 : * h I: weighted synthesis filter impulse response (Q14+shift)
23 : * t0_min I: minimum value in the searched range
24 : * t0_max I: maximum value in the searched range
25 : * corr_norm O: normalized correlation (Q15+(Q_new+shift-1)+scale)
26 : *
27 : * Function:
28 : * Find the normalized correlation between the target vector and the
29 : * filtered past excitation (correlation between target and filtered
30 : * excitation divided by the square root of energy of filtered excitation)
31 : * Size of subframe = L_SUBFR.
32 : *
33 : * Returns:
34 : * void
35 : */
36 :
37 6120 : static void E_GAIN_norm_corr_fx(
38 : Word16 exc[] /*Q_new*/,
39 : Word16 xn[] /*(Q_new+shift-1)*/,
40 : Word16 h[] /*(Q14+shift)*/,
41 : Word16 t_min,
42 : Word16 t_max,
43 : Word16 corr_norm[] /*(Q15+(Q_new+shift-1)+scale)*/,
44 : Word16 L_subfr )
45 : {
46 : Word16 excf[L_SUBFR]; /* filtered past excitation (Q_new+shift-1) */
47 : Word16 ps, norm, exp_alp, exp_ps, scale, L_subfr2;
48 : Word16 t, j, k;
49 : Word32 L_tmp, L_tmp2;
50 :
51 6120 : k = negate( t_min );
52 6120 : L_subfr2 = shr( L_subfr, 1 );
53 :
54 : /* compute the filtered excitation for the first delay t_min */
55 6120 : E_UTIL_f_convolve( &exc[k], h, excf, L_subfr );
56 :
57 : /* Compute rounded down 1/sqrt(energy of xn[]) */
58 6120 : Dot_product12_offs( xn, xn, L_subfr, &scale, 1 );
59 :
60 6120 : scale = add( scale, 2 + 1 ); /* energy of xn[] x 2 + rounded up */
61 6120 : move16();
62 6120 : scale = negate( shr( scale, 1 ) ); /* (1<<scale) < 1/sqrt(energy rounded) */
63 :
64 : /* loop for every possible period */
65 165914 : FOR( t = t_min; t < t_max; t++ )
66 : {
67 : /* Compute correlation between xn[] and excf[] */
68 :
69 : /*for (j = 0; j < L_subfr; j++)
70 : {
71 : ps += xn[j] * excf[j]; MAC(1);
72 : alp += excf[j] * excf[j]; MAC(1);
73 : }*/
74 159794 : L_tmp = Dot_product12_offs( xn, excf, L_subfr, &exp_ps, 1 ); /*Q31 + 2x(Q_new+shift-1) - exp_ps*/
75 159794 : ps = extract_h( L_tmp ); /* Scaling of ps = 15 + 2x(Q_new+shift-1) - exp_ps */
76 :
77 :
78 : /* Compute 1/sqrt(energy of excf[]) */
79 159794 : L_tmp = Dot_product12_offs( excf, excf, L_subfr2, NULL, 1 );
80 159794 : L_tmp2 = Dot_product12_offs( excf + L_subfr2, excf + L_subfr2, L_subfr2, NULL, 1 );
81 159794 : exp_alp = sub( s_min( norm_l( L_tmp ), norm_l( L_tmp2 ) ), 1 );
82 159794 : L_tmp = L_add( L_shl( L_tmp, exp_alp ), L_shl( L_tmp2, exp_alp ) );
83 159794 : exp_alp = sub( 31 + 1, exp_alp );
84 :
85 : /*norm = (Float32)(1.0F / sqrt(alp)); SQRT(1);*/
86 159794 : L_tmp = ISqrt32( L_tmp, &exp_alp ); /*Q31 - (Q_new+shift-1) - exp_alp*/
87 159794 : norm = extract_h( L_tmp ); /* Scaling of norm = 15 - (Q_new+shift-1) - exp_alp */
88 :
89 : /* Normalize correlation = correlation * (1/sqrt(energy)) */
90 : /*corr_norm[t-t_min] = ps * norm; MULT(1); STORE(1);*/
91 159794 : L_tmp = L_mult( ps, norm ); /*Q31 + (Q_new+shift-1) - (exp_ps + exp_alp)*/
92 159794 : L_tmp = L_shl( L_tmp, add( add( exp_ps, exp_alp ), scale ) );
93 :
94 159794 : corr_norm[t - t_min] = round_fx( L_tmp ); /* Scaling of corr_norm = 15 + (Q_new+shift-1) + scale */
95 :
96 : /* update the filtered excitation excf[] for the next iteration */
97 159794 : k = sub( k, 1 );
98 :
99 10226816 : FOR( j = L_subfr - 1; j > 0; j-- )
100 : {
101 : /*excf[j] = excf[j - 1] + exc[k] * h[j]; MAC(1); STORE(1);*/
102 : /* saturation can occur in add() */
103 10067022 : excf[j] = add( mult_r( exc[k], h[j] ), excf[j - 1] ); /*Q_new + (Q14+shift) - 15*/
104 10067022 : move16();
105 : }
106 159794 : excf[0] = mult_r( exc[k], h[0] ); /*Q_new + (Q14+shift) - 15*/
107 159794 : move16();
108 : }
109 : /* Last reduced iteration for t=t_max */
110 6120 : L_tmp = Dot_product12_offs( xn, excf, L_subfr, &exp_ps, 1 ); /*Q31 + 2x(Q_new+shift-1) - exp_ps*/
111 6120 : ps = extract_h( L_tmp ); /*Q15 + 2x(Q_new+shift-1) - exp_ps*/
112 :
113 :
114 : /* Compute 1/sqrt(energy of excf[]) */
115 6120 : L_tmp = Dot_product12_offs( excf, excf, L_subfr2, NULL, 1 );
116 6120 : L_tmp2 = Dot_product12_offs( excf + L_subfr2, excf + L_subfr2, L_subfr2, NULL, 1 );
117 6120 : exp_alp = sub( s_min( norm_l( L_tmp ), norm_l( L_tmp2 ) ), 1 );
118 6120 : L_tmp = L_add( L_shl( L_tmp, exp_alp ), L_shl( L_tmp2, exp_alp ) );
119 6120 : exp_alp = sub( 31 + 1, exp_alp );
120 :
121 :
122 : /*norm = (Float32)(1.0F / sqrt(alp)); SQRT(1);*/
123 6120 : L_tmp = ISqrt32( L_tmp, &exp_alp ); /*Q31 - (Q_new+shift-1) - exp_alp*/
124 6120 : norm = extract_h( L_tmp ); /*15 - (Q_new+shift-1) - exp_alp */
125 :
126 : /* Normalize correlation = correlation * (1/sqrt(energy)) */
127 : /*corr_norm[t-t_min] = ps * norm; MULT(1); STORE(1);*/
128 6120 : L_tmp = L_mult( ps, norm ); /*Q31 + (Q_new+shift-1) - (exp_ps + exp_alp)*/
129 6120 : L_tmp = L_shl( L_tmp, add( add( exp_ps, exp_alp ), scale ) );
130 6120 : corr_norm[t - t_min] = round_fx( L_tmp ); /* 15 + (Q_new+shift-1) + scale */
131 :
132 6120 : return;
133 : }
134 :
135 :
136 : /*
137 : * E_GAIN_norm_corr_interpolate
138 : *
139 : * Parameters:
140 : * x I: input vector
141 : * frac I: fraction (-4..+3)
142 : *
143 : * Function:
144 : * Interpolating the normalized correlation
145 : *
146 : * Returns:
147 : * interpolated value
148 : */
149 0 : static Word16 E_GAIN_norm_corr_interpolate_fx( Word16 *x /*Qx*/, Word16 frac /*Q0*/ )
150 : {
151 : Word16 *x1, *x2, i;
152 : const Word16 *c1, *c2;
153 : Word32 s;
154 :
155 0 : IF( frac < 0 )
156 : {
157 0 : frac = add( frac, 4 ); /*Q0*/
158 0 : x--;
159 : }
160 :
161 0 : x1 = &x[0]; /*Qx*/
162 0 : x2 = &x[1]; /*Qx*/
163 0 : c1 = &E_ROM_inter4_1_fx[frac]; /*Q14*/
164 0 : c2 = &E_ROM_inter4_1_fx[4 - frac]; /*Q14*/
165 :
166 : /*s = x1[0] * c1[0] + x2[0] * c2[0];
167 : s += x1[-1] * c1[4] + x2[1] * c2[4];
168 : s += x1[-2] * c1[8] + x2[2] * c2[8];
169 : s += x1[-3] * c1[12] + x2[3] * c2[12];*/
170 :
171 0 : s = L_deposit_l( 0 );
172 0 : FOR( i = 0; i < 4; i++ )
173 : {
174 0 : s = L_mac( s, *x1--, *c1 ); /* Qx + 15 */
175 0 : s = L_mac( s, *x2++, *c2 ); /* Qx + 15 */
176 0 : c1 += 4;
177 0 : c2 += 4;
178 : }
179 :
180 0 : return round_fx( L_shl( s, 1 ) ); /*Qx*/
181 : }
182 :
183 29218 : static Word16 E_GAIN_norm_corr_interpolate6_fx( Word16 *x /*Qx*/, Word16 frac /*Q0*/ )
184 : {
185 : Word16 *x1, *x2, i;
186 : const Word16 *c1, *c2;
187 : Word32 s;
188 :
189 29218 : IF( frac < 0 )
190 : {
191 11702 : frac = add( frac, 6 ); /*Q0*/
192 11702 : x--;
193 : }
194 :
195 29218 : x1 = &x[0]; /*Qx*/
196 29218 : x2 = &x[1]; /*Qx*/
197 29218 : c1 = &E_ROM_inter6_1_fx[frac]; /*Q14*/
198 29218 : c2 = &E_ROM_inter6_1_fx[6 - frac]; /*Q14*/
199 :
200 : /*s = x1[0] * c1[0] + x2[0] * c2[0];
201 : s += x1[-1] * c1[6] + x2[1] * c2[6];
202 : s += x1[-2] * c1[12] + x2[2] * c2[12];
203 : s += x1[-3] * c1[18] + x2[3] * c2[18];*/
204 29218 : s = L_deposit_l( 0 );
205 146090 : FOR( i = 0; i < 4; i++ )
206 : {
207 116872 : s = L_mac( s, *x1--, *c1 ); /* Qx + 15 */
208 116872 : s = L_mac( s, *x2++, *c2 ); /* Qx + 15 */
209 116872 : c1 += 6;
210 116872 : c2 += 6;
211 : }
212 :
213 29218 : return round_fx( L_shl( s, 1 ) ); /*Qx*/
214 : }
215 :
216 : /*
217 : * E_GAIN_closed_loop_search_fx
218 : *
219 : * Parameters:
220 : * exc I: excitation buffer
221 : * xn I: target signal
222 : * h I: weighted synthesis filter impulse response
223 : * dn I: residual domain target signal
224 : * t0_min I: minimum value in the searched range
225 : * t0_max I: maximum value in the searched range
226 : * pit_frac O: chosen fraction
227 : * i_subfr I: flag to first subframe
228 : * t0_fr2 I: minimum value for resolution 1/2
229 : * t0_fr1 I: minimum value for resolution 1
230 : *
231 : * Function:
232 : * Find the closed loop pitch period with 1/4 subsample resolution.
233 : *
234 : * Returns:
235 : * chosen integer pitch lag
236 : */
237 6120 : Word16 E_GAIN_closed_loop_search_fx( Word16 exc[], /*Q_new*/
238 : Word16 xn[], /*Q_xn*/
239 : Word16 h[], /* Q14+shift */
240 : Word16 t0_min, /*Q0*/
241 : Word16 t0_min_frac, /*Q0*/
242 : Word16 t0_max, /*Q0*/
243 : Word16 t0_max_frac, /*Q0*/
244 : Word16 t0_min_max_res, /*Q0*/
245 : Word16 *pit_frac, /*Q0*/
246 : Word16 *pit_res, /*Q0*/
247 : Word16 pit_res_max, /*Q0*/
248 : Word16 i_subfr, /*Q0*/
249 : Word16 pit_min, /*Q0*/
250 : Word16 pit_fr2, /*Q0*/
251 : Word16 pit_fr1, /*Q0*/
252 : Word16 L_subfr /*Q0*/ )
253 : {
254 : Word16 corr_v[32 + 2 * L_INTERPOL1 + 1];
255 : Word16 cor_max, max, temp;
256 : Word16 *corr;
257 : Word16 i, fraction, frac1, frac2, step;
258 : Word16 t0, t_min, t_max;
259 :
260 6120 : set16_fx( corr_v, 0, 32 + 2 * L_INTERPOL1 + 1 );
261 : /* Find interval to compute normalized correlation */
262 6120 : if ( t0_min_frac > 0 )
263 : {
264 5522 : t0_min = add( t0_min, 1 );
265 5522 : move16();
266 : }
267 6120 : t_min = sub( t0_min, L_INTERPOL1 );
268 6120 : t_max = add( t0_max, L_INTERPOL1 );
269 6120 : move16();
270 6120 : move16();
271 :
272 : /* allocate memory to normalized correlation vector */
273 6120 : corr = &corr_v[negate( t_min )]; /* corr[t_min..t_max] */
274 :
275 : /* Compute normalized correlation between target and filtered excitation */
276 6120 : E_GAIN_norm_corr_fx( exc, xn, h, t_min, t_max, corr_v, L_subfr );
277 :
278 : /* find integer pitch */
279 6120 : max = corr[t0_min]; /*(Q15+(Q_new+shift-1)+scale)*/
280 6120 : move16();
281 6120 : t0 = t0_min; /*Q0*/
282 6120 : move16();
283 :
284 116954 : FOR( i = t0_min + 1; i <= t0_max; i++ )
285 : {
286 : BASOP_SATURATE_WARNING_OFF_EVS;
287 110834 : if ( GE_16( corr[i], max ) )
288 : {
289 40600 : t0 = i;
290 40600 : move16();
291 : }
292 110834 : max = s_max( max, corr[i] );
293 : BASOP_SATURATE_WARNING_ON_EVS;
294 : }
295 :
296 :
297 : /* If first subframe and t0 >= pit_fr1, do not search fractionnal pitch */
298 6120 : test();
299 6120 : IF( ( i_subfr == 0 ) && GE_16( t0, pit_fr1 ) )
300 : {
301 224 : *pit_frac = 0;
302 224 : move16();
303 224 : *pit_res = 1;
304 224 : move16();
305 224 : return ( t0 );
306 : }
307 :
308 :
309 : /*
310 : * Search fractionnal pitch
311 : * Test the fractions around t0 and choose the one which maximizes
312 : * the interpolated normalized correlation.
313 : */
314 :
315 5896 : IF( EQ_16( t0_min_max_res, shr( pit_res_max, 1 ) ) )
316 : {
317 5896 : t0_min_frac = shl( t0_min_frac, 1 ); /*Q0*/
318 5896 : t0_max_frac = shl( t0_max_frac, 1 ); /*Q0*/
319 : }
320 :
321 5896 : step = 1;
322 5896 : move16();
323 5896 : frac1 = sub( 1, pit_res_max ); /*Q0*/
324 5896 : frac2 = sub( pit_res_max, 1 ); /*Q0*/
325 :
326 5896 : test();
327 5896 : test();
328 5896 : IF( ( ( i_subfr == 0 ) && GE_16( t0, pit_fr2 ) ) || LE_16( pit_fr2, pit_min ) )
329 : {
330 5896 : step = 2;
331 5896 : move16();
332 5896 : frac1 = sub( 2, pit_res_max ); /*Q0*/
333 5896 : frac2 = sub( pit_res_max, 2 ); /*Q0*/
334 : }
335 5896 : test();
336 5896 : IF( ( EQ_16( t0, t0_min ) ) && ( t0_min_frac == 0 ) )
337 : {
338 20 : frac1 = t0_min_frac; /*Q0*/
339 20 : move16();
340 : }
341 : ELSE
342 : {
343 5876 : test();
344 5876 : IF( ( EQ_16( t0, t0_min ) ) && ( LT_16( add( frac1, pit_res_max ), t0_min_frac ) ) )
345 : {
346 50 : frac1 = sub( t0_min_frac, pit_res_max ); /*Q0*/
347 : }
348 : }
349 :
350 5896 : if ( EQ_16( t0, t0_max ) )
351 : {
352 134 : frac2 = t0_max_frac; /*Q0*/
353 134 : move16();
354 : }
355 5896 : assert( frac1 <= 0 && frac2 >= 0 && frac2 > frac1 );
356 :
357 5896 : IF( EQ_16( pit_res_max, 6 ) )
358 : {
359 5896 : cor_max = E_GAIN_norm_corr_interpolate6_fx( &corr[t0], frac1 ); /*(Q15+(Q_new+shift-1)+scale)*/
360 5896 : fraction = frac1; /*Q0*/
361 5896 : move16();
362 :
363 29218 : FOR( i = ( frac1 + step ); i <= frac2; i += step )
364 : {
365 23322 : temp = E_GAIN_norm_corr_interpolate6_fx( &corr[t0], i ); /*(Q15+(Q_new+shift-1)+scale)*/
366 23322 : IF( GT_16( temp, cor_max ) )
367 : {
368 11700 : cor_max = temp; /*(Q15+(Q_new+shift-1)+scale)*/
369 11700 : move16();
370 11700 : fraction = i;
371 11700 : move16();
372 : }
373 : }
374 : }
375 : ELSE
376 : {
377 0 : cor_max = E_GAIN_norm_corr_interpolate_fx( &corr[t0], frac1 ); /*(Q15+(Q_new+shift-1)+scale)*/
378 0 : fraction = frac1; /*Q0*/
379 0 : move16();
380 :
381 0 : FOR( i = ( frac1 + step ); i <= frac2; i += step )
382 : {
383 0 : temp = E_GAIN_norm_corr_interpolate_fx( &corr[t0], i ); /*(Q15+(Q_new+shift-1)+scale)*/
384 0 : IF( GT_16( temp, cor_max ) )
385 : {
386 0 : cor_max = temp; /*(Q15+(Q_new+shift-1)+scale)*/
387 0 : move16();
388 0 : fraction = i;
389 0 : move16();
390 : }
391 : }
392 : }
393 :
394 : /* limit the fraction value */
395 5896 : IF( fraction < 0 )
396 : {
397 1538 : fraction = add( fraction, pit_res_max ); /*Q0*/
398 1538 : t0 = sub( t0, 1 );
399 : }
400 5896 : test();
401 5896 : test();
402 5896 : IF( ( ( i_subfr == 0 ) && GE_16( t0, pit_fr2 ) ) || LE_16( pit_fr2, pit_min ) )
403 : {
404 5896 : *pit_res = shr( pit_res_max, 1 ); /*Q0*/
405 5896 : move16();
406 5896 : *pit_frac = shr( fraction, 1 ); /*Q0*/
407 5896 : move16();
408 : }
409 : ELSE
410 : {
411 0 : *pit_res = pit_res_max; /*Q0*/
412 0 : move16();
413 0 : *pit_frac = fraction; /*Q0*/
414 0 : move16();
415 : }
416 5896 : return ( t0 );
417 : }
|