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"
7 : //#include "prot_fx.h"
8 : #include "basop_util.h"
9 : #include "options.h"
10 : #include "rom_enc.h"
11 : #include "prot_fx.h" /* Function prototypes */
12 : #include "prot_fx_enc.h" /* Function prototypes */
13 :
14 : /*--------------------------------------------------------------------------------------*
15 : * Local constant
16 : *--------------------------------------------------------------------------------------*/
17 :
18 : #define _1_Q11 ( 2048 /*1.0f Q11*/ ) /* 1.0f in 4Q11 */
19 : /*--------------------------------------------------------------------------------------*
20 : * E_ACELP_update_cor
21 : *--------------------------------------------------------------------------------------*/
22 8808176 : static void E_ACELP_update_cor_fx(
23 : const Word16 pos[], /* i Q0*/
24 : Word16 nb_pulse, /* i Q0*/
25 : const Word16 sign[], /* i Q13*/
26 : const Word16 R[], /* i Q9+scale*/
27 : const Word16 cor_in[], /* i Q9*/
28 : Word16 cor_out[] /* o Q9*/
29 : )
30 : {
31 : Word16 sign_x, sign_y;
32 : const Word16 *pRx, *pRy;
33 : Word16 i, tmp;
34 :
35 8808176 : IF( EQ_16( nb_pulse, 2 ) )
36 : {
37 : /* Update product of autocorrelation and already fixed pulses. with the
38 : * two newly found ones */
39 8152476 : sign_x = sign[pos[0]]; /*Q13*/
40 8152476 : move16();
41 8152476 : sign_y = sign[pos[1]]; /*Q13*/
42 8152476 : move16();
43 :
44 8152476 : IF( s_xor( sign_x, sign_y ) < 0 )
45 : {
46 4781875 : i = 1;
47 4781875 : move16();
48 4781875 : if ( sign_x > 0 )
49 : {
50 2393914 : i = 0;
51 2393914 : move16();
52 : }
53 4781875 : pRx = R - pos[i]; /*Q9+scale*/
54 4781875 : pRy = R - pos[1 - i]; /*Q9+scale*/
55 : /* different sign x and y */
56 310821875 : FOR( i = 0; i < L_SUBFR; i++ )
57 : {
58 306040000 : tmp = sub( pRx[i], pRy[i] );
59 306040000 : if ( cor_in != NULL )
60 : {
61 279042368 : tmp = add( tmp, cor_in[i] ); /* Q9 */
62 : }
63 306040000 : cor_out[i] = tmp; /* Q9 */
64 306040000 : move16();
65 : }
66 : }
67 : ELSE
68 : {
69 3370601 : pRx = R - pos[0]; /*Q9+scale*/
70 3370601 : pRy = R - pos[1]; /*Q9+scale*/
71 3370601 : IF( sign_x > 0 )
72 : {
73 : /* sign x and y is positive */
74 108755140 : FOR( i = 0; i < L_SUBFR; i++ )
75 : {
76 107081984 : tmp = add( pRx[i], pRy[i] );
77 107081984 : if ( cor_in != NULL )
78 : {
79 78882176 : tmp = add( tmp, cor_in[i] ); /* Q9 */
80 : }
81 107081984 : cor_out[i] = tmp; /* Q9 */
82 107081984 : move16();
83 : }
84 : }
85 : ELSE
86 : {
87 : /* sign x and y is negative */
88 110333925 : FOR( i = 0; i < L_SUBFR; i++ )
89 : {
90 108636480 : tmp = add( pRx[i], pRy[i] );
91 108636480 : if ( cor_in != NULL )
92 : {
93 81052160 : tmp = sub( cor_in[i], tmp ); /* Q9 */
94 : }
95 108636480 : if ( cor_in == NULL )
96 : {
97 27584320 : tmp = negate( tmp );
98 : }
99 108636480 : cor_out[i] = tmp; /* Q9 */
100 108636480 : move16();
101 : }
102 : }
103 : }
104 : }
105 655700 : ELSE IF( EQ_16( nb_pulse, 4 ) )
106 : {
107 655700 : E_ACELP_update_cor_fx( pos, 2, sign, R, cor_in, cor_out );
108 655700 : E_ACELP_update_cor_fx( pos + 2, 2, sign, R, cor_out, cor_out );
109 : }
110 : else
111 : {
112 0 : assert( !"Number of pulses not supported" );
113 : }
114 8808176 : }
115 : /*--------------------------------------------------------------------------------------*
116 : * E_ACELP_2pulse_searchx
117 : * Iterations: nb_pos_ix*16
118 : *--------------------------------------------------------------------------------------*/
119 6203311 : static void E_ACELP_2pulse_searchx_fx(
120 : const Word16 nb_pos_ix, /*Q0*/
121 : const Word16 track_x, /*Q0*/
122 : const Word16 track_y, /*Q0*/
123 : Word16 *R, /*Q9+scale*/
124 : Word16 *ps, /*Qdn*/
125 : Word16 *alp, /*Q6*/
126 : Word16 *ix, /*Q0*/
127 : Word16 *iy, /*Q0*/
128 : Word16 dn[], /*Qdn*/
129 : Word16 *dn2, /*Q0*/
130 : Word16 cor[], /*Q9*/
131 : Word16 sign[], /*Q13*/
132 : Word16 sign_val_2 /*Q15*/ )
133 : {
134 : Word16 i, x;
135 : Word32 y;
136 : Word16 *pos_x, pos[2];
137 : Word32 xy_save;
138 : Word16 ps0, ps1, alp2_16, ps2, sq;
139 : Word32 alp0, alp1, alp2, s;
140 : Word16 *pR, sgnx;
141 : Word16 sqk[2], alpk[2], ik;
142 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
143 6203311 : Flag Overflow = 0;
144 6203311 : move32();
145 : #endif
146 :
147 : /* eight dn2 max positions per track */
148 6203311 : pos_x = &dn2[( track_x * 8 )]; /*Qdn*/
149 6203311 : move16();
150 : /* save these to limit memory searches */
151 6203311 : ps0 = *ps; /*Qdn*/
152 6203311 : move16();
153 : /*alp0 = *alp + 2.0f*R[0]; move16();*/
154 6203311 : alp0 = L_deposit_h( *alp ); /* Qalp = Q_R*Q_signval */
155 6203311 : alp0 = L_mac_sat( alp0, R[0], sign_val_2 ); /*Q9+scale+Q15*/
156 :
157 : /* Ensure that in the loop below s > 0 in the first iteration, the actual values do not matter. */
158 6203311 : sqk[0] = -1;
159 6203311 : move16();
160 6203311 : alpk[0] = 1;
161 6203311 : move16();
162 6203311 : x = pos_x[0];
163 6203311 : move16();
164 6203311 : sgnx = sign[track_y]; /*Q13*/
165 6203311 : move16();
166 6203311 : if ( sign[x] < 0 )
167 : {
168 3069733 : sgnx = negate( sgnx );
169 : }
170 6203311 : if ( mac_ro( L_mac_o( L_mac_o( alp0, cor[x], sign[x], &Overflow ), cor[track_y], sign[track_y], &Overflow ), R[track_y - x], sgnx, &Overflow ) < 0 )
171 :
172 : {
173 0 : sqk[0] = 1;
174 0 : move16();
175 : }
176 6203311 : ik = 0;
177 6203311 : move16();
178 :
179 6203311 : xy_save = L_mac0( L_deposit_l( track_y ), track_x, L_SUBFR ); /*Q0*/
180 :
181 : /* loop track 1 */
182 45273236 : FOR( i = 0; i < nb_pos_ix; i++ )
183 : {
184 39069925 : x = pos_x[i]; /*Q0*/
185 39069925 : move16();
186 39069925 : sgnx = sign[x]; /*Q13*/
187 39069925 : move16();
188 : /* dn[x] has only nb_pos_ix positions saved */
189 : /*ps1 = ps0 + dn[x]; INDIRECT(1);ADD(1);*/
190 39069925 : ps1 = add_sat( ps0, dn[x] ); /*Qdn*/
191 : /*alp1 = alp0 + 2*sgnx*cor[x]; INDIRECT(1);MULT(1); MAC(1);*/
192 39069925 : alp1 = L_mac_o( alp0, cor[x], sgnx, &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
193 39069925 : pR = R - x; /*Q9+scale*/
194 :
195 664188725 : FOR( y = track_y; y < L_SUBFR; y += 4 )
196 : {
197 : /*ps2 = ps1 + dn[y]; ADD(1);*/
198 625118800 : ps2 = add_sat( ps1, dn[y] ); /*Qdn*/
199 : /*alp2 = alp1 + 2.0f*sign[y]*(cor[y] + sgnx*pR[y]); MULT(1); MAC(2);*/
200 : /*alp2 = alp1 + 2.0f*sign[y]*cor[y] + 2.0f*sign[y]*sgnx*pR[y]; MULT(1); MAC(2);*/
201 625118800 : assert( sign[y] == sign_val_2 || sign[y] == -sign_val_2 );
202 :
203 : /* Compiler warning workaround (not instrumented) */
204 625118800 : assert( sgnx != 0 );
205 625118800 : alp2_16 = 0;
206 :
207 625118800 : alp2 = L_mac_o( alp1, cor[y], sign[y], &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
208 625118800 : if ( sgnx > 0 )
209 : {
210 310299472 : alp2_16 = mac_ro( alp2, pR[y], sign[y], &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
211 : }
212 625118800 : if ( sgnx < 0 )
213 : {
214 314819328 : alp2_16 = msu_ro( alp2, pR[y], sign[y], &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
215 : }
216 625118800 : alpk[1 - ik] = alp2_16; /* Qalp */
217 625118800 : move16();
218 :
219 : /*sq = ps2 * ps2; MULT(1);*/
220 625118800 : sq = mult_r( ps2, ps2 ); /* (3+3)Q -> 6Q9 */
221 625118800 : sqk[1 - ik] = sq; /* Q9 */
222 625118800 : move16();
223 :
224 :
225 : /*s = (alpk * sq) - (sqk * alp2); MULT(1);MAC(1);*/
226 625118800 : s = L_msu_o( L_mult( alpk[ik], sq ), sqk[ik], alp2_16, &Overflow ); /* Q_sq = Q_sqk, Q_alpk = Q_alp */
227 625118800 : if ( s > 0 )
228 : {
229 35744593 : ik = sub( 1, ik );
230 : }
231 625118800 : if ( s > 0 )
232 : {
233 35744593 : xy_save = L_mac0( y, x, L_SUBFR ); /* Q0 */
234 : }
235 625118800 : assert( ( ( s >= 0 && i == 0 && y == track_y ) ) || ( y > track_y ) || ( i > 0 ) );
236 : }
237 : }
238 6203311 : ps1 = extract_l( xy_save );
239 6203311 : pos[1] = s_and( ps1, L_SUBFR - 1 );
240 6203311 : move16();
241 6203311 : pos[0] = lshr( ps1, 6 ); /* Q0 */
242 6203311 : move16();
243 : /* Update numerator */
244 6203311 : *ps = add( add( ps0, dn[pos[0]] ), dn[pos[1]] ); /* Qdn */
245 6203311 : move16();
246 :
247 : /* Update denominator */
248 6203311 : *alp = alpk[ik]; /* Q_alp */
249 6203311 : move16();
250 :
251 6203311 : E_ACELP_update_cor_fx( pos, 2, sign, R, cor, cor );
252 :
253 6203311 : *ix = pos[0]; /* Q0 */
254 6203311 : move16();
255 6203311 : *iy = pos[1]; /* Q0 */
256 6203311 : move16();
257 :
258 6203311 : assert( ( ( pos[0] & 3 ) == track_x ) && ( ( pos[1] & 3 ) == track_y ) ); /* sanity check */
259 6203311 : }
260 :
261 : /*--------------------------------------------------------------------------------------*
262 : * E_ACELP_1pulse_searchx
263 : *--------------------------------------------------------------------------------------*/
264 604108 : static void E_ACELP_1pulse_searchx_fx(
265 : UWord8 tracks[2], /*Q0*/
266 : Word16 *R, /*Q9+scale*/
267 : Word16 *ps, /* Qdn */
268 : Word16 *alp, /*Q6*/
269 : Word16 *ix, /*Q0*/
270 : Word16 dn[], /* Qdn */
271 : Word16 cor[], /* Q9 */
272 : Word16 sign[], /* Q13 */
273 : Word16 sign_val_1 /* Q15 */ )
274 : {
275 604108 : Word16 x, x_save = 0;
276 : Word16 ps0;
277 : Word32 alp0;
278 : Word16 ps1, sq;
279 : Word16 alp1;
280 : Word32 s;
281 : Word16 ntracks, t;
282 : Word16 sqk[2], alpk[2], ik;
283 604108 : move16();
284 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
285 604108 : Flag Overflow = 0;
286 604108 : move32();
287 : #endif
288 : /* save these to limit memory searches */
289 : /*alp0 = *alp + R[0]; INDIRECT(1);*/
290 604108 : ps0 = *ps; /* Qdn */
291 604108 : move16();
292 604108 : alp0 = L_deposit_h( *alp ); /* Q22 */
293 604108 : alp0 = L_mac( alp0, R[0], sign_val_1 ); /* Qalp = (Q_R=Q_cor)*Q_signval */
294 :
295 : /* Ensure that in the loop below s > 0 in the first iteration, the actual values do not matter. */
296 604108 : move16();
297 604108 : move16();
298 604108 : alpk[0] = 1;
299 604108 : sqk[0] = -1;
300 604108 : ik = 0;
301 604108 : move16();
302 604108 : if ( mac_ro( alp0, cor[tracks[0]], sign[tracks[0]], &Overflow ) < 0 )
303 : {
304 0 : sqk[0] = 1;
305 0 : move16();
306 : }
307 :
308 604108 : x_save = tracks[0]; /* Q0 */
309 604108 : move16();
310 :
311 604108 : ntracks = 1;
312 604108 : move16();
313 604108 : if ( NE_16( tracks[1], tracks[0] ) )
314 : {
315 158060 : ntracks = 2;
316 158060 : move16();
317 : }
318 1366276 : FOR( t = 0; t < ntracks; ++t )
319 : {
320 12956856 : FOR( x = tracks[t]; x < L_SUBFR; x += 4 )
321 : {
322 : /* ps1 = ps0 + dn[x]; ADD(1);*/
323 12194688 : ps1 = add( ps0, dn[x] );
324 : /* alp1 = alp0 + 2*sign[x]*cor[x]; MAC(1); MULT(1);*/
325 12194688 : assert( sign[x] == sign_val_1 << 1 || sign[x] == -( sign_val_1 << 1 ) );
326 12194688 : alp1 = mac_ro( alp0, cor[x], sign[x], &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
327 12194688 : alpk[1 - ik] = alp1; /* Qalp */
328 12194688 : move16();
329 :
330 :
331 : /*sq = ps1 * ps1; MULT(1);*/
332 12194688 : sq = mult_r( ps1, ps1 ); /* 6Q9 */
333 12194688 : sqk[1 - ik] = sq; /* Q9 */
334 12194688 : move16();
335 :
336 : /*s = (alpk[ik] * sq) - (sqk[ik] * alp1); MULT(1);MAC(1);*/
337 12194688 : s = L_msu_o( L_mult_o( alpk[ik], sq, &Overflow ), sqk[ik], alp1, &Overflow ); /* Q9+Qalp+1 */
338 12194688 : if ( s > 0 )
339 : {
340 2201028 : ik = sub( 1, ik );
341 : }
342 12194688 : if ( s > 0 )
343 : {
344 2201028 : x_save = x;
345 2201028 : move16();
346 : }
347 12194688 : assert( t > 0 || ( ( s >= 0 ) && ( x == tracks[t] ) ) || x > tracks[t] );
348 : }
349 : }
350 :
351 604108 : *ps = add( ps0, dn[x_save] ); /* Qdn */
352 604108 : move16();
353 604108 : *alp = alpk[ik]; /* Qalp */
354 604108 : move16();
355 604108 : *ix = x_save; /* Q0 */
356 604108 : move16();
357 604108 : }
358 :
359 : /*--------------------------------------------------------------------------------------*
360 : * E_ACELP_4tsearchx_fx
361 : * Autocorrelation method for searching pulse positions effectively
362 : * Algorithm is identical to traditional covariance method
363 : *--------------------------------------------------------------------------------------*/
364 6409 : void E_ACELP_4tsearchx_fx(
365 : Word16 dn[], /*Qdn*/
366 : const Word16 cn[], /*Q_new*/
367 : Word16 Rw[], /*Q9*/
368 : Word16 code[], /*Q9*/
369 : const PulseConfig *config,
370 : Word16 ind[] /*Q0*/ )
371 : {
372 : Word16 sign[L_SUBFR], vec[L_SUBFR];
373 : Word16 cor[L_SUBFR];
374 : Word16 R_buf[2 * L_SUBFR - 1], *R;
375 : Word16 dn2[L_SUBFR];
376 6409 : Word16 ps2k, ps /* same format as dn[] */, ps2, alpk, alp = 0 /* Q13 and later Q_Rw*Q_signval=Q_cor*Q_signval */;
377 : Word32 s;
378 : Word16 codvec[NB_PULSE_MAX];
379 : Word16 pos_max[4];
380 : Word16 dn2_pos[8 * 4];
381 : UWord8 ipos[NB_PULSE_MAX];
382 6409 : Word16 i, j, k, st, pos = 0;
383 : Word16 scale;
384 : Word16 sign_val_1, sign_val_2;
385 : Word16 nb_pulse, nb_pulse_m2;
386 6409 : move16();
387 6409 : move16();
388 :
389 6409 : ps = 0; /* to avoid compilation warnings */
390 6409 : move16();
391 :
392 :
393 6409 : alp = config->alp; /* Q13 */
394 6409 : move16();
395 6409 : nb_pulse = config->nb_pulse;
396 6409 : move16();
397 6409 : move16();
398 6409 : nb_pulse_m2 = sub( nb_pulse, 2 );
399 :
400 : /* Init to avoid crash when the search does not find a solution */
401 81753 : FOR( k = 0; k < nb_pulse; k++ )
402 : {
403 75344 : codvec[k] = k;
404 75344 : move16();
405 : }
406 :
407 6409 : scale = 0;
408 6409 : move16();
409 6409 : s = L_mult0( Rw[0], Rw[0] ); /*Q18*/
410 410176 : FOR( i = 1; i < L_SUBFR; i++ )
411 : {
412 403767 : s = L_mac0( s, Rw[i], Rw[i] ); /*Q18*/
413 : }
414 6409 : if ( s_and( (Word16) GE_16( nb_pulse, 9 ), (Word16) GT_32( s, 0x800000 ) ) )
415 : {
416 2998 : scale = -1;
417 2998 : move16();
418 : }
419 6409 : if ( s_and( (Word16) GE_16( nb_pulse, 13 ), (Word16) GT_32( s, 0x4000000 ) ) )
420 : {
421 373 : scale = -2;
422 373 : move16();
423 : }
424 6409 : IF( GE_16( nb_pulse, 18 ) )
425 : {
426 0 : if ( GT_32( s, 0x200000 ) )
427 : {
428 0 : scale = -1;
429 0 : move16();
430 : }
431 0 : if ( GT_32( s, 0x400000 ) )
432 : {
433 0 : scale = -2;
434 0 : move16();
435 : }
436 0 : if ( GT_32( s, 0x4000000 ) )
437 : {
438 0 : scale = -3;
439 0 : move16();
440 : }
441 : }
442 6409 : if ( s_and( (Word16) GE_16( nb_pulse, 28 ), (Word16) GT_32( s, 0x800000 ) ) )
443 : {
444 0 : scale = -3;
445 0 : move16();
446 : }
447 6409 : if ( s_and( (Word16) GE_16( nb_pulse, 36 ), (Word16) GT_32( s, 0x4000000 ) ) )
448 : {
449 0 : scale = -4;
450 0 : move16();
451 : }
452 :
453 : /* Set up autocorrelation vector */
454 6409 : R = R_buf + L_SUBFR - 1;
455 6409 : Copy_Scale_sig( Rw, R, L_SUBFR, scale ); /*Q9+scale*/
456 410176 : FOR( k = 1; k < L_SUBFR; k++ )
457 : {
458 403767 : R[-k] = R[k];
459 403767 : move16();
460 : }
461 :
462 : /* Sign value */
463 6409 : sign_val_2 = 0x2000; /* Q15 */
464 6409 : move16();
465 6409 : if ( GE_16( nb_pulse, 24 ) )
466 : {
467 0 : sign_val_2 = shr( sign_val_2, 1 ); /* Q15 */
468 : }
469 6409 : sign_val_1 = shr( sign_val_2, 1 ); /* Q15 */
470 :
471 : /*
472 : * Find sign for each pulse position.
473 : */
474 6409 : E_ACELP_pulsesign( cn, dn, dn2, sign, vec, alp, sign_val_2, L_SUBFR );
475 :
476 : /*
477 : * Select the most important 8 position per track according to dn2[].
478 : */
479 6409 : E_ACELP_findcandidates( dn2, dn2_pos, pos_max );
480 :
481 : /*
482 : * Deep first search:
483 : */
484 :
485 : /* Ensure that in the loop below s > 0 in the first iteration, the actual values do not matter. */
486 6409 : ps2k = -1;
487 6409 : move16();
488 6409 : alpk = 1;
489 6409 : move16();
490 :
491 : /* Number of iterations */
492 25639 : FOR( k = 0; k < config->nbiter; k++ )
493 : {
494 19230 : E_ACELP_setup_pulse_search_pos( config, k, ipos );
495 :
496 : /* index to first non-fixed position */
497 19230 : pos = config->fixedpulses; /* Q0 */
498 19230 : move16();
499 :
500 19230 : IF( config->fixedpulses == 0 ) /* 1100, 11, 1110, 1111, 2211 */
501 : {
502 0 : ps = 0;
503 0 : move16();
504 0 : alp = 0;
505 0 : move16();
506 0 : set16_fx( cor, 0, L_SUBFR );
507 : }
508 : ELSE
509 : {
510 19230 : assert( config->fixedpulses == 2 || config->fixedpulses == 4 );
511 :
512 : /* set fixed positions */
513 76730 : FOR( i = 0; i < pos; ++i )
514 : {
515 57500 : ind[i] = pos_max[ipos[i]]; /* Q0 */
516 57500 : move16();
517 : }
518 :
519 : /* multiplication of autocorrelation with signed fixed pulses */
520 19230 : E_ACELP_update_cor_fx( ind, config->fixedpulses, sign, R, NULL, cor );
521 :
522 : /* normalisation contribution of fixed part */
523 19230 : s = L_mult0( cor[ind[0]], sign[ind[0]] ); /* Q22 */
524 19230 : ps = dn[ind[0]]; /* Qdn */
525 19230 : move16();
526 57500 : FOR( i = 1; i < pos; ++i )
527 : {
528 38270 : s = L_mac0( s, cor[ind[i]], sign[ind[i]] ); /*Q12+Q9+1=Q22 */
529 38270 : ps = add( ps, dn[ind[i]] ); /* Qdn */
530 : }
531 19230 : alp = round_fx( s ); /*mac0 >>1 sign = 2 Q6*/
532 : }
533 :
534 : /* other stages of 2 pulses */
535 19230 : st = 0;
536 19230 : move16();
537 105912 : FOR( j = pos; j < nb_pulse; j += 2 )
538 : {
539 86682 : IF( GE_16( nb_pulse_m2, j ) ) /* pair-wise search */
540 : {
541 : /*
542 : * Calculate correlation of all possible positions
543 : * of the next 2 pulses with previous fixed pulses.
544 : * Each pulse can have 16 possible positions.
545 : */
546 :
547 84714 : E_ACELP_2pulse_searchx_fx( config->nbpos[st], ipos[j], ipos[j + 1], R, &ps, &alp,
548 84714 : &ind[j], &ind[j + 1], dn, dn2_pos, cor, sign, sign_val_2 );
549 : }
550 : ELSE /* single pulse search */
551 : {
552 1968 : E_ACELP_1pulse_searchx_fx( &ipos[j], R, &ps, &alp,
553 1968 : &ind[j], dn, cor, sign, sign_val_1 );
554 : }
555 :
556 :
557 86682 : st = add( st, 1 );
558 : }
559 :
560 : /* memorise the best codevector */
561 : /*ps2 = ps * ps; MULT(1);*/
562 19230 : ps2 = mult( ps, ps ); /* 2*Qdn+1 */
563 :
564 : /*s = (alpk * ps2) - (ps2k * alp); MULT(2);ADD(1);*/
565 19230 : s = L_msu( L_mult( alpk, ps2 ), ps2k, alp ); /* 2*Qdn+8 */
566 :
567 19230 : IF( s > 0 )
568 : {
569 11682 : ps2k = ps2;
570 11682 : move16();
571 11682 : alpk = alp;
572 11682 : move16();
573 11682 : Copy( ind, codvec, nb_pulse ); /* Q0 */
574 : }
575 : }
576 :
577 :
578 : /*
579 : * Store weighted energy of code, build the codeword and index of codevector.
580 : */
581 6409 : E_ACELP_build_code( nb_pulse, codvec, sign, code, ind );
582 6409 : }
583 :
584 387401 : void E_ACELP_4tsearchx_ivas_fx(
585 : Word16 dn[], /*Qdn*/
586 : const Word16 cn[], /*Q_new*/
587 : Word16 Rw[], /*Q9*/
588 : Word16 code[], /*Q9*/
589 : const PulseConfig *config,
590 : Word16 ind[], /*Q0*/
591 : Word16 element_mode )
592 : {
593 : Word16 sign[L_SUBFR], vec[L_SUBFR];
594 : Word16 cor[L_SUBFR];
595 : Word16 R_buf[2 * L_SUBFR - 1], *R;
596 : Word16 dn2[L_SUBFR];
597 387401 : Word16 ps2k, ps /* same format as dn[] */, ps2, alpk, alp = 0 /* Q13 and later Q_Rw*Q_signval=Q_cor*Q_signval */;
598 : Word32 s;
599 : Word16 codvec[NB_PULSE_MAX];
600 : Word16 pos_max[4];
601 : Word16 dn2_pos[8 * 4];
602 : UWord8 ipos[NB_PULSE_MAX];
603 387401 : Word16 i, j, k, st, pos = 0;
604 : Word16 scale;
605 : Word16 sign_val_1, sign_val_2;
606 : Word16 nb_pulse, nb_pulse_m2;
607 : Word16 psk;
608 : Word16 val, index, track;
609 387401 : move16();
610 387401 : move16();
611 :
612 387401 : psk = ps = 0; /* to avoid compilation warnings */
613 387401 : move16();
614 387401 : move16();
615 :
616 :
617 387401 : alp = config->alp; /* Q13 */
618 387401 : move16();
619 387401 : nb_pulse = config->nb_pulse;
620 387401 : move16();
621 387401 : nb_pulse_m2 = sub( nb_pulse, 2 );
622 :
623 : /* Init to avoid crash when the search does not find a solution */
624 5263443 : FOR( k = 0; k < nb_pulse; k++ )
625 : {
626 4876042 : codvec[k] = k;
627 4876042 : move16();
628 : }
629 :
630 387401 : scale = 0;
631 387401 : move16();
632 387401 : s = L_mult0( Rw[0], Rw[0] ); /* Q18 */
633 24793664 : FOR( i = 1; i < L_SUBFR; i++ )
634 : {
635 24406263 : s = L_mac0( s, Rw[i], Rw[i] ); /* Q18 */
636 : }
637 387401 : if ( s_and( (Word16) GE_16( nb_pulse, 9 ), (Word16) GT_32( s, 0x800000 ) ) )
638 : {
639 135911 : scale = -1;
640 135911 : move16();
641 : }
642 387401 : if ( s_and( (Word16) GE_16( nb_pulse, 13 ), (Word16) GT_32( s, 0x4000000 ) ) )
643 : {
644 0 : scale = -2;
645 0 : move16();
646 : }
647 387401 : IF( GE_16( nb_pulse, 18 ) )
648 : {
649 53517 : if ( GT_32( s, 0x200000 ) )
650 : {
651 53517 : scale = -1;
652 53517 : move16();
653 : }
654 53517 : if ( GT_32( s, 0x400000 ) )
655 : {
656 47720 : scale = -2;
657 47720 : move16();
658 : }
659 53517 : if ( GT_32( s, 0x4000000 ) )
660 : {
661 0 : scale = -3;
662 0 : move16();
663 : }
664 : }
665 387401 : if ( s_and( (Word16) GE_16( nb_pulse, 28 ), (Word16) GT_32( s, 0x800000 ) ) )
666 : {
667 238 : scale = -3;
668 238 : move16();
669 : }
670 387401 : if ( s_and( (Word16) GE_16( nb_pulse, 36 ), (Word16) GT_32( s, 0x4000000 ) ) )
671 : {
672 0 : scale = -4;
673 0 : move16();
674 : }
675 :
676 : /* Set up autocorrelation vector */
677 387401 : R = R_buf + L_SUBFR - 1;
678 387401 : Copy_Scale_sig( Rw, R, L_SUBFR, scale ); /* Q9 + scale */
679 24793664 : FOR( k = 1; k < L_SUBFR; k++ )
680 : {
681 24406263 : R[-k] = R[k];
682 24406263 : move16();
683 : }
684 :
685 : /* Sign value */
686 387401 : sign_val_2 = 0x2000; /* Q15 */
687 387401 : move16();
688 387401 : if ( GE_16( nb_pulse, 24 ) )
689 : {
690 25186 : sign_val_2 = shr( sign_val_2, 1 ); /* Q15 */
691 : }
692 387401 : sign_val_1 = shr( sign_val_2, 1 ); /* Q15 */
693 :
694 : /*
695 : * Find sign for each pulse position.
696 : */
697 387401 : E_ACELP_pulsesign( cn, dn, dn2, sign, vec, alp, sign_val_2, L_SUBFR );
698 :
699 : /*
700 : * Select the most important 8 position per track according to dn2[].
701 : */
702 387401 : E_ACELP_findcandidates( dn2, dn2_pos, pos_max );
703 :
704 : /*
705 : * Deep first search:
706 : */
707 :
708 : /* Ensure that in the loop below s > 0 in the first iteration, the actual values do not matter. */
709 387401 : ps2k = -1;
710 387401 : move16();
711 387401 : alpk = 1;
712 387401 : move16();
713 :
714 : /* Number of iterations */
715 1766560 : FOR( k = 0; k < config->nbiter; k++ )
716 : {
717 1379159 : E_ACELP_setup_pulse_search_pos( config, k, ipos );
718 :
719 : /* index to first non-fixed position */
720 1379159 : pos = config->fixedpulses; /* Q0 */
721 1379159 : move16();
722 :
723 1379159 : IF( config->fixedpulses == 0 ) /* 1100, 11, 1110, 1111, 2211 */
724 : {
725 104924 : ps = 0;
726 104924 : move16();
727 104924 : alp = 0;
728 104924 : move16();
729 104924 : set16_fx( cor, 0, L_SUBFR );
730 : }
731 : ELSE
732 : {
733 1274235 : assert( config->fixedpulses == 2 || config->fixedpulses == 4 );
734 :
735 : /* set fixed positions */
736 5115065 : FOR( i = 0; i < pos; ++i )
737 : {
738 3840830 : ind[i] = pos_max[ipos[i]]; /* Q0 */
739 3840830 : move16();
740 : }
741 :
742 : /* multiplication of autocorrelation with signed fixed pulses */
743 1274235 : E_ACELP_update_cor_fx( ind, config->fixedpulses, sign, R, NULL, cor );
744 :
745 : /* normalisation contribution of fixed part */
746 1274235 : s = L_mult0( cor[ind[0]], sign[ind[0]] ); /* Q22 */
747 1274235 : ps = dn[ind[0]]; /* Qdn */
748 1274235 : move16();
749 3840830 : FOR( i = 1; i < pos; ++i )
750 : {
751 2566595 : s = L_mac0( s, cor[ind[i]], sign[ind[i]] ); /*Q12+Q9+1=Q22 */
752 2566595 : ps = add( ps, dn[ind[i]] );
753 : }
754 1274235 : alp = round_fx( s ); /*mac0 >>1 sign = 2 Q6*/
755 : }
756 :
757 : /* other stages of 2 pulses */
758 1379159 : st = 0;
759 1379159 : move16();
760 8099896 : FOR( j = pos; j < nb_pulse; j += 2 )
761 : {
762 6720737 : IF( GE_16( nb_pulse_m2, j ) ) /* pair-wise search */
763 : {
764 : /*
765 : * Calculate correlation of all possible positions
766 : * of the next 2 pulses with previous fixed pulses.
767 : * Each pulse can have 16 possible positions.
768 : */
769 :
770 6118597 : E_ACELP_2pulse_searchx_fx( config->nbpos[st], ipos[j], ipos[j + 1], R, &ps, &alp,
771 6118597 : &ind[j], &ind[j + 1], dn, dn2_pos, cor, sign, sign_val_2 );
772 : }
773 : ELSE /* single pulse search */
774 : {
775 602140 : E_ACELP_1pulse_searchx_fx( &ipos[j], R, &ps, &alp,
776 602140 : &ind[j], dn, cor, sign, sign_val_1 );
777 : }
778 :
779 6720737 : IF( GT_16( alp, ONE_IN_Q14 ) )
780 : {
781 780 : alp = shr( alp, 1 );
782 780 : Scale_sig( cor, L_SUBFR, -1 ); /*Q8*/
783 780 : Scale_sig( R_buf, 2 * L_SUBFR - 1, -1 ); /*Q8+scale*/
784 780 : Scale_sig( dn, L_SUBFR, -1 ); /*Qdn-1*/
785 : }
786 :
787 :
788 6720737 : st = add( st, 1 );
789 : }
790 :
791 : /* memorise the best codevector */
792 : /*ps2 = ps * ps; MULT(1);*/
793 1379159 : ps2 = mult( ps, ps ); /* 2*Qdn+1 */
794 :
795 : /*s = (alpk * ps2) - (ps2k * alp); MULT(2);ADD(1);*/
796 1379159 : s = L_msu( L_mult( alpk, ps2 ), ps2k, alp ); /* 2*Qdn+8 */
797 :
798 1379159 : IF( s > 0 )
799 : {
800 753880 : ps2k = ps2;
801 753880 : move16();
802 753880 : psk = ps;
803 753880 : move16();
804 753880 : alpk = alp;
805 753880 : move16();
806 753880 : Copy( ind, codvec, nb_pulse ); /*Q0*/
807 : }
808 : }
809 :
810 :
811 : /*
812 : * Store weighted energy of code, build the codeword and index of codevector.
813 : */
814 387401 : IF( EQ_16( element_mode, EVS_MONO ) )
815 : {
816 0 : E_ACELP_build_code( nb_pulse, codvec, sign, code, ind );
817 : }
818 : ELSE
819 : {
820 : /* Store weighted energy of code, build the codeword and index of codevector. */
821 387401 : set16_fx( code, 0, L_SUBFR );
822 387401 : set16_fx( ind, -1, NPMAXPT * 4 );
823 :
824 5263443 : FOR( k = 0; k < config->nb_pulse; k++ )
825 : {
826 4876042 : i = codvec[k]; /* read pulse position Q0*/
827 4876042 : move16();
828 4876042 : val = sign[i]; /* read sign Q13*/
829 4876042 : move16();
830 :
831 4876042 : index = shr( i, 2 ); /* pos of pulse (0..15) */
832 : // track = i % 4;
833 4876042 : track = s_and( i, 3 );
834 4876042 : IF( L_mult0( val, psk ) > 0 )
835 : {
836 2406864 : code[i] = add( code[i], ONE_IN_Q9 /*1.0f*/ ); /* Q9 */
837 2406864 : move16();
838 2406864 : codvec[k] = add( codvec[k], 2 * L_SUBFR ); /* Q0 */
839 2406864 : move16();
840 : }
841 : ELSE
842 : {
843 2469178 : code[i] = sub( code[i], ONE_IN_Q9 /*1.0f*/ ); /* Q9 */
844 2469178 : move16();
845 2469178 : index = add( index, 16 ); /* Q0 */
846 : }
847 :
848 4876042 : i = imult1616( track, NPMAXPT );
849 11389266 : WHILE( ind[i] >= 0 )
850 : {
851 6513224 : i++;
852 : }
853 :
854 4876042 : ind[i] = index;
855 4876042 : move16();
856 : }
857 : }
858 387401 : }
|