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 "basop_util.h"
9 : #include "prot_fx.h" /* Function prototypes */
10 : #include "prot_fx_enc.h" /* Function prototypes */
11 :
12 : /*-------------------------------------------------------------------*
13 : * Local constants
14 : *-------------------------------------------------------------------*/
15 :
16 : #define GAIN_PIT_MAX 19661
17 :
18 :
19 : /*-------------------------------------------------------------------*
20 : * Local function prototypes
21 : *-------------------------------------------------------------------*/
22 :
23 : static Word16 adpt_enr_fx( const Word16 codec_mode, const Word16 *exc, const Word16 *h1, Word16 *y1, const Word16 L_subfr, Word16 *gain, Word16 *g_corr, const Word16 clip_gain, const Word16 *xn, Word16 *xn2, Word16 *exp_ener, Word16 use_prev_sf_pit_gain );
24 :
25 : /*-------------------------------------------------------------------*
26 : * function lp_filt_exc_enc_fx()
27 : *
28 : * Low-pass filtering of the adaptive excitation
29 : * Innovation target construction
30 : * Gain quantization limitation
31 : *-------------------------------------------------------------------*/
32 :
33 727882 : Word16 lp_filt_exc_enc_fx(
34 : const Word16 codec_mode, /* i : MODE1 or MODE2 Q0 */
35 : const Word16 coder_type, /* i : coding type Q0 */
36 : const Word16 i_subfr, /* i : subframe index Q0 */
37 : Word16 *exc, /* i/o: pointer to excitation signal frame Q_new */
38 : const Word16 *h1, /* i : weighted filter input response Q(14+shift) */
39 : const Word16 *xn, /* i : target vector Q_new-1+shift */
40 : Word16 *y1, /* o : zero-memory filtered adaptive excitation Q_new-1+shift */
41 : Word16 *xn2, /* o : target vector for innovation search Q_new-1+shift */
42 : const Word16 L_subfr, /* i : length of vectors for gain quantization Q0 */
43 : const Word16 L_frame, /* i : frame size Q0 */
44 : Word16 *g_corr, /* o : ACELP correlation values mant/exp */
45 : const Word16 clip_gain, /* i : adaptive gain clipping flag Q0 */
46 : Word16 *gain_pit, /* o : adaptive excitation gain Q14 */
47 : Word16 *lp_flag /* i/o: mode selection Q0 */
48 : )
49 : {
50 : Word16 gain1, gain2, g_corr2[4], exc_tmp[5 * L_SUBFR], xn2_tmp[5 * L_SUBFR];
51 : Word16 y1_tmp[5 * L_SUBFR];
52 : Word16 select, i, exp_ener, exp_ener1;
53 : Word16 wtmp, wtmp1;
54 : Word32 Ltmp;
55 :
56 727882 : Word16 use_prev_sf_pit_gain = 0; // Q0
57 727882 : move16();
58 :
59 727882 : gain1 = 0;
60 727882 : move16();
61 727882 : gain2 = 0;
62 727882 : move16();
63 :
64 : /*----------------------------------------------------------------*
65 : * Find the target energy if the adaptive exc. is not filtered
66 : *----------------------------------------------------------------*/
67 727882 : test();
68 727882 : IF( EQ_16( codec_mode, MODE2 ) && EQ_16( coder_type, 100 ) )
69 : {
70 0 : use_prev_sf_pit_gain = 1; // Q0
71 0 : move16();
72 : }
73 727882 : exp_ener = 0;
74 727882 : move16();
75 727882 : wtmp = 0;
76 727882 : move16();
77 727882 : test();
78 727882 : IF( EQ_16( *lp_flag, FULL_BAND ) || EQ_16( *lp_flag, NORMAL_OPERATION ) )
79 : {
80 683264 : wtmp = adpt_enr_fx( codec_mode, &exc[i_subfr], h1, y1, L_subfr, &gain1, g_corr, clip_gain, xn, xn2, &exp_ener, use_prev_sf_pit_gain ); // exp_ener
81 683264 : move16();
82 : }
83 :
84 : /*----------------------------------------------------------------*
85 : * Filter the adaptive excitation
86 : * Find the target energy if the adapt. exc. is filtered
87 : *----------------------------------------------------------------*/
88 :
89 727882 : exp_ener1 = 0;
90 727882 : move16();
91 727882 : wtmp1 = 0;
92 727882 : move16();
93 727882 : test();
94 727882 : IF( ( ( *lp_flag == LOW_PASS ) ) || ( EQ_16( *lp_flag, NORMAL_OPERATION ) ) )
95 : {
96 657282 : test();
97 657282 : IF( EQ_16( codec_mode, MODE2 ) && EQ_16( L_frame, L_FRAME16k ) )
98 : {
99 0 : FOR( i = 0; i < L_subfr; i++ )
100 : {
101 0 : Ltmp = L_mult( 6881, exc[i - 1 + i_subfr] ); /* constants in Q15 */
102 0 : Ltmp = L_mac( Ltmp, 19005, exc[i + i_subfr] );
103 0 : Ltmp = L_mac( Ltmp, 6881, exc[i + 1 + i_subfr] );
104 0 : exc_tmp[i] = round_fx( Ltmp );
105 0 : move16();
106 : }
107 : }
108 : ELSE
109 : {
110 42723330 : FOR( i = 0; i < L_subfr; i++ )
111 : {
112 42066048 : Ltmp = L_mult( 5898, exc[i - 1 + i_subfr] ); /* constants in Q15 */
113 42066048 : Ltmp = L_mac( Ltmp, 20972, exc[i + i_subfr] );
114 42066048 : Ltmp = L_mac( Ltmp, 5898, exc[i + 1 + i_subfr] );
115 42066048 : exc_tmp[i] = round_fx( Ltmp );
116 42066048 : move16();
117 : }
118 : }
119 :
120 657282 : wtmp1 = adpt_enr_fx( codec_mode, exc_tmp, h1, y1_tmp, L_subfr, &gain2, g_corr2, clip_gain, xn, xn2_tmp, &exp_ener1, use_prev_sf_pit_gain ); // exp_ener1
121 : }
122 :
123 727882 : if ( LT_16( exp_ener, exp_ener1 ) )
124 : {
125 52845 : wtmp = shr( wtmp, 1 ); // exp_ener + 1
126 : }
127 :
128 727882 : if ( GT_16( exp_ener, exp_ener1 ) )
129 : {
130 93382 : wtmp1 = shr( wtmp1, 1 ); // exp_ener1 + 1
131 : }
132 :
133 : /*-----------------------------------------------------------------*
134 : * use the best prediction (minimize quadratic error)
135 : *-----------------------------------------------------------------*/
136 :
137 727882 : test();
138 727882 : test();
139 727882 : IF( ( ( LT_16( wtmp1, wtmp ) ) && ( EQ_16( *lp_flag, NORMAL_OPERATION ) ) ) || ( ( *lp_flag == LOW_PASS ) ) )
140 : {
141 : /* use the LP filter for pitch excitation prediction */
142 445835 : select = LOW_PASS;
143 445835 : move16();
144 445835 : Copy( exc_tmp, &exc[i_subfr], L_subfr ); // Q_new
145 445835 : Copy( y1_tmp, y1, L_subfr ); // Q_new-1+shift
146 445835 : Copy( xn2_tmp, xn2, L_subfr ); // Q_new-1+shift
147 :
148 445835 : IF( use_prev_sf_pit_gain == 0 )
149 : {
150 445835 : *gain_pit = gain2; // Q14
151 445835 : move16();
152 445835 : g_corr[0] = g_corr2[0];
153 445835 : move16();
154 445835 : g_corr[1] = g_corr2[1];
155 445835 : move16();
156 445835 : g_corr[2] = g_corr2[2];
157 445835 : move16();
158 445835 : g_corr[3] = g_corr2[3];
159 445835 : move16();
160 : }
161 : }
162 : ELSE
163 : {
164 : /* no LP filter used for pitch excitation prediction */
165 282047 : select = FULL_BAND;
166 282047 : move16();
167 282047 : IF( use_prev_sf_pit_gain == 0 )
168 : {
169 282047 : *gain_pit = gain1; // Q14
170 282047 : move16();
171 : }
172 : }
173 :
174 727882 : return select;
175 : }
176 :
177 : /*-------------------------------------------------------------------*
178 : * adpt_enr_fx()
179 : *
180 : * Find adaptive excitation energy
181 : * This serves to decide about the filtering of the adaptive excitation
182 : *-------------------------------------------------------------------*/
183 :
184 : /* o : adaptive excitation energy mant */
185 1340546 : static Word16 adpt_enr_fx(
186 : const Word16 codec_mode, /* i : MODE1 or MODE2 */
187 : const Word16 *exc, /* i : excitation vector Q_new */
188 : const Word16 *h1, /* i : impuls response Q15 */
189 : Word16 *y1, /* o : zero-memory filtered adpt. excitation 12 bits */
190 : const Word16 L_subfr, /* i : vector length */
191 : Word16 *gain, /* o : subframe adaptive gain Q14 */
192 : Word16 *g_corr, /* o : correlations for adptive gain mant/exp */
193 : const Word16 clip_gain, /* i : adaptive gain clipping flag Q0 */
194 : const Word16 *xn, /* i : adaptive codebook target 12 bits Q_new-1+shift*/
195 : Word16 *xn2, /* o : algebraic codebook target 12 bits Q_new-1+shift*/
196 : Word16 *exp_ener, /* o : adaptive excitation energy exp */
197 : Word16 use_prev_sf_pit_gain /* i : flag to use prev sf pitch gain or not */
198 : )
199 : {
200 : Word16 ener, i;
201 : Word16 exc_tmp[L_FRAME16k], xn_tmp[L_FRAME16k];
202 : Word32 Ltmp;
203 1340546 : Flag Overflow = 0;
204 :
205 1340546 : Overflow = 0;
206 1340546 : move16();
207 1340546 : Overflow =
208 1340546 : conv_fx( exc, h1, y1, L_subfr );
209 :
210 1340546 : IF( use_prev_sf_pit_gain == 0 )
211 : {
212 1340546 : *gain = corr_xy1_fx( xn, y1, g_corr, L_subfr, codec_mode == MODE2, &Overflow );
213 1340546 : move16();
214 :
215 1340546 : test();
216 1340546 : IF( GT_16( L_subfr, L_SUBFR ) && Overflow )
217 : {
218 436908 : FOR( i = 0; i < L_subfr; i++ )
219 : {
220 435328 : exc_tmp[i] = mult( exc[i], 8192 /*0.25.Q15*/ ); // Q_new
221 435328 : move16();
222 435328 : xn_tmp[i] = mult( xn[i], 8192 /*0.25.Q15*/ ); // Q_new
223 435328 : move16();
224 : }
225 1580 : Overflow = 0;
226 :
227 1580 : conv_fx( exc_tmp, h1, y1, L_subfr );
228 1580 : *gain = corr_xy1_fx( xn_tmp, y1, g_corr, L_subfr, codec_mode == MODE2, &Overflow );
229 1580 : move16();
230 : }
231 :
232 : /* clip gain, if necessary to avoid problems at decoder */
233 1340546 : test();
234 1340546 : if ( EQ_16( clip_gain, 1 ) && GT_16( *gain, 15565 ) ) /* constant in Q14 */
235 : {
236 13318 : *gain = 15565; // 0.95.Q14
237 13318 : move16();
238 : }
239 :
240 1340546 : test();
241 1340546 : IF( EQ_16( clip_gain, 2 ) && GT_16( *gain, 10650 ) ) // 0.65.Q14
242 : {
243 4468 : *gain = 10650; // 0.65.Q14
244 4468 : move16();
245 : }
246 : }
247 :
248 : /* find energy of new target xn2[] */
249 1340546 : updt_tar_fx( xn, xn2, y1, *gain, L_subfr );
250 :
251 1340546 : IF( GT_16( L_subfr, L_SUBFR ) )
252 : {
253 : /* could possibly happen in GSC */
254 16340 : Ltmp = Calc_Energy_Autoscaled( xn2, 0, L_subfr, exp_ener );
255 16340 : i = norm_l( Ltmp );
256 16340 : ener = extract_h( L_shl( Ltmp, i ) ); // exp_ener
257 16340 : i = sub( 31, i );
258 16340 : *exp_ener = sub( i, *exp_ener );
259 16340 : move16();
260 : }
261 : ELSE
262 : {
263 1324206 : ener = extract_h( Dot_product12( xn2, xn2, L_SUBFR, exp_ener ) ); // Q15
264 : }
265 :
266 1340546 : return ener;
267 : }
268 :
269 : /*-------------------------------------------------------------------*
270 : * corr_xy1()
271 : *
272 : * Find the correlations between the target xn[] and the filtered adaptive
273 : * codebook excitation y1[]. ( <y1,y1> and -2<xn,y1> )
274 : *-------------------------------------------------------------------*/
275 :
276 : /* o : pitch gain (0..GAIN_PIT_MAX) */
277 1450516 : Word16 corr_xy1_fx(
278 : const Word16 xn_1[], /* i : target signal Q_new*/
279 : const Word16 y1_1[], /* i : filtered adaptive codebook excitation 12 bits*/
280 : Word16 g_corr[], /* o : correlations <y1,y1> and -2<xn,y1> mant/exp*/
281 : const Word16 L_subfr, /* i : vector length */
282 : const Word16 norm_flag, /* i : flag for constraining pitch contribution */
283 : Flag *Overflow_out /* o : propagating the Overflow flag to upper level */
284 : )
285 : {
286 : Word16 i;
287 : Word16 tmp, xx, xy, yy, exp_xy, exp_xx, exp_yy, exp_div, gain, gain_p_snr;
288 : Word32 Ltmp1, Ltmp2;
289 : Word16 xn[L_FRAME16k], y1[L_FRAME16k];
290 1450516 : Flag Overflow = 0;
291 :
292 : /*----------------------------------------------------------------*
293 : * Find the ACELP correlations and the pitch gain
294 : *----------------------------------------------------------------*/
295 :
296 : /* Compute scalar product <y1[],y1[]> */
297 1450516 : Copy( xn_1, xn, L_subfr ); // Q_new
298 1450516 : Copy( y1_1, y1, L_subfr );
299 1450516 : Overflow = 0;
300 1450516 : move16();
301 1450516 : Ltmp1 = Dot_product12_o( y1, y1, L_subfr, &exp_yy, &Overflow );
302 1450516 : *Overflow_out |= Overflow;
303 1450516 : move16();
304 1450516 : IF( Overflow )
305 : {
306 1350958 : FOR( i = 0; i < L_subfr; i++ )
307 : {
308 1334976 : xn[i] = mult_r( xn_1[i], 4096 /*0.125.Q15*/ ); // Q-new
309 1334976 : move16();
310 1334976 : y1[i] = mult_r( y1_1[i], 4096 /*0.125.Q15*/ );
311 1334976 : move16();
312 : }
313 :
314 15982 : Ltmp1 = Dot_product12( y1, y1, L_subfr, &exp_yy );
315 15982 : exp_yy = add( exp_yy, 6 );
316 15982 : yy = extract_h( Ltmp1 );
317 :
318 : /* Compute scalar product <xn[],y1[]> */
319 15982 : Ltmp2 = Dot_product12( xn, y1, L_subfr, &exp_xy );
320 15982 : xy = extract_h( Ltmp2 );
321 15982 : exp_xy = add( exp_xy, 6 );
322 :
323 15982 : g_corr[0] = yy;
324 15982 : move16();
325 15982 : g_corr[1] = exp_yy;
326 15982 : move16();
327 : /* -2.0*temp1 + 0.01 is done in Gain_enc_2 function */
328 15982 : g_corr[2] = xy;
329 15982 : move16();
330 15982 : g_corr[3] = exp_xy;
331 15982 : move16();
332 : }
333 : ELSE
334 : {
335 1434534 : yy = extract_h( Ltmp1 ); // exp_yy
336 : /* Ltmp1 = L_shr(Ltmp1, sub(30, exp_yy));*/
337 :
338 : /* Compute scalar product <xn[],y1[]> */
339 1434534 : Ltmp2 = Dot_product12_o( xn, y1, L_subfr, &exp_xy, &Overflow );
340 1434534 : *Overflow_out |= Overflow;
341 1434534 : move16();
342 1434534 : xy = extract_h( Ltmp2 );
343 : /* Ltmp2 = L_shr(Ltmp2, sub(30, exp_xy));*/
344 :
345 1434534 : g_corr[0] = yy;
346 1434534 : move16();
347 1434534 : g_corr[1] = exp_yy;
348 1434534 : move16();
349 : /* -2.0*temp1 + 0.01 is done in Gain_enc_2 function*/
350 1434534 : g_corr[2] = xy; // exp_xy
351 1434534 : move16();
352 1434534 : g_corr[3] = exp_xy;
353 1434534 : move16();
354 : }
355 :
356 : /* find pitch gain and bound it by [0,GAIN_PIT_MAX] */
357 1450516 : test();
358 1450516 : IF( xy >= 0 && NE_16( s_or( yy, xy ), 16384 ) )
359 : {
360 : /* compute gain = xy/yy */
361 1377533 : xy = shr( xy, 1 ); /* be sure that xy < yy */
362 1377533 : gain = div_s( xy, yy ); // Q15
363 1377533 : i = sub( exp_xy, exp_yy );
364 1377533 : gain = shl_o( gain, i, &Overflow ); /* saturation can occur here */
365 1377533 : *Overflow_out |= Overflow;
366 1377533 : move16();
367 :
368 1377533 : gain = s_max( gain, 0 );
369 1377533 : gain = s_min( gain, GAIN_PIT_MAX ); /* 1.2 in Q14 */
370 : }
371 : ELSE
372 : {
373 72983 : gain = 0;
374 72983 : move16();
375 : }
376 :
377 : /* Limit the energy of pitch contribution */
378 1450516 : IF( norm_flag )
379 : {
380 : /*that part of code seems never used*/
381 : /* Compute scalar product <xn[],xn[]> */
382 0 : xx = round_fx( Dot_product12_offs( xn, xn, L_subfr, &exp_xx, 1 ) );
383 :
384 : /* gain_p_snr = sqrt(<xn,xn>/<y1,y1>) */
385 0 : tmp = BASOP_Util_Divide1616_Scale( xx, yy, &exp_div );
386 0 : exp_xx = add( sub( exp_xx, exp_yy ), exp_div );
387 0 : tmp = Sqrt16( tmp, &exp_xx ); // exp_xx
388 :
389 : /* Note: shl works as shl or shr. */
390 0 : exp_xx = sub( exp_xx, 1 );
391 : BASOP_SATURATE_WARNING_OFF_EVS
392 0 : gain_p_snr = round_fx_sat( L_shl_sat( Mpy_32_16_1( 1717986944l /*ACELP_GAINS_CONST Q31*/, tmp ), exp_xx ) );
393 : BASOP_SATURATE_WARNING_ON_EVS
394 :
395 0 : gain = s_min( gain, gain_p_snr ); // Q14
396 : }
397 :
398 1450516 : return gain; // Q14
399 : }
|