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_com_fx.h" /* Static table prototypes */
8 : #include "rom_com.h" /* Static table prototypes */
9 : #include "rom_enc.h" /* Static table prototypes */
10 : #include "prot_fx.h" /* Function prototypes */
11 : #include "prot_fx_enc.h" /* Function prototypes */
12 : //#include "basop_mpy.h"
13 :
14 : /*-------------------------------------------------------------------*
15 : * Local constants
16 : *-------------------------------------------------------------------*/
17 :
18 : #define NMAX 8 /* Control of the routine's complexity */
19 : /* #define FAC_DELTA 16.0f */
20 : #define SFAC_DELTA 11
21 :
22 : /*-------------------------------------------------------------------*
23 : * Local functions
24 : *-------------------------------------------------------------------*/
25 :
26 : static Word16 cod_2pos_fx( const Word16 ind1, const Word16 ind2, const Word16 sign1, const Word16 sign2, const Word16 n );
27 :
28 : static void gauss2v_fx( BSTR_ENC_HANDLE hBstr, const Word16 h[], const Word16 xn[], const Word16 dn[], Word16 code[], Word16 y1[], Word32 *gain, const Word16 lg, const Word16 shift, const Word16 Q_new, const Word16 nb_bits );
29 : /*-------------------------------------------------------------------*
30 : * Gaus_encode
31 : *
32 : * Encoder UnVoiced excitation coding using Gaussian codebooks
33 : * - ACELP quantized Gaussian excitation
34 : * - gain quantization
35 : * - Total excitation for UnVoiced coders
36 : * - Updates
37 : *-------------------------------------------------------------------*/
38 0 : Word16 gaus_encode_fx(
39 : Encoder_State *st_fx, /* i/o: encoder state structure */
40 : const Word16 i_subfr, /* i : subframe index Q0*/
41 : const Word16 *h1, /* i : weighted filter input response Q14*/
42 : const Word16 *xn, /* i : target vector Q12*/
43 : Word16 *exc, /* o : pointer to excitation signal frame Q_new*/
44 : Word16 *mem_w0, /* o : weighting filter denominator memory Q_new*/
45 : Word16 *clip_gain, /* o : memory of gain of pitch clipping algorithm [2.56x,Q14,Q8,Q0,Q14,Q14]*/
46 : Word16 *tilt_code, /* o : synthesis excitation spectrum tilt Q15*/
47 : Word16 *code, /* o : algebraic excitation Q9*/
48 : Word32 *gain_code, /* o : Code gain. Q16*/
49 : Word16 *y2, /* o : zero-memory filtered adaptive excitation Q9*/
50 : Word16 *gain_inov, /* o : innovation gain Q12*/
51 : Word16 *voice_fac, /* o : voicing factor Q15*/
52 : Word16 *gain_pit, /* o : adaptive excitation gain Q14*/
53 : const Word16 Q_new, /* i : scaling factor */
54 : const Word16 shift, /* i : scaling factor */
55 : Word32 *norm_gain_code /* o : normalized innovative cb. gain Q16*/
56 : )
57 : {
58 : Word16 nb_bits, idx;
59 0 : Word16 i = 0;
60 : Word32 Ltmp;
61 : Word16 dn[L_SUBFR], exp_code, gcode; /* Correlation between xn and h1 */
62 : Word16 exp, tmp, tmp_idx;
63 : #ifndef ISSUE_1867_replace_overflow_libenc
64 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
65 : Flag Overflow = 0;
66 : move32();
67 : #endif
68 : #endif
69 :
70 : /*----------------------------------------------------------------*
71 : * Encode gaussian excitation
72 : *----------------------------------------------------------------*/
73 :
74 : /* Correlation between target xn2[] and impulse response h1[] */
75 0 : corr_xh_fx( xn, dn, h1 );
76 :
77 0 : tmp_idx = shr( i_subfr, 6 );
78 0 : nb_bits = st_fx->acelp_cfg.fixed_cdk_index[tmp_idx]; /* Q0 */
79 0 : move16();
80 :
81 0 : gauss2v_fx( st_fx->hBstr, h1, xn, dn, code, y2, gain_code, L_SUBFR, shift, Q_new, shr( nb_bits, 1 ) );
82 :
83 : /*----------------------------------------------------------------*
84 : * Encode gaussian gain
85 : *----------------------------------------------------------------*/
86 :
87 : /* codeword energy computation */
88 0 : Ltmp = Dot_product12( code, code, L_SUBFR, &exp_code );
89 :
90 0 : exp_code = sub( exp_code, 18 + 6 ); /* exp: -18 (code in Q9), -6 (L_subfr = 64) */
91 0 : Ltmp = Isqrt_lc( Ltmp, &exp_code );
92 0 : *gain_inov = extract_h( L_shl_sat( Ltmp, sub( exp_code, 3 ) ) ); /* g_code_inov in Q12 */
93 :
94 0 : nb_bits = st_fx->acelp_cfg.gains_mode[tmp_idx]; /* Q0 */
95 0 : move16();
96 : /* low bound = -30; stepSize = 1.71875; inv_stepSize = 0.5818181 */
97 0 : idx = gain_enc_gaus_fx( gain_code, nb_bits, -7680, 28160, 19065 ); /* Q0 */
98 0 : push_indice( st_fx->hBstr, IND_GAIN, idx, nb_bits );
99 :
100 : /*----------------------------------------------------------------*
101 : * Total excitation for Unvoiced coders
102 : *----------------------------------------------------------------*/
103 : #ifdef ISSUE_1867_replace_overflow_libenc
104 0 : gcode = round_fx_sat( L_shl_sat( *gain_code, Q_new ) ); /* scaled gain_code with Qnew */
105 : #else
106 : gcode = round_fx_o( L_shl_o( *gain_code, Q_new, &Overflow ), &Overflow ); /* scaled gain_code with Qnew */
107 : #endif
108 0 : FOR( i = 0; i < L_SUBFR; i++ )
109 : {
110 0 : exc[i + i_subfr] = round_fx( L_shl( L_mult( gcode, code[i] ), 15 - 9 ) ); /* Q_new */
111 : }
112 :
113 : /*----------------------------------------------------------------*
114 : * Updates: last value of new target is stored in mem_w0
115 : *----------------------------------------------------------------*/
116 :
117 0 : Ltmp = L_mult( gcode, y2[L_SUBFR - 1] ); /* Q_new + 10 */
118 0 : Ltmp = L_shl( Ltmp, add( 5, shift ) ); /* Q_new + 15 + shift */
119 0 : Ltmp = L_negate( Ltmp );
120 0 : Ltmp = L_mac( Ltmp, xn[L_SUBFR - 1], 16384 ); /* Q_new + 15 + shift */
121 0 : Ltmp = L_shl_sat( Ltmp, sub( 1, shift ) ); /* Q_new + 16 */
122 0 : *mem_w0 = round_fx_sat( Ltmp ); /* Q_new */
123 0 : move16();
124 0 : init_gp_clip_fx( clip_gain ); /* reset pitch clipping parameters */
125 :
126 0 : *gain_pit = 0;
127 0 : *tilt_code = 0;
128 0 : move16(); /* purely unvoiced */
129 0 : *voice_fac = -32768; /* -1 in Q31 */
130 0 : move16(); /* purely unvoiced */
131 0 : exp = sub( norm_s( *gain_inov ), 1 );
132 0 : exp = s_max( exp, 0 );
133 :
134 0 : tmp = div_s( shr( 8192, exp ), *gain_inov );
135 0 : *norm_gain_code = L_shr( Mult_32_16( *gain_code, tmp ), sub( 1, exp ) ); /* Q16 */
136 0 : move16();
137 :
138 0 : return ( L_SUBFR << 6 );
139 : }
140 : /*-------------------------------------------------------------------*
141 : * gauss2v()
142 : *
143 : * encoder of Gaussian Codebook for unvoiced
144 : * consisting of addition of 2 Gaussian vectors
145 : *
146 : * One Gaussian vector of 192 values vectors delayed by 2
147 : *-------------------------------------------------------------------*/
148 0 : void gauss2v_fx(
149 : BSTR_ENC_HANDLE hBstr, /* i/o: encoder state structure */
150 : const Word16 h[], /* i : weighted LP filter impulse response Q15 */
151 : const Word16 xn[], /* i : target signal Q12 */
152 : const Word16 dn[], /* i : backward filtered target Q12 */
153 : Word16 code[], /* o : gaussian excitation Q9 */
154 : Word16 y1[], /* o : zero-memory filtered gauss. excitation Q8 */
155 : Word32 *gain, /* o : excitation gain. 32-bit number in Q16 */
156 : const Word16 lg, /* i : subframe size Q0 */
157 : const Word16 shift, /* i : Scaling factor Q0 */
158 : const Word16 Q_new, /* i : Scaling factor Q0 */
159 : const Word16 nb_bits /* i : nb ob bits per track (max 6) Q0 */
160 : )
161 : {
162 : Word16 i, j, ind1, ind2;
163 : Word16 nvec, step;
164 : Word32 cor, cora, dotprod;
165 : Word16 enerw;
166 : Word32 eneri, cor2;
167 : Word32 enerw32, cor2w32;
168 : Word16 *cpt1;
169 : Word16 *pt1, *pt2;
170 : Word32 max_val[NMAX + 1];
171 : Word16 *pos[NMAX + 1];
172 : Word32 sign[NMAX + 1];
173 : Word32 ener[NMAX + 1], corr[NMAX + 1], ener1;
174 : Word16 dico2[L_SUBFR * NMAX];
175 : Word16 exp_num;
176 : Word16 exp_den;
177 : Word16 Num;
178 : Word16 Den;
179 : Word32 GainPortion1;
180 : Word32 GainPortion2;
181 : Word32 cor_abs;
182 : Word16 cor_neg;
183 : Word16 div_result;
184 : Word32 ener_sqrt;
185 : Word32 Portion;
186 : Word16 sign1, sign2;
187 : Word16 enerw_norm, enerw_mantissa;
188 : Word16 cor2w_norm, cor2w_mantissa;
189 : Word16 eneri_norm, eneri_mantissa;
190 : Word16 cor2_norm, cor2_mantissa;
191 : Word16 difference_norm;
192 : Word32 cor32; /* 32-bit intermediate value*/
193 : Word16 hi1, lo1;
194 : Word16 update_best;
195 : Word16 idx;
196 : Word32 Lc0, Lc1, Lnum, Lden;
197 : Word16 gxx, gcc, index_delta, delta, m_sign, inv_delta;
198 : Word16 hg[190], Gaus_dico2[190];
199 : Word16 shiftP3;
200 : #ifndef ISSUE_1867_replace_overflow_libenc
201 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
202 : Flag Overflow = 0;
203 : move32();
204 : #endif
205 : #endif
206 :
207 : /*----------------------------------------------------------------*
208 : * Encode the tilt of gaussian excitation
209 : *----------------------------------------------------------------*/
210 :
211 : /* Compute spectral tilt of target */
212 0 : Lc0 = L_mult( xn[1], xn[1] ); /* Q25 */
213 0 : Lc1 = L_mult( xn[1], xn[0] ); /* Q25 */
214 0 : FOR( i = 2; i < L_SUBFR; i++ )
215 : {
216 : /* fc0 += xn[i]*xn[i] */
217 : /* fc1 += xn[i]*xn[i-1] */
218 0 : Lc0 = L_mac_sat( Lc0, xn[i], xn[i] ); /* Q25 */
219 0 : Lc1 = L_mac_sat( Lc1, xn[i], xn[i - 1] ); /* Q25 */
220 : }
221 : /* fgxx = fc1/fc0 */
222 0 : exp_num = sub( norm_l( Lc1 ), 1 );
223 0 : Num = extract_h( L_shl( Lc1, exp_num ) );
224 0 : m_sign = s_or( shr( Num, 16 ), 1 ); /* Remove sign */
225 0 : Num = abs_s( Num );
226 0 : Lc0 = L_max( Lc0, 1 );
227 0 : exp_den = norm_l( Lc0 );
228 0 : Den = extract_h( L_shl( Lc0, exp_den ) ); /* Q9 + exp_den */
229 0 : gxx = shr( div_s( Num, Den ), sub( exp_num, sub( exp_den, 2 ) ) ); /* Q13 */
230 0 : gxx = i_mult2( gxx, m_sign ); /* Apply sign */
231 :
232 0 : set16_fx( hg, 0, 190 ); /* Compute spectral tilt of filtered codebook */
233 0 : Copy( h, hg, L_SUBFR ); // Q15
234 0 : conv_fx( gaus_dico_fx, hg, Gaus_dico2, 190 ); // Q12
235 :
236 0 : Lc0 = L_mult( Gaus_dico2[1], Gaus_dico2[1] ); /* Q25 */
237 0 : Lc1 = L_mult( Gaus_dico2[1], Gaus_dico2[0] ); /* Q25 */
238 0 : FOR( i = 2; i < 190; i++ )
239 : {
240 : /* fc0 += fgaus_dico2[i]*fgaus_dico2[i] */
241 : /* fc1 += fgaus_dico2[i]*fgaus_dico2[i-1] */
242 0 : Lc0 = L_mac( Lc0, Gaus_dico2[i], Gaus_dico2[i] ); /* Q25 */
243 0 : Lc1 = L_mac( Lc1, Gaus_dico2[i], Gaus_dico2[i - 1] ); /* Q25 */
244 : }
245 :
246 : /* fgcc = fc1/fc0 */
247 :
248 0 : exp_num = sub( norm_l( Lc1 ), 1 );
249 0 : Num = extract_h( L_shl( Lc1, exp_num ) );
250 0 : m_sign = s_or( shr( Num, 16 ), 1 ); /* Remove sign */
251 0 : Num = abs_s( Num );
252 :
253 0 : Lc0 = L_max( Lc0, 1 );
254 0 : exp_den = norm_l( Lc0 );
255 0 : Den = extract_h( L_shl( Lc0, exp_den ) );
256 0 : gcc = shr( div_s( Num, Den ), sub( exp_num, sub( exp_den, 2 ) ) ); /* Q13 */
257 0 : gcc = i_mult2( gcc, m_sign ); /* Apply sign */
258 :
259 : /* fdelta = (1-fgcc*fgxx) / (2*fgcc+fgxx) Compute and quantize spectral tilt modification factor */
260 0 : Lnum = L_sub( 134217728L, L_mult( gcc, gxx ) ); /* Q30 */
261 0 : Lden = L_mac( L_mult( gxx, 8192 ), gcc, 16384 ); /* Q30 */
262 :
263 0 : exp_num = sub( norm_l( Lnum ), 1 );
264 0 : Num = extract_h( L_shl( Lnum, exp_num ) ); /* Q14 + exp_den */
265 0 : m_sign = s_or( shr( Num, 16 ), 1 ); /* Remove sign */
266 0 : Num = abs_s( Num );
267 :
268 0 : Lden = L_max( Lden, 1 );
269 0 : exp_den = norm_l( Lden );
270 0 : Den = extract_h( L_shl( Lden, exp_den ) );
271 :
272 0 : delta = shr_sat( div_s( Num, Den ), sub( exp_num, exp_den ) ); /* Q15 */
273 0 : delta = i_mult2( delta, m_sign ); /* Apply sign Q0*/
274 : /* index_delta = (short)(FAC_DELTA * fdelta) */
275 0 : index_delta = shr( delta, SFAC_DELTA );
276 :
277 : /* index_delta [0,7] */
278 0 : index_delta = s_max( index_delta, 0 );
279 0 : index_delta = s_min( index_delta, 7 );
280 :
281 : /* fdelta = STEP_DELTA * (float)index_delta */
282 0 : delta = shl( index_delta, 11 ); /* delta in Q15 */
283 :
284 0 : IF( delta > 0 ) /* Adapt spectral tilt of initial codebook */
285 : {
286 : /* Computation of 1 / (1+fdelta*fdelta) */
287 0 : inv_delta = inv_delta_tab[sub( index_delta, 1 )];
288 0 : move16(); /* Q15 */
289 :
290 : /* fgaus_dico2[0] = gaus_dico[0] */
291 0 : Gaus_dico2[0] = gaus_dico_fx[0]; /* Q12 */
292 0 : move16();
293 0 : FOR( i = 1; i < 190; i++ )
294 : {
295 : /* fgaus_dico2[i] = (gaus_dico[i] - fdelta*gaus_dico[i-1]) / (1 + fdelta*fdelta) */
296 0 : Lnum = L_msu( L_deposit_h( gaus_dico_fx[i] ), delta, gaus_dico_fx[i - 1] );
297 0 : Gaus_dico2[i] = round_fx( Mpy_32_16_1( Lnum, inv_delta ) );
298 : }
299 : }
300 : ELSE
301 : {
302 0 : FOR( i = 0; i < 190; i++ )
303 : {
304 : /* fgaus_dico2[i] = gaus_dico[i] */
305 0 : Gaus_dico2[i] = gaus_dico_fx[i]; /* Q12 */
306 0 : move16();
307 : }
308 : }
309 :
310 : /*----------------------------------------------------------------*
311 : * Initializations
312 : *----------------------------------------------------------------*/
313 :
314 0 : ind1 = 0;
315 0 : move16();
316 0 : ind2 = 0;
317 0 : move16();
318 :
319 0 : nvec = shl( 1, nb_bits );
320 0 : step = shr( 0x80, nb_bits );
321 :
322 : /*----------------------------------------------------------------*
323 : * dot product between dn and gaussian codevectors,
324 : * keep NMAX best vectors
325 : *----------------------------------------------------------------*/
326 :
327 0 : set32_fx( max_val, 0, NMAX + 1 );
328 0 : set32_fx( sign, 0, NMAX + 1 );
329 :
330 0 : FOR( i = 0; i < NMAX + 1; i++ )
331 : {
332 0 : pos[i] = (Word16 *) Gaus_dico2;
333 : }
334 :
335 0 : cpt1 = Gaus_dico2;
336 0 : move16();
337 :
338 0 : FOR( i = 0; i < nvec; i++ )
339 : {
340 : /* Dot product without normalization, because values are compared with each other afterwards. */
341 0 : cor = Dot_product( cpt1, dn, lg ); /* Q12 * Q12 * length of 64 + 1 left shift ==> Q31*/
342 0 : cora = L_abs( cor );
343 0 : j = NMAX - 1;
344 0 : move16();
345 :
346 : DO
347 : {
348 0 : IF( GE_32( cora, max_val[j] ) )
349 : {
350 0 : max_val[j + 1] = max_val[j];
351 0 : move32(); /*Q31*/
352 0 : pos[j + 1] = pos[j];
353 0 : move16(); /*Pointer*/
354 0 : sign[j + 1] = sign[j];
355 0 : move32(); /*Q31*/
356 0 : max_val[j] = cora;
357 0 : move32(); /*Q31*/
358 0 : pos[j] = cpt1;
359 0 : move16(); /*Pointer*/
360 0 : sign[j] = cor;
361 0 : move32(); /*Q31*/
362 : }
363 0 : j--;
364 : }
365 0 : WHILE( j >= 0 );
366 0 : cpt1 += step;
367 : }
368 :
369 : /*----------------------------------------------------------------*
370 : * filter selected vectors
371 : * put sign
372 : * compute energy
373 : *----------------------------------------------------------------*/
374 :
375 0 : pt1 = dico2;
376 0 : move16();
377 0 : FOR( i = 0; i < NMAX; i++ )
378 : {
379 : /* Input vector (pos) Q12, filter coefs in Q15, result in same format as input vector (Q12) */
380 0 : conv_fx( pos[i], h, pt1, lg );
381 :
382 : /* put sign and compute energy */
383 0 : IF( sign[i] < 0 )
384 : {
385 0 : FOR( j = 0; j < lg; j++ )
386 : {
387 0 : pt1[j] = negate( pt1[j] );
388 0 : move16(); /*Store into dico2*/
389 : }
390 : }
391 0 : ener[i] = Dot_product( pt1, pt1, lg ); /* pt1 points to filtered vector in dico2, in Q12 */
392 0 : move32(); /* Result is for Q12 * Q12 with length of 64 (6 bits) + 1 left shift => Q31 */
393 0 : corr[i] = Dot_product( pt1, xn, lg ); /* must be equal to sign[i] !! */
394 0 : move32(); /* pt1 points into dico2, in Q12. xn is in Q12 */
395 : /* Result is for Q12 * Q12 with length of 64 (6 bits) + 1 left shift => Q31 */
396 0 : pt1 += L_SUBFR;
397 : }
398 :
399 : /*------------------------------------------------------------------------*
400 : * try all combinations of NMAX best vectors
401 : *------------------------------------------------------------------------*/
402 :
403 0 : pt1 = dico2;
404 0 : move16();
405 :
406 : /* Initial values for search algorithm */
407 0 : enerw32 = L_deposit_h( 0x80 );
408 0 : cor2w32 = L_deposit_l( -2 );
409 0 : enerw_norm = norm_l( enerw32 );
410 0 : cor2w_norm = norm_l( cor2w32 );
411 0 : cor2w_mantissa = round_fx( L_shl( cor2w32, cor2w_norm ) );
412 0 : enerw_mantissa = round_fx( L_shl( enerw32, enerw_norm ) );
413 :
414 0 : FOR( i = 0; i < NMAX; i++ )
415 : {
416 0 : pt2 = pt1;
417 0 : move16();
418 0 : FOR( j = i; j < NMAX; j++ )
419 : {
420 0 : cor32 = L_add( corr[i], corr[j] ); /* Q31 */
421 :
422 0 : dotprod = Dot_product( pt1, pt2, lg ); /* Q12 * Q12 * length of 64 + 1 left shift ==> Q31 */
423 :
424 : /* eneri = round_fx(ener[i]) + round_fx(ener[j]) + 2*round_fx(dotprod) */
425 : /* Use ScalingShift to stay aligned with ener[] */
426 0 : eneri = L_shl( dotprod, 1 ); /* One left shift added for factor of 2 */
427 0 : eneri = L_add( ener[i], eneri );
428 0 : eneri = L_add( ener[j], eneri ); /* Q31 */
429 :
430 0 : lo1 = L_Extract_lc( cor32, &hi1 );
431 0 : cor2 = Sad_32( 0, hi1, lo1 ); /* Square + Add */
432 :
433 0 : cor2_norm = norm_l( cor2 );
434 0 : eneri_norm = norm_l( eneri );
435 : #ifdef ISSUE_1867_replace_overflow_libenc
436 0 : cor2_mantissa = round_fx_sat( L_shl_sat( cor2, cor2_norm ) );
437 0 : eneri_mantissa = round_fx_sat( L_shl_sat( eneri, eneri_norm ) );
438 : #else
439 : cor2_mantissa = round_fx_o( L_shl_o( cor2, cor2_norm, &Overflow ), &Overflow );
440 : eneri_mantissa = round_fx_o( L_shl_o( eneri, eneri_norm, &Overflow ), &Overflow );
441 : #endif
442 0 : difference_norm = sub( add( cor2_norm, enerw_norm ), add( cor2w_norm, eneri_norm ) );
443 :
444 0 : update_best = 0;
445 0 : move16();
446 :
447 0 : IF( difference_norm > 0 )
448 : {
449 0 : if ( GT_32( L_shr( L_mult( cor2_mantissa, enerw_mantissa ), difference_norm ),
450 : L_mult( cor2w_mantissa, eneri_mantissa ) ) )
451 : {
452 0 : update_best = 1;
453 0 : move16();
454 : }
455 : }
456 : ELSE
457 : {
458 0 : if ( L_msu_sat( L_shl( L_mult( cor2w_mantissa, eneri_mantissa ), difference_norm ), cor2_mantissa, enerw_mantissa ) < 0 ) // Saturation to be revisited
459 : {
460 0 : update_best = 1;
461 0 : move16();
462 : }
463 : }
464 0 : IF( update_best != 0 )
465 : {
466 0 : cor2w_mantissa = cor2_mantissa;
467 0 : move16();
468 0 : cor2w_norm = cor2_norm;
469 0 : move16();
470 0 : enerw_mantissa = eneri_mantissa;
471 0 : move16();
472 0 : enerw_norm = eneri_norm;
473 0 : move16();
474 0 : ind1 = i;
475 0 : move16();
476 0 : ind2 = j;
477 0 : move16();
478 : }
479 0 : pt2 += L_SUBFR;
480 : }
481 0 : pt1 += L_SUBFR;
482 : }
483 :
484 0 : enerw = round_fx( L_shr( L_deposit_h( enerw_mantissa ), enerw_norm ) );
485 :
486 : /*----------------------------------------------------------------*
487 : * Compute zero-memory filtered gauss. excitation y
488 : *----------------------------------------------------------------*/
489 :
490 0 : pt1 = dico2 + ind1 * L_SUBFR;
491 0 : move16(); /*Pointer arithmetic*/
492 0 : pt2 = dico2 + ind2 * L_SUBFR;
493 0 : move16();
494 :
495 0 : shiftP3 = add( shift, 3 );
496 0 : FOR( i = 0; i < lg; i++ )
497 : {
498 : /* Sum of 2 Q12 values, must give a Q1.8 */
499 0 : y1[i] = shr( add( pt1[i], pt2[i] ), shiftP3 );
500 0 : move16(); /* Compensate for "shift" */
501 : }
502 :
503 : /*----------------------------------------------------------------*
504 : * signs of vectors
505 : *----------------------------------------------------------------*/
506 :
507 0 : sign1 = ( -32768 );
508 0 : move16();
509 0 : if ( sign[ind1] >= 0 )
510 : {
511 0 : sign1 = 32767;
512 0 : move16();
513 : }
514 :
515 0 : sign2 = ( -32768 );
516 0 : move16();
517 0 : if ( sign[ind2] >= 0 )
518 : {
519 0 : sign2 = 32767;
520 0 : move16();
521 : }
522 :
523 : /*----------------------------------------------------------------*
524 : * Compute code
525 : *----------------------------------------------------------------*/
526 :
527 0 : pt1 = pos[ind1];
528 0 : move16(); /* Points to gaussian vector (gaus_dico_fx) in Q12 */
529 0 : pt2 = pos[ind2];
530 0 : move16(); /* Points to gaussian vector (gaus_dico_fx) in Q12 */
531 :
532 : /* sign[ind1] and sign[ind2] */
533 0 : FOR( i = 0; i < lg; i++ )
534 : {
535 : /* code[i]=(pt1[i]*sign1 + pt2[i]*sign2) /8 */
536 : /* Division by 8 (shift by 3) is for scaling (Q12 to Q0.9 output) */
537 0 : code[i] = shr( add( mult( pt1[i], sign1 ), mult( pt2[i], sign2 ) ), 3 );
538 0 : move16();
539 : }
540 :
541 0 : cor = L_add( corr[ind1], corr[ind2] );
542 :
543 : /*----------------------------------------------------------------*
544 : * Compute index
545 : *----------------------------------------------------------------*/
546 :
547 0 : i = (Word16) ( ( pos[ind1] - Gaus_dico2 ) / step ); /* Division by step can be replaced by shift. Pointer arithmetic */
548 0 : j = (Word16) ( ( pos[ind2] - Gaus_dico2 ) / step ); /* Division by step can be replaced by shift. Pointer arithmetic */
549 :
550 0 : idx = cod_2pos_fx( i, j, sign1, sign2, nvec ); /* Q0 */
551 0 : move16();
552 :
553 0 : push_indice( hBstr, IND_GAUS_CDBK_INDEX, idx, 2 * nb_bits + 1 );
554 0 : push_indice( hBstr, IND_TILT_FACTOR, index_delta, 3 );
555 :
556 : /*----------------------------------------------------------------*
557 : * Find quantized gain
558 : *----------------------------------------------------------------*/
559 :
560 : /* Divide cor/enerw: intermediate result stored into GainPortion1 */
561 0 : cor_neg = 0;
562 0 : move16();
563 0 : if ( cor < 0 ) /* Make Num positive. */
564 : {
565 0 : cor_neg = 1;
566 0 : move16();
567 : }
568 0 : cor_abs = L_abs( cor );
569 :
570 0 : exp_num = sub( norm_l( cor_abs ), 1 );
571 0 : exp_den = norm_s( enerw );
572 0 : Num = round_fx( L_shl( cor_abs, exp_num ) );
573 0 : Den = shl( enerw, exp_den );
574 :
575 0 : GainPortion1 = L_deposit_l( 0 ); /* Unexpected division by zero. Eliminate this gain contribution */
576 0 : IF( Den != 0 ) /* Protection against division by zero */
577 : {
578 0 : div_result = div_s( Num, Den ); /* Q15 */
579 0 : IF( cor_neg != 0 )
580 : {
581 0 : div_result = negate( div_result ); /* Retrieve sign */
582 : }
583 : /* Re-scale to compensate for normalization*/
584 0 : GainPortion1 = L_shr( L_deposit_l( div_result ), sub( exp_num, exp_den ) );
585 : }
586 :
587 0 : ener1 = Dot_product( xn, xn, lg ); /* Q12 * Q12 * length of 64 + 1 left shift ==> Q31 */
588 :
589 0 : exp_num = sub( norm_s( enerw ), 1 );
590 0 : exp_den = norm_l( ener1 );
591 0 : Num = shl( enerw, exp_num );
592 0 : Den = round_fx_sat( L_shl_sat( ener1, exp_den ) );
593 0 : GainPortion2 = L_deposit_l( 0 ); /* Unexpected division by zero. Eliminate this gain contribution */
594 0 : IF( Den != 0 ) /* Protection against division by zero */
595 : {
596 0 : div_result = div_s( Num, Den ); /* Q15 */
597 :
598 : /* Re-scale to compensate for normalization*/
599 0 : GainPortion2 = L_shr_sat( L_deposit_l( div_result ), sub( exp_num, exp_den ) );
600 : }
601 :
602 0 : ener_sqrt = Isqrt( L_shl_sat( GainPortion2, 1 ) ); /* Make value a Q16 prior to division (align on power of 4) */
603 0 : ener_sqrt = L_shr( ener_sqrt, 8 ); /* Left-shift Q23 result to make a Q15 result */
604 :
605 0 : Portion = Mult_32_16( GainPortion1, 19661 ); /* Performs GainPortion1*.6 */
606 0 : Portion = Madd_32_16( Portion, ener_sqrt, 13107 ); /* Performs ener_sqrt*.4 */
607 :
608 : /* Gain must be output in a 32-bit variable as a Q16 */
609 : /* Compensate for Q_new */
610 : #ifdef ISSUE_1867_replace_overflow_libenc
611 0 : *gain = L_shl_sat( Portion, sub( 13, Q_new ) ); /* Q16 */
612 : #else
613 : *gain = L_shl_o( Portion, sub( 13, Q_new ), &Overflow ); /* Q16 */
614 : #endif
615 0 : move32();
616 :
617 0 : return;
618 : }
619 : /*---------------------------------------------------------------------*
620 : * Put selected codevector positions and signs into quantization index
621 : *---------------------------------------------------------------------*/
622 0 : static Word16 cod_2pos_fx( /* o : codebook quantization index */
623 : const Word16 ind1, /* i : index of 1st gaussian vector Q0*/
624 : const Word16 ind2, /* i : index of 2nd gaussian vector Q0*/
625 : const Word16 sign1, /* i : sign of 1st gaussian vector Qx*/
626 : const Word16 sign2, /* i : sign of 2nd gaussian vector Qx*/
627 : const Word16 n /* i : nb. of codebook vectors Q0*/
628 : )
629 : {
630 : Word16 i1, i2, index, s1, s2;
631 0 : s1 = 1;
632 0 : move16();
633 :
634 0 : if ( sign1 > 0 )
635 : {
636 0 : s1 = 0;
637 0 : move16();
638 : }
639 0 : s2 = 1;
640 0 : move16();
641 0 : if ( sign2 > 0 )
642 : {
643 0 : s2 = 0;
644 0 : move16();
645 : }
646 :
647 0 : IF( EQ_16( s1, s2 ) )
648 : {
649 0 : IF( LE_16( ind1, ind2 ) )
650 : {
651 0 : i1 = ind1; /* Q0 */
652 0 : move16();
653 0 : i2 = ind2; /* Q0 */
654 0 : move16();
655 : }
656 : ELSE
657 : {
658 0 : i1 = ind2; /* Q0 */
659 0 : move16();
660 0 : i2 = ind1; /* Q0 */
661 0 : move16();
662 : }
663 : }
664 : ELSE
665 : {
666 0 : IF( GT_16( ind1, ind2 ) )
667 : {
668 0 : i1 = ind1; /* Q0 */
669 0 : move16();
670 0 : i2 = ind2; /* Q0 */
671 0 : move16();
672 : }
673 : ELSE
674 : {
675 0 : i1 = ind2; /* Q0 */
676 0 : move16();
677 0 : i2 = ind1; /* Q0 */
678 0 : move16();
679 0 : s1 = s2;
680 0 : move16();
681 : }
682 : }
683 :
684 0 : index = extract_l( L_mult( i1, n ) );
685 0 : index = add( index, shl( i2, 1 ) );
686 0 : index = add( index, s1 );
687 :
688 0 : return index;
689 : }
|