Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #include "options.h" /* Compilation switches */
6 : #include "cnst.h" /* Common constants */
7 : #include "prot_fx.h" /* Function prototypes */
8 : #include "stl.h"
9 : #include "basop_util.h"
10 :
11 :
12 : /*======================================================================*/
13 : /* FUNCTION : est_tilt_fx() */
14 : /*-----------------------------------------------------------------------*/
15 : /* PURPOSE : Estimate spectral tilt based on the relative E of adaptive */
16 : /* and innovative excitations */
17 : /* */
18 : /*-----------------------------------------------------------------------*/
19 : /* INPUT ARGUMENTS : */
20 : /* _ (Word16 *) exc : adaptive excitation vector Q0 */
21 : /* _ (Word16) gain_pit : adaptive gain Q14 */
22 : /* _ (Word16 *) code : algebraic exctitation vector Q12 */
23 : /* _ (Word32) gain_code : algebraic code gain Q16 */
24 : /* _ (Word16) Q_exc : Scaling factor of excitation Q0 */
25 : /*-----------------------------------------------------------------------*/
26 : /* OUTPUT ARGUMENTS : */
27 : /* _ (Word16 *) voice_fac : voicing factor Q15 */
28 : /*-----------------------------------------------------------------------*/
29 : /* INPUT OUTPUT ARGUMENTS */
30 : /*-----------------------------------------------------------------------*/
31 :
32 : /*-----------------------------------------------------------------------*/
33 : /* RETURN ARGUMENTS : */
34 : /* _ (Word16) tolt_code : tilt of the code Q15 */
35 : /*=======================================================================*/
36 559 : Word16 est_tilt_fx( /* o : tilt of the code Q15 */
37 : const Word16 *exc, /* i : adaptive excitation vector Qx */
38 : const Word16 gain_pit, /* i : adaptive gain Q14 */
39 : const Word16 *code, /* i : algebraic excitation vector Q9 */
40 : const Word32 gain_code, /* i : algebraic code gain Q16 */
41 : Word16 *voice_fac, /* o : voicing factor Q15 */
42 : const Word16 Q_exc /* i : Scaling factor of excitation Q0 */
43 : )
44 : {
45 : Word16 i, tmp, exp, ener1, exp1, ener2, exp2;
46 : Word32 L_tmp;
47 : Word16 tilt_code;
48 :
49 559 : ener1 = extract_h( Dot_product12( exc, exc, L_SUBFR, &exp1 ) );
50 559 : exp1 = sub( exp1, add( Q_exc, Q_exc ) );
51 559 : L_tmp = L_mult( gain_pit, gain_pit ); /* energy of pitch excitation */
52 559 : exp = norm_l( L_tmp );
53 559 : tmp = extract_h( L_shl( L_tmp, exp ) );
54 559 : ener1 = mult( ener1, tmp );
55 559 : exp1 = sub( sub( exp1, exp ), 10 ); /* 10 -> gain_pit Q14 to Q9 */
56 :
57 559 : ener2 = extract_h( Dot_product12( code, code, L_SUBFR, &exp2 ) );
58 :
59 559 : exp = norm_l( gain_code );
60 559 : tmp = extract_h( L_shl( gain_code, exp ) );
61 559 : tmp = mult( tmp, tmp ); /* energy of innovative code excitation */
62 559 : ener2 = mult( ener2, tmp );
63 559 : exp2 = sub( exp2, add( exp, exp ) );
64 :
65 559 : i = sub( exp1, exp2 );
66 : BASOP_SATURATE_WARNING_OFF_EVS
67 559 : ener1 = shr_sat( ener1, sub( 1, s_min( i, 0 ) ) );
68 559 : ener2 = shr_sat( ener2, add( s_max( 0, i ), 1 ) );
69 : BASOP_SATURATE_WARNING_ON_EVS
70 559 : tmp = sub( ener1, ener2 );
71 559 : ener1 = add( add( ener1, ener2 ), 1 );
72 :
73 : /* find voice factor (1=voiced, -1=unvoiced) */
74 559 : exp = div_s( abs_s( tmp ), ener1 );
75 559 : if ( tmp < 0 )
76 : {
77 309 : exp = negate( exp );
78 : }
79 559 : *voice_fac = exp;
80 559 : move16();
81 :
82 : /* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */
83 :
84 : /* tilt_code = (float)(0.25*(1.0 + *voice_fac)) */
85 559 : tilt_code = mac_r( 8192L /*0.25.Q15*/ * 65536 /*1.Q16*/ - 0x8000 /*1.Q15*/, *voice_fac, 8192 /*0.25.Q15*/ ); /*Q15 */
86 :
87 559 : return tilt_code;
88 : }
89 :
90 : /*======================================================================*/
91 : /* FUNCTION : est_tilt_ivas_fx() */
92 : /*-----------------------------------------------------------------------*/
93 : /* PURPOSE : Estimate spectral tilt based on the relative E of adaptive */
94 : /* and innovative excitations */
95 : /* */
96 : /*-----------------------------------------------------------------------*/
97 : /* INPUT ARGUMENTS : */
98 : /* _ (Word16 *) exc : adaptive excitation vector Q0 */
99 : /* _ (Word16) gain_pit : adaptive gain Q14 */
100 : /* _ (Word16 *) code : algebraic exctitation vector Q12 */
101 : /* _ (Word32) gain_code : algebraic code gain Q16 */
102 : /* _ (Word16) Q_exc : Scaling factor of excitation Q0 */
103 : /*-----------------------------------------------------------------------*/
104 : /* OUTPUT ARGUMENTS : */
105 : /* _ (Word16 *) voice_fac : voicing factor Q15 */
106 : /*-----------------------------------------------------------------------*/
107 : /* INPUT OUTPUT ARGUMENTS */
108 : /*-----------------------------------------------------------------------*/
109 :
110 : /*-----------------------------------------------------------------------*/
111 : /* RETURN ARGUMENTS : */
112 : /* _ (Word16) tolt_code : tilt of the code Q15 */
113 : /*=======================================================================*/
114 :
115 : /* o : tilt of the code Q15 */
116 1150836 : Word16 est_tilt_ivas_fx(
117 : const Word16 *exc, /* i : adaptive excitation vector Qx */
118 : const Word16 gain_pit, /* i : adaptive gain Q14 */
119 : const Word16 *code, /* i : algebraic excitation vector Q9 */
120 : const Word32 gain_code, /* i : algebraic code gain Q16 */
121 : Word16 *voice_fac, /* o : voicing factor Q15 */
122 : const Word16 Q_exc, /* i : Scaling factor of excitation Q0 */
123 : const Word16 L_subfr, /* i : Sub frame length */
124 : const Word16 flag_tilt /* i : flag for special tilt */
125 : )
126 : {
127 : Word16 i, tmp, exp, ener1, exp1, ener2, exp2;
128 : Word32 L_tmp;
129 : Word16 tilt_code;
130 :
131 1150836 : ener1 = extract_h( Dot_product12( exc, exc, L_subfr, &exp1 ) );
132 1150836 : exp1 = sub( exp1, add( Q_exc, Q_exc ) );
133 1150836 : L_tmp = L_mult( gain_pit, gain_pit ); /* energy of pitch excitation */
134 1150836 : exp = norm_l( L_tmp );
135 1150836 : tmp = extract_h( L_shl( L_tmp, exp ) );
136 1150836 : ener1 = mult( ener1, tmp );
137 1150836 : exp1 = sub( sub( exp1, exp ), 10 ); /* 10 -> gain_pit Q14 to Q9 */
138 :
139 1150836 : ener2 = extract_h( Dot_product12( code, code, L_subfr, &exp2 ) );
140 :
141 1150836 : exp = norm_l( gain_code );
142 1150836 : tmp = extract_h( L_shl( gain_code, exp ) );
143 1150836 : tmp = mult( tmp, tmp ); /* energy of innovative code excitation */
144 1150836 : ener2 = mult( ener2, tmp );
145 1150836 : exp2 = sub( exp2, add( exp, exp ) );
146 :
147 1150836 : i = sub( exp1, exp2 );
148 : BASOP_SATURATE_WARNING_OFF_EVS
149 1150836 : ener1 = shr_sat( ener1, sub( 1, s_min( i, 0 ) ) );
150 1150836 : ener2 = shr_sat( ener2, add( s_max( 0, i ), 1 ) );
151 : BASOP_SATURATE_WARNING_ON_EVS
152 1150836 : tmp = sub( ener1, ener2 );
153 1150836 : ener1 = add( add( ener1, ener2 ), 1 );
154 :
155 : /* find voice factor (1=voiced, -1=unvoiced) */
156 1150836 : exp = div_s( abs_s( tmp ), ener1 );
157 1150836 : IF( tmp < 0 )
158 : {
159 811336 : exp = negate( exp );
160 : }
161 1150836 : *voice_fac = exp;
162 1150836 : move16();
163 :
164 1150836 : IF( flag_tilt == 0 )
165 : {
166 : /* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */
167 :
168 : /* tilt_code = (float)(0.25*(1.0 + *voice_fac)) */
169 1150836 : tilt_code = mac_r( 8192L /*0.25.Q15*/ * 65536 /*1.Q16*/ - 0x8000 /*1.Q15*/, *voice_fac, 8192 /*0.25.Q15*/ ); /*Q15 */
170 : }
171 0 : ELSE IF( EQ_16( flag_tilt, 1 ) )
172 : {
173 : /*Between 0.25 (=unvoiced) and 0.5 (=voiced)*/
174 : // tilt_code = (float)(0.25f + (*voice_fac + 1.0f) * 0.125f);
175 0 : tilt_code = mac_r( 12288L /*0.375.Q15*/ * 65536 /*1.Q16*/ - 0x8000 /*1.Q15*/, *voice_fac, 4096 /*0.125.Q15*/ ); /*Q15 */
176 : }
177 : ELSE
178 : {
179 : /*Between 0.28 (=unvoiced) and 0.56 (=voiced)*/
180 : // tilt_code = (float)(0.28f + (*voice_fac + 1.0f) * 0.14f);
181 0 : tilt_code = mac_r( 13763L /*0.42.Q15*/ * 65536 /*1.Q16*/ - 0x8000 /*1.Q15*/, *voice_fac, 4588 /*0.14.Q15*/ ); /*Q15 */
182 : }
183 :
184 1150836 : return tilt_code;
185 : }
186 :
187 : /*-------------------------------------------------------------------*
188 : * Est_tilt2:
189 : *
190 : * Estimate spectral tilt based on the relative E of adaptive
191 : * and innovative excitations
192 : *-------------------------------------------------------------------*/
193 6376 : Word16 Est_tilt2( /* o : tilt of the code */
194 : const Word16 *exc, /* i : adaptive excitation vector Qx */
195 : const Word16 gain_pit, /* i : adaptive gain Q14 */
196 : const Word16 *code, /* i : algebraic exctitation vector Q9 */
197 : const Word32 gain_code, /* i : algebraic code gain Q16 */
198 : Word16 *voice_fac, /* o : voicing factor Q15 */
199 : const Word16 Q_exc /* i : Scaling factor of excitation Q0 */
200 : )
201 : {
202 : Word16 i, tmp, exp, ener1, exp1, ener2, exp2;
203 : Word32 L_tmp;
204 : Word16 tilt_code;
205 :
206 : /* Scale exc to avoid overflow */
207 6376 : ener1 = extract_h( Energy_scale( exc, L_SUBFR, Q_exc, &exp1 ) );
208 :
209 6376 : exp1 = sub( exp1, add( Q_exc, Q_exc ) );
210 6376 : L_tmp = L_mult( gain_pit, gain_pit ); /* energy of pitch excitation */
211 6376 : exp = norm_l( L_tmp );
212 6376 : tmp = extract_h( L_shl( L_tmp, exp ) );
213 6376 : ener1 = mult( ener1, tmp );
214 6376 : exp1 = sub( sub( exp1, exp ), 10 ); /* 10 -> gain_pit Q14 to Q9 */
215 :
216 6376 : ener2 = extract_h( Dot_product12( code, code, L_SUBFR, &exp2 ) );
217 :
218 6376 : exp = norm_l( gain_code );
219 6376 : tmp = extract_h( L_shl( gain_code, exp ) );
220 6376 : tmp = mult( tmp, tmp ); /* energy of innovative code excitation */
221 6376 : ener2 = mult( ener2, tmp );
222 6376 : exp2 = sub( exp2, add( exp, exp ) );
223 :
224 6376 : i = sub( exp1, exp2 );
225 6376 : ener1 = shr( ener1, sub( 1, s_min( i, 0 ) ) );
226 6376 : ener2 = shr( ener2, add( s_max( 0, i ), 1 ) );
227 :
228 6376 : tmp = sub( ener1, ener2 );
229 6376 : ener1 = add( add( ener1, ener2 ), 1 );
230 :
231 : /* find voice factor (1=voiced, -1=unvoiced) */
232 6376 : exp = div_s( abs_s( tmp ), ener1 );
233 6376 : IF( tmp < 0 )
234 : {
235 2584 : exp = negate( exp );
236 : }
237 6376 : *voice_fac = exp;
238 6376 : move16();
239 :
240 : /* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */
241 :
242 : /* tilt_code = (float)(0.25*(1.0 + *voice_fac)) */
243 6376 : tilt_code = mac_r( 8192L /*0.25.Q15*/ * 65536 /*1.Q16*/ - 0x8000 /*1.Q15*/, *voice_fac, 8192 /*0.25.Q15*/ );
244 :
245 6376 : return tilt_code;
246 : }
247 :
248 : /*---------------------------------------------------------*
249 : * Find voice factor and tilt code *
250 : *---------------------------------------------------------*/
251 14070 : void E_UTIL_voice_factor( Word16 *exc, /* i : pointer to the excitation frame Q_new */
252 : Word16 i_subfr, /* i : subframe index */
253 : Word16 *code, /* i : innovative codebook Q9 */
254 : Word16 gain_pit, /* i : adaptive codebook gain 1Q14 */
255 : Word32 gain_code, /* i : innovative cb. gain 15Q16 */
256 : Word16 *voice_fac, /* o : subframe voicing estimation Q15 */
257 : Word16 *tilt_code, /* o : tilt factor Q15 */
258 : Word16 L_subfr, /* i : subframe length */
259 : Word16 flag_tilt, /* i : Flag for triggering new voice factor tilt*/
260 : Word16 Q_new, /* i : excitation buffer format */
261 : Word16 shift /* i : scaling to get 12bit */
262 : )
263 : {
264 : Word16 i, e, e2, stmp, exp_ener, fac;
265 : Word32 ener, tmp, num;
266 : Word64 ener_64;
267 :
268 : BASOP_SATURATE_ERROR_ON_EVS;
269 :
270 :
271 14070 : IF( shift != 0 )
272 : {
273 1865 : fac = shl( 0x4000 /*1.Q14*/, add( 1, shift ) );
274 : /* energy of pitch excitation */
275 1865 : stmp = mult_r( exc[0 + i_subfr], fac ); /* remove fac bits */
276 1865 : ener_64 = W_mult0_16_16( stmp, stmp );
277 119360 : FOR( i = 1; i < L_subfr; i++ )
278 : {
279 117495 : stmp = mult_r( exc[i + i_subfr], fac ); /* remove fac bits */
280 117495 : ener_64 = W_mac0_16_16( ener_64, stmp, stmp );
281 : }
282 : }
283 : ELSE
284 : {
285 12205 : ener_64 = W_mult0_16_16( exc[0 + i_subfr], exc[0 + i_subfr] );
286 781120 : FOR( i = 1; i < L_subfr; i++ )
287 : {
288 768915 : ener_64 = W_mac0_16_16( ener_64, exc[i + i_subfr], exc[i + i_subfr] ); /* Q_new -> exponent = (15-Q_new)*2+1 */
289 : }
290 : }
291 14070 : ener = W_sat_l( ener_64 );
292 :
293 :
294 : /* exponent of ener: (2*(15-Q_new+shift)+1+2-exp_ener-2*e2) */
295 14070 : exp_ener = norm_l( ener );
296 14070 : if ( ener == 0 )
297 : {
298 8014 : exp_ener = 31;
299 8014 : move16();
300 : }
301 14070 : ener = L_shl( ener, exp_ener );
302 14070 : e2 = norm_s( gain_pit );
303 14070 : gain_pit = shl( gain_pit, e2 );
304 14070 : ener = Mpy_32_16_1( ener, mult_r( gain_pit, gain_pit ) );
305 :
306 :
307 : /* energy of innovative code excitation */
308 14070 : tmp = L_deposit_l( 1 );
309 :
310 914550 : FOR( i = 0; i < L_subfr; i++ )
311 : {
312 900480 : tmp = L_mac0( tmp, code[i], code[i] ); /* 6Q9 -> 13Q18 */
313 : }
314 : /* exponent of tmp: 2*(15-9)+1+2*(15-e)) */
315 14070 : e = norm_l( gain_code );
316 14070 : gain_code = L_shl( gain_code, e );
317 14070 : tmp = Mpy_32_32( tmp, Mpy_32_32( gain_code, gain_code ) );
318 :
319 : /* find voice factor (1=voiced, -1=unvoiced) */
320 : /*i = (2*(15-Q_new+shift)+1+2-exp_ener-2*e2) - (2*(15-9)+1 + 2*(15-e));*/
321 14070 : i = sub( sub( sub( sub( sub( 33, add( shift, shift ) ), add( Q_new, Q_new ) ), exp_ener ), add( e2, e2 ) ), sub( 43, add( e, e ) ) );
322 14070 : IF( i >= 0 )
323 : {
324 0 : ener = L_shr( ener, 1 );
325 0 : tmp = L_shr_sat( tmp, add( 1, i ) );
326 : }
327 : ELSE
328 : {
329 14070 : tmp = L_shr( tmp, 1 );
330 : BASOP_SATURATE_WARNING_OFF_EVS
331 14070 : ener = L_shr_sat( ener, sub( 1, i ) );
332 : BASOP_SATURATE_WARNING_ON_EVS
333 : }
334 :
335 14070 : *voice_fac = 0;
336 14070 : move16();
337 14070 : num = L_sub( ener, tmp );
338 14070 : IF( num != 0 )
339 : {
340 : BASOP_SATURATE_WARNING_OFF_EVS /* Allow saturating the voice factor because if has a limited range by definition. */
341 14070 : *voice_fac = divide3232( num, L_add( ener, tmp ) );
342 14070 : move16();
343 : BASOP_SATURATE_WARNING_ON_EVS
344 : }
345 :
346 : /* find tilt of code for next subframe */
347 14070 : IF( flag_tilt == 0 )
348 : {
349 : /*Between 0 (=unvoiced) and 0.5 (=voiced)*/
350 2672 : move16();
351 2672 : *tilt_code = add( 8192 /*0.25f Q15*/, mult_r( 8192 /*0.25f Q15*/, *voice_fac ) );
352 : }
353 11398 : ELSE IF( EQ_16( flag_tilt, 1 ) )
354 : {
355 : /*Between 0.25 (=unvoiced) and 0.5 (=voiced)*/
356 5028 : move16();
357 5028 : *tilt_code = add( mult_r( 4096 /*0.125f Q15*/, *voice_fac ), 12288 /*0.125f+0.25f Q15*/ );
358 : }
359 : ELSE
360 : {
361 : /*Between 0.28 (=unvoiced) and 0.56 (=voiced)*/
362 6370 : move16();
363 6370 : *tilt_code = add( mult_r( 4588 /*0.14f Q15*/, *voice_fac ), 13763 /*0.14f+0.28f Q15*/ );
364 : }
365 : BASOP_SATURATE_ERROR_OFF_EVS;
366 14070 : }
|