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