Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 : #include <stdint.h>
5 : #include "options.h" /* Compilation switches */
6 : #include "cnst.h" /* Common constants */
7 : #include "rom_enc.h" /* Encoder static table prototypes */
8 : #include "rom_com_fx.h" /* Encoder static table prototypes */
9 : #include "rom_com.h" /* Encoder static table prototypes */
10 : #include "rom_dec.h"
11 : //#include "prot_fx.h" /* Function prototypes */
12 : #include "prot_fx.h" /* Function prototypes */
13 : #include "prot_fx_enc.h" /* Function prototypes */
14 :
15 : /*-------------------------------------------------------------------*
16 : * Local constants
17 : *-------------------------------------------------------------------*/
18 :
19 : #define MAX_DELTA 16 /* half-length of the delta search */
20 : #define COR_BUF_LEN ( L_INTERPOL1 * 2 + MAX_DELTA * 2 + 1 )
21 :
22 : /*-------------------------------------------------------------------*
23 : * pitch_ol2()
24 : *
25 : * Open-loop pitch precision improvement with 1/4 resolution
26 : * The pitch is searched in the interval <pitch_ol-delta, pitch_ol+delta),
27 : * i.e. the value pitch_ol + delta is not a part of the interval
28 : *-------------------------------------------------------------------*/
29 1187384 : void pitch_ol2_fx(
30 : const Word16 pit_min, /* i : minimum pitch value (20 or 29) */
31 : const Word16 pitch_ol, /* i : pitch to be improved */
32 : Word16 *pitch_fr_fx,
33 : /* o : adjusted 1/4 fractional pitch */ /*Q7*/
34 : Word16 *voicing_fr_fx,
35 : /* o : adjusted 1/4 fractional voicing */ /*Q15*/
36 : const Word16 pos, /* i : position in frame where to calculate the improv. */
37 : const Word16 *wsp_fx,
38 : /* i : weighted speech for current frame and look-ahead */ /*Q_new-1+shift*/
39 : const Word16 delta, /* i : delta for pitch search (2 or 7) */
40 : const Word16 element_mode /* i : EVS or IVAS */
41 : )
42 : {
43 : Word16 i, t, step, fraction, t0_min, t0_max, t_min, t_max;
44 : const Word16 *pt_wsp_fx;
45 : Word16 wsp_fr_fx[L_SUBFR];
46 : Word16 temp_fx, cor_max_fx, cor_fx[COR_BUF_LEN], *pt_cor_fx;
47 : Word32 cor_32[COR_BUF_LEN], *pt_cor_32, t0, t1;
48 : Word16 t0s, t1s;
49 : Word16 exp3;
50 : Word32 R1, R2;
51 : Word16 R0, exp_R0, exp_R1, exp_R2, j;
52 : Word16 pit_max;
53 : #ifndef ISSUE_1867_replace_overflow_libenc
54 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
55 : Flag Overflow = 0;
56 : move32();
57 : #endif
58 : #endif
59 :
60 : /* initialization */
61 1187384 : pit_max = PIT_MAX;
62 1187384 : move16();
63 1187384 : t0_min = sub( pitch_ol, delta );
64 1187384 : t0_max = add( pitch_ol, sub( delta, 1 ) );
65 1187384 : t0_min = s_max( t0_min, pit_min );
66 1187384 : t_min = sub( t0_min, L_INTERPOL1 );
67 :
68 1187384 : t0_max = s_min( t0_max, pit_max );
69 1187384 : t_max = add( t0_max, L_INTERPOL1 );
70 :
71 1187384 : pt_wsp_fx = wsp_fx + pos;
72 1187384 : pt_cor_32 = cor_32;
73 1187384 : t1 = L_deposit_l( 0 );
74 26698284 : FOR( t = t_min; t <= t_max; t++ )
75 : {
76 25510900 : t0 = Dot_product( pt_wsp_fx, pt_wsp_fx - t, L_SUBFR );
77 25510900 : *pt_cor_32++ = t0;
78 25510900 : move32();
79 25510900 : t0 = L_abs( t0 );
80 25510900 : t1 = L_max( t1, t0 );
81 : }
82 1187384 : exp3 = norm_l( t1 );
83 1187384 : pt_cor_32 = cor_32;
84 1187384 : pt_cor_fx = cor_fx;
85 26698284 : FOR( t = t_min; t <= t_max; t++ )
86 : {
87 : #ifdef ISSUE_1867_replace_overflow_libenc
88 25510900 : t0 = L_shl_sat( *pt_cor_32++, exp3 );
89 25510900 : *pt_cor_fx++ = round_fx_sat( t0 );
90 : #else
91 : t0 = L_shl_o( *pt_cor_32++, exp3, &Overflow );
92 : *pt_cor_fx++ = round_fx_o( t0, &Overflow );
93 : #endif
94 25510900 : move16();
95 : }
96 :
97 1187384 : pt_cor_fx = cor_fx + L_INTERPOL1;
98 1187384 : cor_max_fx = *pt_cor_fx++;
99 1187384 : move16();
100 1187384 : t1s = t0_min;
101 1187384 : move16();
102 16011828 : FOR( t = t0_min + 1; t <= t0_max; t++ )
103 : {
104 14824444 : if ( GT_16( *pt_cor_fx, cor_max_fx ) )
105 : {
106 5894469 : t1s = t;
107 5894469 : move16();
108 : }
109 14824444 : cor_max_fx = s_max( cor_max_fx, *pt_cor_fx );
110 14824444 : pt_cor_fx++;
111 : }
112 :
113 : /*----------------------------------------------------------------*
114 : * Search fractionnal pitch with 1/4 subsample resolution.
115 : * search the fractions around t0 and choose the one which maximizes
116 : * the interpolated normalized correlation.
117 : *----------------------------------------------------------------*/
118 1187384 : pt_cor_fx = cor_fx + sub( L_INTERPOL1, t0_min );
119 1187384 : t0s = t1s;
120 1187384 : move16();
121 :
122 1187384 : step = 1;
123 1187384 : move16(); /* 1/4 subsample resolution */
124 1187384 : fraction = 1;
125 1187384 : move16();
126 :
127 1187384 : IF( NE_16( t0s, t0_min ) ) /* Process negative fractions */
128 : {
129 1088512 : t0s = sub( t0s, 1 );
130 1088512 : cor_max_fx = Interpol_4( &pt_cor_fx[t0s], fraction );
131 3265536 : FOR( i = fraction + step; i <= 3; i += step )
132 : {
133 2177024 : temp_fx = Interpol_4( &pt_cor_fx[t0s], i );
134 2177024 : if ( GT_16( temp_fx, cor_max_fx ) )
135 : {
136 2038075 : fraction = i;
137 2038075 : move16();
138 : }
139 2177024 : cor_max_fx = s_max( temp_fx, cor_max_fx );
140 : }
141 : }
142 : ELSE /* Limit case */
143 : {
144 98872 : fraction = 0;
145 98872 : move16();
146 98872 : cor_max_fx = Interpol_4( &pt_cor_fx[t0s], fraction );
147 98872 : move16();
148 : }
149 5936920 : FOR( i = 0; i <= 3; i += step ) /* Process positive fractions */
150 : {
151 4749536 : temp_fx = Interpol_4( &pt_cor_fx[t1s], i );
152 :
153 4749536 : IF( GT_16( temp_fx, cor_max_fx ) )
154 : {
155 1380022 : cor_max_fx = temp_fx;
156 1380022 : move16();
157 1380022 : fraction = i;
158 1380022 : move16();
159 1380022 : t0s = t1s;
160 1380022 : move16();
161 : }
162 : }
163 :
164 1187384 : *pitch_fr_fx = shl( add( shl( t0s, 2 ), fraction ), 4 );
165 1187384 : move16(); /*Q7*/
166 :
167 1187384 : IF( NE_32( t1, 1L ) )
168 : {
169 1171900 : IF( element_mode != EVS_MONO )
170 : {
171 1163506 : pred_lt4_ivas_fx( pt_wsp_fx, wsp_fr_fx, t0s, fraction, L_SUBFR, L_pitch_inter4_1, 4, PIT_UP_SAMP );
172 : }
173 : ELSE
174 : {
175 8394 : pred_lt4( pt_wsp_fx, wsp_fr_fx, t0s, fraction, L_SUBFR, pitch_inter4_1, 4, PIT_UP_SAMP );
176 : }
177 :
178 1171900 : R0 = cor_max_fx;
179 1171900 : move16();
180 1171900 : R1 = L_mult( pt_wsp_fx[0], pt_wsp_fx[0] );
181 1171900 : R2 = L_mult( wsp_fr_fx[0], wsp_fr_fx[0] );
182 75001600 : FOR( j = 1; j < L_SUBFR; j++ )
183 : {
184 73829700 : R1 = L_mac_sat( R1, pt_wsp_fx[j], pt_wsp_fx[j] );
185 73829700 : R2 = L_mac_sat( R2, wsp_fr_fx[j], wsp_fr_fx[j] );
186 : }
187 :
188 : /* *voicing_fr = cor_max * inv_sqrt(enr_wsp * enr_old) */
189 : /* *voicing_fr = R0 * inv_sqrt(R1 * R2) */
190 1171900 : exp_R0 = norm_s( R0 );
191 1171900 : R0 = shl( R0, exp_R0 );
192 :
193 1171900 : exp_R1 = norm_l( R1 );
194 1171900 : R1 = L_shl( R1, exp_R1 );
195 :
196 1171900 : exp_R2 = norm_l( R2 );
197 1171900 : R2 = L_shl( R2, exp_R2 );
198 :
199 : #ifdef ISSUE_1867_replace_overflow_libenc
200 1171900 : R1 = L_mult_sat( round_fx_sat( R1 ), round_fx_sat( R2 ) );
201 : #else
202 : R1 = L_mult_o( round_fx_o( R1, &Overflow ), round_fx_o( R2, &Overflow ), &Overflow );
203 : #endif
204 1171900 : i = norm_l( R1 );
205 1171900 : R1 = L_shl( R1, i );
206 :
207 1171900 : exp_R1 = add( exp_R1, exp_R2 );
208 1171900 : exp_R1 = add( exp_R1, i );
209 1171900 : exp_R1 = sub( 62, exp_R1 );
210 :
211 1171900 : R1 = Isqrt_lc( R1, &exp_R1 );
212 :
213 : #ifdef ISSUE_1867_replace_overflow_libenc
214 1171900 : R1 = L_mult( R0, round_fx_sat( R1 ) );
215 : #else
216 : R1 = L_mult( R0, round_fx_o( R1, &Overflow ) );
217 : #endif
218 1171900 : exp_R0 = sub( 31, exp_R0 );
219 1171900 : exp_R0 = sub( add( exp_R0, exp_R1 ), exp3 );
220 :
221 : #ifdef ISSUE_1867_replace_overflow_libenc
222 1171900 : *voicing_fr_fx = round_fx_sat( L_shl_sat( R1, exp_R0 ) ); /*Q15*/
223 : #else
224 : *voicing_fr_fx = round_fx_o( L_shl_o( R1, exp_R0, &Overflow ), &Overflow ); /*Q15*/
225 : #endif
226 1171900 : move16();
227 : }
228 : ELSE
229 : {
230 15484 : *voicing_fr_fx = 0;
231 15484 : move16();
232 : }
233 :
234 1187384 : return;
235 : }
236 :
237 : /*-------------------------------------------------------------------*
238 : * StableHighPitchDetect()
239 : *
240 : * stable very short pitch detection
241 : *-------------------------------------------------------------------*/
242 3100 : void StableHighPitchDetect_fx(
243 : Word16 *flag_spitch, /* o : flag to indicate very short stable pitch */
244 : Word16 pitch[], /* i/o: OL pitch buffer */
245 : const Word16 voicing[], /* i : OL pitch gains */
246 : const Word16 wsp[], /* i : weighted speech */
247 : const Word16 localVAD, /* i : local VAD flag */
248 : Word16 *voicing_sm, /* i/o: smoothed open-loop pitch gains */
249 : Word16 *voicing0_sm, /* i/o: smoothed high pitch gains */
250 : Word16 *LF_EnergyRatio_sm, /* i/o: smoothed [0, 300Hz] relative peak energy*/
251 : Word16 *predecision_flag, /* i/o: predecision flag */
252 : Word32 *diff_sm, /* i/o: smoothed pitch frequency difference */
253 : Word32 *energy_sm, /* i/o: smoothed energy around pitch frequency */
254 : Word16 Q_new,
255 : Word16 EspecdB[] )
256 : {
257 : Word16 i, pitch_freq_point;
258 : Word16 T, Tp, pit_min;
259 : Word16 energy0_16, energy1_16, ratio, voicing_m;
260 : Word32 energy0, energy1, cor_max, diff, sum_energy;
261 : const Word16 *pt_wsp;
262 : Word16 tmp, tmp1, exp, diff16, cor_max16, exp1, exp2, pit_min_up;
263 : Word32 L_tmp, L_tmp1;
264 : Word16 Top;
265 : #ifndef ISSUE_1867_replace_overflow_libenc
266 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
267 : Flag Overflow = 0;
268 : move32();
269 : #endif
270 : #endif
271 :
272 : /*voicing = (voicing[0] + voicing[1] + voicing[2] )/3;*/
273 3100 : L_tmp = L_mult( voicing[0], 10923 /*1/3 in Q15*/ );
274 3100 : L_tmp = L_mac( L_tmp, voicing[1], 10923 /*1/3 in Q15*/ );
275 3100 : L_tmp = L_mac( L_tmp, voicing[2], 10923 /*1/3 in Q15*/ );
276 3100 : voicing_m = round_fx_sat( L_tmp );
277 : /**voicing_sm = 0.75f*(*voicing_sm) + 0.25f*voicing;*/
278 3100 : *voicing_sm = round_fx( L_mac( L_mult( *voicing_sm, 24576 /*0.75f Q15*/ ), voicing_m, 8192 /*0.25f Q15*/ ) );
279 3100 : move16();
280 : /* pitch_freq_point = (short)(L_FFT/(mult_fact*T_op[1])+0.5f);*/
281 3100 : Top = pitch[1];
282 3100 : move16();
283 3100 : exp = norm_s( Top );
284 3100 : tmp = div_s( shl( 1, sub( 14, exp ) ), Top ); /*Q(29 - exp)*/
285 3100 : L_tmp = L_mult0( tmp, L_FFT ); /*Q(29 - exp)*/
286 3100 : pitch_freq_point = extract_h( L_add( L_shl( L_tmp, sub( exp, 13 ) ), 32768 ) ); /* Q0*/
287 3100 : diff = L_deposit_l( 0 );
288 3100 : sum_energy = L_deposit_l( 0 );
289 29328 : FOR( i = 1; i < 2 * pitch_freq_point; i++ )
290 : {
291 26228 : diff = L_add( diff, sub( EspecdB[pitch_freq_point], EspecdB[i] ) );
292 26228 : sum_energy = L_add( sum_energy, EspecdB[i] );
293 : }
294 : /*sum_energy /= (2*pitch_freq_point-1);*/
295 3100 : tmp = sub( shl( pitch_freq_point, 1 ), 1 );
296 3100 : exp = norm_s( tmp );
297 3100 : tmp1 = div_s( shl( 1, sub( 14, exp ) ), tmp ); /*Q(29-exp)*/
298 3100 : L_tmp = Mult_32_16( sum_energy, tmp1 );
299 3100 : sum_energy = L_shl( L_tmp, sub( exp, 14 ) );
300 : /**diff_sm = 0.2f * diff + 0.8f * *diff_sm;*/
301 3100 : *diff_sm = L_add( Mult_32_16( diff, 6554 ), Mult_32_16( *diff_sm, 26214 ) );
302 3100 : move32();
303 : /**energy_sm = 0.2f * sum_energy + 0.8f * *energy_sm;*/
304 3100 : *energy_sm = L_add( Mult_32_16( sum_energy, 6554 ), Mult_32_16( *energy_sm, 26214 ) );
305 3100 : move32();
306 : /*diff /= sum_energy;*/
307 :
308 3100 : IF( sum_energy )
309 : {
310 3100 : exp = norm_l( sum_energy );
311 3100 : tmp = extract_h( L_shl( sum_energy, exp ) );
312 3100 : exp = sub( sub( 30, exp ), 7 );
313 3100 : IF( tmp < 0 )
314 : {
315 193 : tmp = abs_s( tmp );
316 193 : tmp = div_s( 16384, tmp ); /*Q(15+exp)*/
317 : BASOP_SATURATE_WARNING_OFF_EVS
318 193 : diff = L_negate( L_shr_sat( Mult_32_16( diff, tmp ), sub( exp + 7, 31 ) ) );
319 : #ifdef ISSUE_1867_replace_overflow_libenc
320 : BASOP_SATURATE_WARNING_ON_EVS
321 193 : diff16 = round_fx_sat( diff );
322 : #else
323 : BASOP_SATURATE_WARNING_ON_EVS
324 : diff16 = round_fx_o( diff, &Overflow );
325 : #endif
326 : }
327 : ELSE
328 : {
329 2907 : tmp = div_s( 16384, tmp ); /*Q(15+exp)*/
330 : BASOP_SATURATE_WARNING_OFF_EVS
331 2907 : diff = L_shr_sat( Mult_32_16( diff, tmp ), sub( exp + 7, 31 ) );
332 : #ifdef ISSUE_1867_replace_overflow_libenc
333 : BASOP_SATURATE_WARNING_ON_EVS
334 2907 : diff16 = round_fx_sat( diff );
335 : #else
336 : BASOP_SATURATE_WARNING_ON_EVS
337 : diff16 = round_fx_o( diff, &Overflow );
338 : #endif
339 : }
340 : }
341 : ELSE
342 : {
343 : #ifdef ISSUE_1867_replace_overflow_libenc
344 0 : diff16 = round_fx_sat( L_shl_sat( diff, 25 ) );
345 : #else
346 : diff16 = round_fx_o( L_shl_o( diff, 25, &Overflow ), &Overflow );
347 : #endif
348 : }
349 3100 : test();
350 3100 : test();
351 3100 : if ( LT_32( *diff_sm, -1280 /*-10.0f Q7*/ ) && LT_32( *energy_sm, 4928 /*38.5f Q7*/ ) && LT_16( diff16, -26214 /*-.8f Q15*/ ) )
352 : {
353 154 : *predecision_flag = 1;
354 154 : move16();
355 : }
356 3100 : test();
357 3100 : test();
358 3100 : if ( GT_32( *diff_sm, 1280 /*10.0f Q7*/ ) && GT_32( *energy_sm, 10624 /*83.0f Q7*/ ) && GT_16( diff16, 16384 /*.5 Q15*/ ) )
359 : {
360 133 : *predecision_flag = 0;
361 133 : move16();
362 : }
363 :
364 : /* short pitch possiblity pre-decision */
365 3100 : maximum_fx( EspecdB, 7, &energy0_16 );
366 3100 : maximum_fx( EspecdB + 8, 7, &energy1_16 );
367 3100 : ratio = s_max( sub( energy1_16, energy0_16 ), 0 ); /*Q7 */
368 : /*ratio *= max(voicing,0);*/
369 3100 : tmp = s_max( voicing_m, 0 );
370 3100 : ratio = mult_r( ratio, tmp ); /*Q7*/
371 : /**LF_EnergyRatio_sm = (15*(*LF_EnergyRatio_sm) + ratio)/16;*/
372 3100 : L_tmp = L_mult( ratio, 2048 );
373 3100 : L_tmp = L_mac( L_tmp, *LF_EnergyRatio_sm, 30720 );
374 3100 : *LF_EnergyRatio_sm = round_fx( L_tmp );
375 3100 : move16();
376 3100 : test();
377 3100 : if ( GT_16( *LF_EnergyRatio_sm, 4480 /*35.0f Q7*/ ) || GT_16( ratio, 6400 /*50.0f Q7*/ ) )
378 : {
379 1 : *predecision_flag = 1;
380 1 : move16();
381 : }
382 :
383 3100 : if ( LT_16( *LF_EnergyRatio_sm, 2048 /*16.0f Q7*/ ) )
384 : {
385 2978 : *predecision_flag = 0;
386 2978 : move16();
387 : }
388 :
389 : /* short pitch candidate detection */
390 3100 : Tp = pitch[1];
391 3100 : move16();
392 3100 : cor_max = 0;
393 3100 : move16();
394 3100 : pt_wsp = wsp + 3 * L_SUBFR;
395 3100 : pit_min = PIT_MIN_DOUBLEEXTEND;
396 3100 : move16();
397 3100 : pit_min_up = PIT_MIN;
398 3100 : move16();
399 58900 : FOR( T = pit_min; T <= pit_min_up; T++ )
400 : {
401 55800 : energy1 = Dot_product( pt_wsp, pt_wsp - T, L_SUBFR );
402 55800 : test();
403 55800 : IF( ( GT_32( energy1, cor_max ) ) || ( EQ_16( T, pit_min ) ) )
404 : {
405 20766 : cor_max = L_add( energy1, 0 );
406 20766 : Tp = T;
407 20766 : move16();
408 : }
409 : }
410 3100 : energy0 = Dot_product12( pt_wsp, pt_wsp, L_SUBFR, &exp1 );
411 3100 : exp1 = sub( exp1, shl( Q_new, 1 ) );
412 3100 : energy1 = Dot_product12( pt_wsp - Tp, pt_wsp - Tp, L_SUBFR, &exp2 );
413 3100 : exp2 = sub( exp2, shl( Q_new, 1 ) );
414 : /* cor_max *= inv_sqrt( energy0*energy1 );*/
415 3100 : L_tmp = Mult_32_32( energy0, energy1 );
416 3100 : exp = norm_l( L_tmp );
417 3100 : L_tmp1 = L_shl( L_tmp, exp );
418 :
419 3100 : exp = 31 - exp - ( 31 - exp1 - exp2 );
420 3100 : move16();
421 3100 : L_tmp1 = Isqrt_lc( L_tmp1, &exp ); /*Q(31-exp)*/
422 3100 : cor_max = Mult_32_32( cor_max, L_tmp1 );
423 3100 : exp = 31 - ( shl( Q_new, 1 ) + 1 ) - ( 31 - exp ) + 31;
424 : #ifdef ISSUE_1867_replace_overflow_libenc
425 3100 : cor_max16 = round_fx_sat( L_shl_sat( cor_max, exp ) ); /*Q15*/
426 : #else
427 : cor_max16 = round_fx_o( L_shl_o( cor_max, exp, &Overflow ), &Overflow ); /*Q15*/
428 : #endif
429 : /**voicing0_sm = add(mult_r(24576 ,(*voicing0_sm)) , mult_r(8192 , cor_max16));*/
430 3100 : *voicing0_sm = round_fx( L_mac( L_mult( 24576 /*.75f Q15*/, *voicing0_sm ), 8192 /*.25f Q15*/, cor_max16 ) );
431 3100 : move16();
432 :
433 : /* final short pitch detection */
434 3100 : test();
435 3100 : test();
436 3100 : test();
437 3100 : *flag_spitch = 0;
438 3100 : move16();
439 3100 : IF( ( EQ_16( localVAD, 1 ) ) && ( EQ_16( *predecision_flag, 1 ) ) &&
440 : ( GT_16( *voicing0_sm, 16384 ) ) && ( GT_16( *voicing0_sm, mult_r( *voicing_sm, 21299 ) ) ) )
441 : {
442 0 : *flag_spitch = 1;
443 0 : move16();
444 0 : pitch[0] = Tp;
445 0 : move16();
446 0 : pitch[1] = Tp;
447 0 : move16();
448 0 : pitch[2] = Tp;
449 0 : move16();
450 : }
451 :
452 3100 : return;
453 : }
454 :
455 :
456 : /*-------------------------------------------------------------------*
457 : * pitch_ol2()
458 : *
459 : * Open-loop pitch precision improvement with 1/4 resolution
460 : * The pitch is searched in the interval <pitch_ol-delta, pitch_ol+delta),
461 : * i.e. the value pitch_ol + delta is not a part of the interval
462 : *-------------------------------------------------------------------*/
463 :
464 : /*-------------------------------------------------------------------*
465 : * StableHighPitchDetect()
466 : *
467 : * Very short stable pitch detection
468 : *-------------------------------------------------------------------*/
469 1150754 : void StableHighPitchDetect_ivas_fx(
470 : Word16 *flag_spitch, /* o : flag to indicate very short stable pitch */
471 : Word16 pitch[], /* i/o: OL pitch buffer */
472 : const Word16 voicing[], /* i : OL pitch gains Q15 */
473 : const Word16 wsp[], /* i : weighted speech Qx */
474 : const Word16 localVAD, /* i : local VAD flag */
475 : Word16 *voicing_sm, /* i/o: smoothed open-loop pitch gains */
476 : Word16 *voicing0_sm, /* i/o: smoothed high pitch gains */
477 : Word16 *LF_EnergyRatio_sm, /* i/o: smoothed [0, 300Hz] relative peak energy Q7*/
478 : Word16 *predecision_flag, /* i/o: predecision flag */
479 : Word32 *diff_sm, /* i/o: smoothed pitch frequency difference Q7*/
480 : Word32 *energy_sm, /* i/o: smoothed energy around pitch frequency Q7*/
481 : Word16 Q_new,
482 : Word16 EspecdB[] /*Q8*/
483 : )
484 : {
485 : Word16 i, pitch_freq_point;
486 : Word16 T, Tp, pit_min;
487 : Word16 energy0_16, energy1_16, ratio, voicing_m;
488 : Word32 energy0, energy1, cor_max, diff, sum_energy;
489 : const Word16 *pt_wsp;
490 : Word16 tmp, tmp1, exp, diff16, cor_max16, exp1, exp2, pit_min_up;
491 : Word32 L_tmp, L_tmp1;
492 : Word16 Top;
493 : #ifndef ISSUE_1867_replace_overflow_libenc
494 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
495 : Flag Overflow = 0;
496 : move32();
497 : #endif
498 : #endif
499 :
500 : /*voicing = (voicing[0] + voicing[1] + voicing[2] )/3;*/
501 1150754 : L_tmp = L_mult( voicing[0], 10923 /*1/3 in Q15*/ );
502 1150754 : L_tmp = L_mac( L_tmp, voicing[1], 10923 /*1/3 in Q15*/ );
503 1150754 : L_tmp = L_mac( L_tmp, voicing[2], 10923 /*1/3 in Q15*/ );
504 1150754 : voicing_m = round_fx_sat( L_tmp );
505 : /**voicing_sm = 0.75f*(*voicing_sm) + 0.25f*voicing;*/
506 1150754 : *voicing_sm = round_fx( L_mac( L_mult( *voicing_sm, 24576 /*0.75f Q15*/ ), voicing_m, 8192 /*0.25f Q15*/ ) );
507 1150754 : move16();
508 :
509 : /* pitch_freq_point = (short)(L_FFT/(mult_fact*T_op[1])+0.5f);*/
510 1150754 : Top = pitch[1];
511 1150754 : move16();
512 1150754 : pitch_freq_point = idiv1616( L_FFT, Top ); /* Q0*/
513 1150754 : sum_energy = L_deposit_l( 0 );
514 10112522 : FOR( i = 1; i < 2 * pitch_freq_point; i++ )
515 : {
516 8961768 : sum_energy = L_mac0( sum_energy, EspecdB[i], 1 ); // sum_energy
517 : }
518 1150754 : tmp = sub( shl( pitch_freq_point, 1 ), 1 );
519 :
520 : /* for ( i = 1; i < 2 * pitch_freq_point; i++ )
521 : {
522 : diff += ( EspecdB[pitch_freq_point] - EspecdB[i] );
523 : }
524 : sum energy is the accumulated value of EspecdB over the loop and EspecdB[pitch_freq_point] is constant for the loop
525 : diff can be computed as (2 * pitch_freq_point - 1) * EspecdB[pitch_freq_point] - sum_energy */
526 :
527 1150754 : diff = L_mac0( L_negate( sum_energy ), EspecdB[pitch_freq_point], tmp );
528 :
529 : /*sum_energy /= (2*pitch_freq_point-1);*/
530 :
531 1150754 : exp = norm_s( tmp );
532 1150754 : tmp1 = div_s( shl( 1, sub( 14, exp ) ), tmp ); /*Q(29-exp)*/
533 1150754 : L_tmp = Mult_32_16( sum_energy, tmp1 );
534 1150754 : sum_energy = L_shl( L_tmp, sub( exp, 14 ) );
535 : /**diff_sm = 0.2f * diff + 0.8f * *diff_sm;*/
536 1150754 : *diff_sm = L_add( Mult_32_16( diff, 6554 /*.2f Q15*/ ), Mult_32_16( *diff_sm, 26214 /*.8f Q15*/ ) );
537 1150754 : move32();
538 : /**energy_sm = 0.2f * sum_energy + 0.8f * *energy_sm;*/
539 1150754 : *energy_sm = L_add( Mult_32_16( sum_energy, 6554 /*.2f Q15*/ ), Mult_32_16( *energy_sm, 26214 /*.8f Q15*/ ) );
540 1150754 : move32();
541 : /*diff /= sum_energy;*/
542 :
543 1150754 : IF( sum_energy )
544 : {
545 1150708 : exp = norm_l( sum_energy );
546 1150708 : tmp = extract_h( L_shl( sum_energy, exp ) );
547 1150708 : exp = sub( sub( 30, exp ), 7 );
548 1150708 : IF( tmp < 0 )
549 : {
550 174875 : tmp = abs_s( tmp );
551 174875 : tmp = div_s( 16384, tmp ); /*Q(15+exp)*/
552 : BASOP_SATURATE_WARNING_OFF_EVS
553 174875 : diff = L_negate( L_shr_sat( Mult_32_16( diff, tmp ), sub( exp + 7, 31 ) ) );
554 : #ifdef ISSUE_1867_replace_overflow_libenc
555 : BASOP_SATURATE_WARNING_ON_EVS
556 174875 : diff16 = round_fx_sat( diff );
557 : #else
558 : BASOP_SATURATE_WARNING_ON_EVS
559 : diff16 = round_fx_o( diff, &Overflow );
560 : #endif
561 : }
562 : ELSE
563 : {
564 975833 : tmp = div_s( 16384, tmp ); /*Q(15+exp)*/
565 : BASOP_SATURATE_WARNING_OFF_EVS
566 975833 : diff = L_shr_sat( Mult_32_16( diff, tmp ), sub( exp + 7, 31 ) );
567 : #ifdef ISSUE_1867_replace_overflow_libenc
568 : BASOP_SATURATE_WARNING_ON_EVS
569 975833 : diff16 = round_fx_sat( diff );
570 : #else
571 : BASOP_SATURATE_WARNING_ON_EVS
572 : diff16 = round_fx_o( diff, &Overflow );
573 : #endif
574 : }
575 : }
576 : ELSE
577 : {
578 : #ifdef ISSUE_1867_replace_overflow_libenc
579 46 : diff16 = round_fx_sat( L_shl_sat( diff, 25 ) );
580 : #else
581 : diff16 = round_fx_o( L_shl_o( diff, 25, &Overflow ), &Overflow );
582 : #endif
583 : }
584 1150754 : test();
585 1150754 : test();
586 1150754 : IF( LT_32( *diff_sm, -1280 /*-10.0f Q7*/ ) && LT_32( *energy_sm, 4928 /*38.5f Q7*/ ) && LT_16( diff16, -26214 /*-.8f Q15*/ ) )
587 : {
588 21665 : *predecision_flag = 1;
589 21665 : move16();
590 : }
591 1150754 : test();
592 1150754 : test();
593 1150754 : if ( GT_32( *diff_sm, 1280 /*10.0f Q7*/ ) && GT_32( *energy_sm, 10624 /*83.0f Q7*/ ) && GT_16( diff16, 16384 /*.5 Q15*/ ) )
594 : {
595 87651 : *predecision_flag = 0;
596 87651 : move16();
597 : }
598 :
599 : /* short pitch possiblity pre-decision */
600 1150754 : maximum_fx( EspecdB, 7, &energy0_16 );
601 1150754 : maximum_fx( EspecdB + 8, 7, &energy1_16 );
602 1150754 : test();
603 1150754 : IF( energy1_16 < 0 && energy0_16 > 0 )
604 : {
605 31300 : ratio = 0;
606 31300 : move16();
607 : }
608 : ELSE
609 : {
610 1119454 : ratio = s_max( sub( energy1_16, energy0_16 ), 0 ); /*Q7 */
611 : }
612 : /*ratio *= max(voicing,0);*/
613 1150754 : tmp = s_max( voicing_m, 0 );
614 1150754 : ratio = mult_r( ratio, tmp ); /*Q7*/
615 : /**LF_EnergyRatio_sm = (15*(*LF_EnergyRatio_sm) + ratio)/16;*/
616 1150754 : L_tmp = L_mult( ratio, 2048 );
617 1150754 : L_tmp = L_mac( L_tmp, *LF_EnergyRatio_sm, 30720 );
618 1150754 : *LF_EnergyRatio_sm = round_fx( L_tmp );
619 1150754 : move16();
620 1150754 : test();
621 1150754 : if ( GT_16( *LF_EnergyRatio_sm, 4480 /*35.0f Q7*/ ) || GT_16( ratio, 6400 /*50.0f Q7*/ ) )
622 : {
623 28236 : *predecision_flag = 1;
624 28236 : move16();
625 : }
626 :
627 1150754 : if ( LT_16( *LF_EnergyRatio_sm, 2048 /*16.0f Q7*/ ) )
628 : {
629 1101229 : *predecision_flag = 0;
630 1101229 : move16();
631 : }
632 :
633 : /* short pitch candidate detection */
634 1150754 : Tp = pitch[1];
635 1150754 : move16();
636 1150754 : cor_max = 0;
637 1150754 : move16();
638 1150754 : pt_wsp = wsp + 3 * L_SUBFR;
639 1150754 : pit_min = PIT_MIN_DOUBLEEXTEND;
640 1150754 : move16();
641 1150754 : pit_min_up = PIT_MIN;
642 1150754 : move16();
643 21864326 : FOR( T = pit_min; T <= pit_min_up; T++ )
644 : {
645 20713572 : energy1 = Dot_product( pt_wsp, pt_wsp - T, L_SUBFR );
646 20713572 : test();
647 20713572 : IF( ( GT_32( energy1, cor_max ) ) || ( EQ_16( T, pit_min ) ) )
648 : {
649 6110378 : cor_max = L_add( energy1, 0 );
650 6110378 : Tp = T;
651 6110378 : move16();
652 : }
653 : }
654 1150754 : energy0 = Dot_product12( pt_wsp, pt_wsp, L_SUBFR, &exp1 );
655 1150754 : exp1 = sub( exp1, shl( Q_new, 1 ) );
656 1150754 : energy1 = Dot_product12( pt_wsp - Tp, pt_wsp - Tp, L_SUBFR, &exp2 );
657 1150754 : exp2 = sub( exp2, shl( Q_new, 1 ) );
658 : /* cor_max *= inv_sqrt( energy0*energy1 );*/
659 1150754 : L_tmp = Mult_32_32( energy0, energy1 );
660 1150754 : exp = norm_l( L_tmp );
661 1150754 : L_tmp1 = L_shl( L_tmp, exp );
662 :
663 1150754 : exp = sub( sub( 31, exp ), ( sub( sub( 31, exp1 ), exp2 ) ) );
664 1150754 : move16();
665 1150754 : L_tmp1 = Isqrt_lc( L_tmp1, &exp ); /*Q(31-exp)*/
666 1150754 : cor_max = Mult_32_32( cor_max, L_tmp1 );
667 1150754 : exp = add( sub( sub( 31, add( shl( Q_new, 1 ), 1 ) ), sub( 31, exp ) ), 31 );
668 : #ifdef ISSUE_1867_replace_overflow_libenc
669 1150754 : cor_max16 = round_fx_sat( L_shl_sat( cor_max, exp ) ); /*Q15*/
670 : #else
671 : cor_max16 = round_fx_o( L_shl_o( cor_max, exp, &Overflow ), &Overflow ); /*Q15*/
672 : #endif
673 : /**voicing0_sm = add(mult_r(24576 ,(*voicing0_sm)) , mult_r(8192 , cor_max16));*/
674 1150754 : *voicing0_sm = round_fx( L_mac( L_mult( 24576 /*.75f Q15*/, *voicing0_sm ), 8192 /*.25f Q15*/, cor_max16 ) );
675 1150754 : move16();
676 :
677 : /* final short pitch detection */
678 1150754 : test();
679 1150754 : test();
680 1150754 : test();
681 1150754 : *flag_spitch = 0;
682 1150754 : move16();
683 1150754 : IF( ( EQ_16( localVAD, 1 ) ) && ( EQ_16( *predecision_flag, 1 ) ) &&
684 : ( GT_16( *voicing0_sm, 21299 /*.65f in Q15*/ ) ) && ( GT_16( *voicing0_sm, mult_r( *voicing_sm, 22938 /*.7f in Q15*/ ) ) ) )
685 : {
686 37168 : *flag_spitch = 1;
687 37168 : move16();
688 37168 : pitch[0] = Tp;
689 37168 : move16();
690 37168 : pitch[1] = Tp;
691 37168 : move16();
692 37168 : pitch[2] = Tp;
693 37168 : move16();
694 : }
695 :
696 1150754 : return;
697 : }
|