Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : /*====================================================================================
34 : 3GPP TS26.258 Aug 24, 2023. IVAS Codec Version IVAS-FL-1.0
35 : ====================================================================================*/
36 :
37 : /*====================================================================================
38 : EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
39 : ====================================================================================*/
40 :
41 : #include <stdlib.h>
42 : #include <assert.h>
43 : #include <stdint.h>
44 : #include "options.h"
45 : #include "stl.h"
46 : #include <math.h>
47 : #include "cnst.h"
48 : #include "prot_fx.h"
49 : #include "basop_util.h"
50 : #include "basop32.h"
51 : #include "wmc_auto.h"
52 : #include "prot_fx_enc.h"
53 : #include "ivas_prot_fx.h"
54 :
55 : #define INV_BANDS10 3277 /* 1/10 in Q15 */
56 : #define INV_BANDS9 3641 /* 1/9 in Q15 */
57 : #define INV_BANDS3 10923 /* 1/9 in Q15 */
58 : const Word16 b_hp400_fx[3] = { 3660, -7320, 3660 }; /* Q12 (/4) */
59 : const Word16 a_hp400_fx[3] = { 16384, 29280, -14160 };
60 : const Word16 a_hp400_ivas_fx[3] = { 4096, 7320, -3540 }; /*Q12*/
61 :
62 : #define WMC_TOOL_SKIP
63 :
64 : // conversion functions:
65 4794771 : Word32 float_to_fix( float number, Word32 Q )
66 : {
67 4794771 : assert( Q >= 0 );
68 4794771 : if ( number == 1.0f && Q == Q31 )
69 : {
70 0 : return ONE_IN_Q31;
71 : }
72 4794771 : if ( isnan( number ) )
73 : {
74 0 : number = 0;
75 : }
76 4794771 : assert( fabs( number ) < pow( 2, 31 - Q ) );
77 4794771 : Word32 ret = (Word32) ( number * ( (UWord32) 1 << Q ) );
78 4794771 : return ret;
79 : }
80 :
81 0 : float fix_to_float( Word32 number, Word32 Q )
82 : {
83 0 : assert( Q >= 0 );
84 0 : float ret = (float) number / ( (UWord32) 1 << Q );
85 0 : return ret;
86 : }
87 :
88 92160 : Word16 float_to_fix16( float number, Word16 Q )
89 : {
90 92160 : assert( Q >= 0 );
91 92160 : IF( isnan( number ) )
92 0 : return 0;
93 92160 : if ( number == 1.0f && Q == Q15 )
94 0 : return MAX16B;
95 92160 : if ( number == -1.0f && Q == Q15 )
96 0 : return MIN16B;
97 92160 : assert( fabs( number ) < pow( 2, 15 - Q ) );
98 92160 : Word16 ret = (Word16) ( number * ( (UWord16) 1 << Q ) );
99 92160 : return ret;
100 : }
101 :
102 0 : Word16 float_to_fix16_thrld( float number, Word16 Q )
103 : {
104 0 : assert( Q >= 0 );
105 0 : if ( number == 1.0f && Q == Q15 )
106 0 : return MAX16B;
107 0 : float limit = (float) pow( 2, 15 - Q );
108 : /*Add threshold*/
109 0 : if ( number > MAX16B_FLT )
110 : {
111 0 : number = MAX16B_FLT;
112 : }
113 0 : else if ( number < MIN16B_FLT )
114 : {
115 0 : number = MIN16B_FLT;
116 : }
117 0 : assert( number <= limit && number >= -limit );
118 0 : Word16 ret = (Word16) ( number * ( (UWord16) 1 << Q ) );
119 0 : return ret;
120 : }
121 :
122 68942 : float fix16_to_float( Word16 number, Word16 Q )
123 : {
124 68942 : assert( Q >= 0 );
125 68942 : float ret = (float) number / ( (UWord16) 1 << Q );
126 68942 : return ret;
127 : }
128 :
129 : // Float to 32-bit Mantissa and Exponent
130 4214584 : void f2me( float n, Word32 *mantissa, Word16 *expo )
131 : {
132 : Word32 e;
133 4214584 : float mf = (float) frexp( n, &e );
134 4214584 : *expo = (Word16) e;
135 4214584 : *mantissa = float_to_fix( mf, Q31 );
136 4214584 : }
137 :
138 : // 32-bit Mantissa and Exponent to Float
139 0 : float me2f( Word32 m, Word16 expo )
140 : {
141 0 : float mf = fix_to_float( m, Q31 );
142 0 : return (float) ldexp( mf, expo );
143 : }
144 :
145 : // Float buffer to 32-bit mantissa buffer and common exponent.
146 72 : void f2me_buf( const float *x, Word32 *m, Word16 *e, const Word32 n )
147 : {
148 72 : Word16 max_e = -32, tmp_e;
149 : Word32 i;
150 :
151 2107364 : for ( i = 0; i < n; i++ )
152 : {
153 2107292 : f2me( x[i], &m[i], &tmp_e );
154 2107292 : max_e = ( max_e > tmp_e ) ? max_e : tmp_e;
155 : }
156 :
157 2107364 : for ( i = 0; i < n; i++ )
158 : {
159 2107292 : f2me( x[i], &m[i], &tmp_e );
160 2107292 : m[i] = L_shr( m[i], max_e - tmp_e );
161 : }
162 :
163 72 : *e = max_e;
164 72 : }
165 :
166 : // 32-bit Mantissa buffer and exponent into float buffer.
167 0 : void me2f_buf( const Word32 *m, const Word16 e, float *out, const Word32 n )
168 : {
169 0 : for ( int i = 0; i < n; i++ )
170 : {
171 0 : out[i] = me2f( m[i], e );
172 : }
173 0 : }
174 :
175 : // Float to 16-bit Mantissa and Exponent
176 0 : void f2me_16( float n, Word16 *mantissa, Word16 *expo )
177 : {
178 : Word32 e;
179 0 : float mf = (float) frexp( n, &e );
180 0 : *expo = (Word16) e;
181 0 : *mantissa = float_to_fix16( mf, 15 );
182 0 : }
183 :
184 : // 16-bit Mantissa and Exponent to Float
185 0 : float me2f_16( Word16 m, Word16 expo )
186 : {
187 0 : float mf = fix16_to_float( m, 15 );
188 0 : return (float) ldexp( mf, expo );
189 : }
190 :
191 : // Float buffer to 16-bit mantissa buffer and common exponent.
192 0 : void f2me_buf_16( const float *x, Word16 *m, Word16 *e, const Word32 n )
193 : {
194 0 : Word16 max_e = -16, tmp_e;
195 : Word32 i;
196 :
197 0 : for ( i = 0; i < n; i++ )
198 : {
199 0 : f2me_16( x[i], &m[i], &tmp_e );
200 0 : max_e = ( max_e > tmp_e ) ? max_e : tmp_e;
201 : }
202 :
203 0 : for ( i = 0; i < n; i++ )
204 : {
205 0 : f2me_16( x[i], &m[i], &tmp_e );
206 0 : m[i] = shr( m[i], max_e - tmp_e );
207 : }
208 :
209 0 : *e = max_e;
210 0 : }
211 :
212 : // 16-bit Mantissa buffer and exponent into float buffer.
213 0 : void me2f_buf_16( const Word16 *m, const Word16 e, float *out, const Word32 n )
214 : {
215 0 : for ( int i = 0; i < n; i++ )
216 : {
217 0 : out[i] = me2f_16( m[i], e );
218 : }
219 0 : }
220 0 : void f2fix( float *var_flt, Word32 *var_fix, Word32 expo )
221 : {
222 0 : *var_fix = (Word32) ( *var_flt * pow( 2, 31 - expo ) );
223 0 : }
224 :
225 0 : void fix2f( Word32 *var_fix, float *var_flt, Word32 expo )
226 : {
227 0 : float mf = fix_to_float( *var_fix, 31 );
228 0 : *var_flt = (float) ldexp( mf, expo );
229 0 : }
230 :
231 0 : void f2fix_16( float *var_flt, Word16 *var_fix, Word32 expo )
232 : {
233 0 : *var_fix = (Word16) ( *var_flt * pow( 2, 15 - expo ) );
234 0 : }
235 :
236 0 : void fix2f_16( Word16 *var_fix, float *var_flt, Word32 expo )
237 : {
238 0 : float mf = fix16_to_float( *var_fix, 15 );
239 0 : *var_flt = (float) ldexp( mf, expo );
240 0 : }
241 :
242 : #undef WMC_TOOL_SKIP
243 :
244 : /*-------------------------------------------------------------------*
245 : * usdequant_fx()
246 : *
247 : * Uniform scalar de-quantizer routine
248 : *
249 : * Applies de-quantization based on scale and round operations.
250 : *-------------------------------------------------------------------*/
251 276181 : Word16 usdequant_fx( /* Qx*/
252 : const Word16 idx, /* i: quantizer index Q0*/
253 : const Word16 qlow, /* i: lowest codebook entry (index 0) Qx*/
254 : const Word16 delta /* i: quantization step Qx-1*/
255 : )
256 : {
257 : Word16 g;
258 : Word32 L_tmp;
259 :
260 : /*g = idx * delta + qlow;*/
261 276181 : L_tmp = L_deposit_l( qlow ); /*Qx */
262 276181 : L_tmp = L_mac( L_tmp, idx, delta ); /*Qx */
263 276181 : g = round_fx_sat( L_shl_sat( L_tmp, 16 ) ); /*Qx */
264 276181 : return ( g );
265 : }
266 :
267 188430 : Word32 usdequant32_fx( /* Qx*/
268 : const Word16 idx, /* i: quantizer index Q0*/
269 : const Word32 qlow, /* i: lowest codebook entry (index 0) Qx*/
270 : const Word32 delta /* i: quantization step Qx-1*/
271 : )
272 : {
273 : Word32 g;
274 : Word64 L_tmp;
275 :
276 : /*g = idx * delta + qlow;*/
277 188430 : L_tmp = W_deposit32_l( qlow ); /*Qx */
278 188430 : L_tmp = W_mac_32_16( L_tmp, delta, idx );
279 188430 : IF( GE_64( L_tmp, MAX_32 ) )
280 : {
281 42608 : g = MAX_32;
282 42608 : move32();
283 : }
284 : ELSE
285 : {
286 145822 : g = W_extract_l( L_tmp ); /*Qx */
287 : }
288 188430 : return ( g );
289 : }
290 :
291 : /*-------------------------------------------------------------------*
292 : * usquant()
293 : *
294 : * Uniform scalar quantizer according to MMSE criterion
295 : * (nearest neighbour in Euclidean space)
296 : *
297 : * Applies quantization based on scale and round operations.
298 : * Index of the winning codeword and the winning codeword itself are returned.
299 : *-------------------------------------------------------------------*/
300 176638 : Word16 usquant_fx( /* o: index of the winning codeword */
301 : const Word16 x, /* i: scalar value to quantize Qx*/
302 : Word16 *xq, /* o: quantized value Qx*/
303 : const Word16 qlow, /* i: lowest codebook entry (index 0) Qx*/
304 : const Word16 delta, /* i: quantization step Qx-1*/
305 : const Word16 cbsize /* i: codebook size */
306 : )
307 : {
308 : Word16 idx;
309 : Word16 tmp, exp;
310 : Word32 L_tmp;
311 : #ifndef ISSUE_1836_replace_overflow_libcom
312 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
313 : Flag Overflow = 0;
314 : move32();
315 : #endif
316 : #endif
317 :
318 : /* idx = (short)( (x - qlow)/delta + 0.5f); */
319 176638 : exp = norm_s( delta );
320 176638 : tmp = div_s( shl( 1, sub( 14, exp ) ), delta ); /*Q(29-exp-(Qx-1))->Q(30-exp-Qx) */
321 : #ifdef ISSUE_1836_replace_overflow_libcom
322 176638 : L_tmp = L_mult( sub_sat( x, qlow ), tmp ); /*Q(31-exp) */
323 176638 : idx = extract_l( L_shr_r( L_add( L_tmp, shl_sat( 1, sub( 30, exp ) ) ), sub( 31, exp ) ) ); /*Q0 */
324 : #else
325 : L_tmp = L_mult( sub_o( x, qlow, &Overflow ), tmp ); /*Q(31-exp) */
326 : idx = extract_l( L_shr_r( L_add( L_tmp, shl_o( 1, sub( 30, exp ), &Overflow ) ), sub( 31, exp ) ) ); /*Q0 */
327 : #endif
328 :
329 176638 : idx = s_min( idx, sub( cbsize, 1 ) );
330 176638 : idx = s_max( idx, 0 );
331 :
332 : /* *xq = idx*delta + qlow; */
333 176638 : L_tmp = L_deposit_l( qlow ); /*Qx */
334 176638 : L_tmp = L_mac( L_tmp, idx, delta ); /*Qx */
335 : #ifdef ISSUE_1836_replace_overflow_libcom
336 176638 : *xq = round_fx_sat( L_shl_sat( L_tmp, 16 ) ); /*Qx */
337 : #else
338 : *xq = round_fx_o( L_shl_o( L_tmp, 16, &Overflow ), &Overflow ); /*Qx */
339 : #endif
340 176638 : return idx;
341 : }
342 : /*-------------------------------------------------------------------*
343 : * Dot_product:
344 : *
345 : * Compute scalar product of <x[],y[]> using accumulator.
346 : * Performs no normalization, as opposed to Dot_product12()
347 : *-------------------------------------------------------------------*/
348 3228258 : Word32 Dot_product( /* o : Sum */
349 : const Word16 x[], /* i : 12bits: x vector */
350 : const Word16 y[], /* i : 12bits: y vector */
351 : const Word16 lg /* i : vector length */
352 : )
353 : {
354 : Word16 i;
355 : Word32 L_sum;
356 : Word64 L64_sum;
357 :
358 3228258 : L64_sum = 1;
359 3228258 : move64();
360 34256724 : FOR( i = 0; i < lg; i++ )
361 : {
362 31028466 : L64_sum = W_mac_16_16( L64_sum, x[i], y[i] );
363 : }
364 3228258 : L_sum = W_sat_l( L64_sum );
365 3228258 : return L_sum;
366 : }
367 : /*---------------------------------------------------------------------*
368 : * dotp_fx()
369 : *
370 : * Dot product of vector x[] and vector y[]
371 : *---------------------------------------------------------------------*/
372 :
373 6411 : Word32 dotp_fx( /* o : dot product of x[] and y[] */
374 : const Word16 x[], /* i : vector x[] */
375 : const Word16 y[], /* i : vector y[] */
376 : const Word16 n, /* i : vector length */
377 : Word16 *exp /* (o) : exponent of result (0..+30) */
378 : )
379 : {
380 : Word16 sft;
381 : Word32 L_sum;
382 :
383 6411 : assert( *exp == 0 );
384 :
385 6411 : L_sum = L_add( L_shr( Dot_product( x, y, n ), 1 ), 1 );
386 :
387 : /* Normalize acc in Q31 */
388 :
389 6411 : sft = norm_l( L_sum );
390 6411 : L_sum = L_shl( L_sum, sft );
391 :
392 6411 : *exp = sub( 30, sft );
393 6411 : move16(); /* exponent = 0..30 */
394 :
395 6411 : return L_sum;
396 : }
397 :
398 115123 : Word32 sum2_fx( /* o : sum of all squared vector elements Q(2x+1)*/
399 : const Word16 *vec, /* i : input vector Qx*/
400 : const Word16 lvec /* i : length of input vector */
401 : )
402 : {
403 : Word16 i;
404 : Word32 L_tmp;
405 : #ifndef ISSUE_1836_replace_overflow_libcom
406 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
407 : Flag Overflow = 0;
408 : move32();
409 : #endif
410 : #endif
411 115123 : L_tmp = L_deposit_l( 0 );
412 13111091 : FOR( i = 0; i < lvec; i++ )
413 : {
414 : #ifdef ISSUE_1836_replace_overflow_libcom
415 12995968 : L_tmp = L_mac_sat( L_tmp, vec[i], vec[i] ); /*Q(2x+1) */
416 : #else
417 : L_tmp = L_mac_o( L_tmp, vec[i], vec[i], &Overflow ); /*Q(2x+1) */
418 : #endif
419 : }
420 :
421 115123 : return L_tmp;
422 : }
423 :
424 0 : Word64 sum2_fx_no_sat( /* o : sum of all squared vector elements Q(2*Qx)*/
425 : const Word16 *vec, /* i : input vector Qx*/
426 : const Word16 lvec /* i : length of input vector */
427 : )
428 : {
429 : Word16 i;
430 : Word64 sum;
431 :
432 0 : sum = 0;
433 0 : move64();
434 0 : FOR( i = 0; i < lvec; i++ )
435 : {
436 0 : sum = W_mac0_16_16( sum, vec[i], vec[i] ); // 2*Qx
437 : }
438 :
439 0 : return sum;
440 : }
441 :
442 13146 : Word32 sum_32_fx(
443 : const Word32 *vec, /* i : input vector */
444 : const Word16 lvec, /* i : length of input vector */
445 : Word16 *e )
446 : {
447 : Word16 i, shift;
448 13146 : Word64 tmp = 0;
449 13146 : move64();
450 : Word32 ans;
451 :
452 61090 : FOR( i = 0; i < lvec; i++ )
453 : {
454 47944 : tmp = W_add( tmp, vec[i] ); // e
455 : }
456 13146 : shift = W_norm( tmp );
457 13146 : tmp = W_shl( tmp, shift ); // shift + (31 - e)
458 13146 : ans = W_extract_h( tmp ); // shift + (31 - e) - 32
459 13146 : *e = add( sub( *e, shift ), 32 );
460 13146 : move16();
461 :
462 13146 : return ans;
463 : }
464 :
465 70466 : Word32 sum2_fx_mod( /* o : sum of all squared vector elements Q(2x+1 -5)*/
466 : const Word16 *vec, /* i : input vector Qx*/
467 : const Word16 lvec /* i : length of input vector */
468 : )
469 : {
470 : Word16 i;
471 : Word32 L_tmp;
472 : #ifndef ISSUE_1836_replace_overflow_libcom
473 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
474 : Flag Overflow = 0;
475 : move32();
476 : #endif
477 : #endif
478 :
479 70466 : L_tmp = L_deposit_l( 0 );
480 45168706 : FOR( i = 0; i < lvec; i++ )
481 : {
482 : #ifdef ISSUE_1836_replace_overflow_libcom
483 45098240 : L_tmp = L_add_sat( L_tmp, L_shr( L_mult_sat( vec[i], vec[i] ), 9 ) );
484 : #else
485 : L_tmp = L_add_o( L_tmp, L_shr( L_mult_o( vec[i], vec[i], &Overflow ), 9 ), &Overflow );
486 : #endif
487 : }
488 :
489 70466 : return L_tmp;
490 : }
491 : /*-------------------------------------------------------------------*
492 : * Copy:
493 : *
494 : * Copy vector x[] to y[]
495 : *
496 : *-------------------------------------------------------------------*/
497 57229638 : void Copy(
498 : const Word16 x[], /* i : input vector */
499 : Word16 y[], /* o : output vector */
500 : const Word16 L /* i : vector length */
501 : )
502 : {
503 : Word16 i;
504 :
505 57229638 : IF( y < x )
506 : {
507 6371114789 : FOR( i = 0; i < L; i++ )
508 : {
509 6344297700 : y[i] = x[i];
510 6344297700 : move16();
511 : }
512 :
513 : /* Location of x and y may differ depending on platform/memory allocation. Since IF and ELSE has different complexity count, the early return is used instead of ELSE to ensure the same complexity number regardless of x and y memory addresses. */
514 26817089 : return;
515 : }
516 :
517 6854485414 : FOR( i = L - 1; i >= 0; i-- )
518 : {
519 6824072865 : y[i] = x[i];
520 6824072865 : move16();
521 : }
522 :
523 30412549 : return;
524 : }
525 : /*-------------------------------------------------------------------*
526 : * Copy64:
527 : *
528 : * Copy vector x[] to y[] (64 bits)
529 : *-------------------------------------------------------------------*/
530 8214 : void Copy64(
531 : const Word64 x[], /* i : input vector */
532 : Word64 y[], /* o : output vector */
533 : const Word16 L /* i : vector length */
534 : )
535 : {
536 : Word16 i;
537 8214 : IF( y < x )
538 : {
539 0 : FOR( i = 0; i < L; i++ )
540 : {
541 0 : y[i] = x[i];
542 0 : move64();
543 : }
544 :
545 : /* Location of x and y may differ depending on platform/memory allocation. Since IF and ELSE has different complexity count, the early return is used instead of ELSE to ensure the same complexity number regardless of x and y memory addresses. */
546 0 : return;
547 : }
548 :
549 35814 : FOR( i = L - 1; i >= 0; i-- )
550 : {
551 27600 : y[i] = x[i];
552 27600 : move64();
553 : }
554 :
555 8214 : return;
556 : }
557 :
558 464840 : void set64_fx(
559 : Word64 y[], /* i/o: Vector to set */
560 : const Word64 a, /* i : Value to set the vector to */
561 : const Word16 N /* i : Lenght of the vector */
562 : )
563 : {
564 : Word16 i;
565 27666646 : FOR( i = 0; i < N; i++ )
566 : {
567 27201806 : y[i] = a;
568 27201806 : move64();
569 : }
570 :
571 464840 : return;
572 : }
573 :
574 57737 : void Copy_pword(
575 : const PWord16 x[], /* i : input vector */
576 : PWord16 y[], /* o : output vector */
577 : const Word16 L /* i : vector length */
578 : )
579 : {
580 : Word16 i;
581 :
582 57737 : IF( y < x )
583 : {
584 1090540 : FOR( i = 0; i < L; i++ )
585 : {
586 1038224 : y[i].v.im = x[i].v.im;
587 1038224 : y[i].v.re = x[i].v.re;
588 1038224 : move16();
589 1038224 : move16();
590 : }
591 :
592 : /* Location of x and y may differ depending on platform/memory allocation. Since IF and ELSE has different complexity count, the early return is used instead of ELSE to ensure the same complexity number regardless of x and y memory addresses. */
593 52316 : return;
594 : }
595 :
596 331901 : FOR( i = L - 1; i >= 0; i-- )
597 : {
598 326480 : y[i].v.im = x[i].v.im;
599 326480 : y[i].v.re = x[i].v.re;
600 326480 : move16();
601 326480 : move16();
602 : }
603 :
604 5421 : return;
605 : }
606 : /*-------------------------------------------------------------------*
607 : * Copy32:
608 : *
609 : * Copy vector x[] to y[] (32 bits)
610 : *-------------------------------------------------------------------*/
611 217617679 : void Copy32(
612 : const Word32 x[], /* i : input vector */
613 : Word32 y[], /* o : output vector */
614 : const Word16 L /* i : vector length */
615 : )
616 : {
617 : Word16 i;
618 217617679 : IF( y < x )
619 : {
620 27482448068 : FOR( i = 0; i < L; i++ )
621 : {
622 27372618863 : y[i] = x[i];
623 27372618863 : move32();
624 : }
625 :
626 109829205 : return;
627 : }
628 :
629 24950249707 : FOR( i = L - 1; i >= 0; i-- )
630 : {
631 24842461233 : y[i] = x[i];
632 24842461233 : move32();
633 : }
634 : }
635 :
636 128 : void set8_fx(
637 : Word8 y[], /* i/o: Vector to set */
638 : const Word8 a, /* i : Value to set the vector to */
639 : const Word16 N /* i : Lenght of the vector */
640 : )
641 : {
642 : Word16 i;
643 :
644 1536 : FOR( i = 0; i < N; i++ )
645 : {
646 1408 : y[i] = a;
647 1408 : move16();
648 : }
649 :
650 128 : return;
651 : }
652 :
653 : /*-------------------------------------------------------------------*
654 : * set16_fx()
655 : * set32_fx()
656 : *
657 : * Set the vector elements to a value
658 : *-------------------------------------------------------------------*/
659 156042033 : void set16_fx(
660 : Word16 y[], /* i/o: Vector to set */
661 : const Word16 a, /* i : Value to set the vector to */
662 : const Word16 N /* i : Lenght of the vector */
663 : )
664 : {
665 : Word16 i;
666 :
667 15854939901 : FOR( i = 0; i < N; i++ )
668 : {
669 15698897868 : y[i] = a;
670 15698897868 : move16();
671 : }
672 :
673 156042033 : return;
674 : }
675 :
676 522927717 : void set32_fx(
677 : Word32 y[], /* i/o: Vector to set */
678 : const Word32 a, /* i : Value to set the vector to */
679 : const Word16 N /* i : Lenght of the vector */
680 : )
681 : {
682 : Word16 i;
683 :
684 46337696079 : FOR( i = 0; i < N; i++ )
685 : {
686 45814768362 : y[i] = a;
687 45814768362 : move32();
688 : }
689 :
690 522927717 : return;
691 : }
692 : /*-------------------------------------------------------------------*
693 : * Copy_Scale_sig
694 : *
695 : * Up/down scale a 16 bits vector x and move it into y
696 : *-------------------------------------------------------------------*/
697 8355123 : void Copy_Scale_sig(
698 : const Word16 x[], /* i : signal to scale input Qx */
699 : Word16 y[], /* o : scaled signal output Qx */
700 : const Word16 lg, /* i : size of x[] Q0 */
701 : const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */
702 : )
703 : {
704 : Word16 i;
705 : Word16 tmp;
706 : #ifndef ISSUE_1836_replace_overflow_libcom
707 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
708 : Flag Overflow = 0;
709 : move32();
710 : #endif
711 : #endif
712 8355123 : IF( exp0 == 0 )
713 : {
714 1504123000 : FOR( i = 0; i < lg; i++ )
715 : {
716 1502339246 : y[i] = x[i];
717 1502339246 : move16();
718 : }
719 1783754 : return;
720 : }
721 6571369 : IF( exp0 < 0 )
722 : {
723 4560075 : tmp = shl( -32768, exp0 ); /* we use negative to correctly represent 1.0 */
724 2589830421 : FOR( i = 0; i < lg; i++ )
725 : {
726 2585270346 : y[i] = msu_r( 0, x[i], tmp );
727 2585270346 : move16();
728 : }
729 4560075 : return;
730 : }
731 1346905593 : FOR( i = 0; i < lg; i++ )
732 : {
733 : #ifdef ISSUE_1836_replace_overflow_libcom
734 1344894299 : y[i] = shl_sat( x[i], exp0 );
735 : #else
736 : y[i] = shl_o( x[i], exp0, &Overflow );
737 : #endif
738 1344894299 : move16(); /* saturation can occur here */
739 : }
740 : }
741 : /*-------------------------------------------------------------------*
742 : * Copy_Scale_sig
743 : *
744 : * Up/down scale a 16 bits vector x and move it into y
745 : *-------------------------------------------------------------------*/
746 2542235 : void Copy_Scale_sig_16_32_DEPREC(
747 : const Word16 x[], /* i : signal to scale input Qx */
748 : Word32 y[], /* o : scaled signal output Qx */
749 : const Word16 lg, /* i : size of x[] Q0 */
750 : const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */
751 : )
752 : {
753 : Word16 i;
754 : Word16 tmp;
755 : #ifndef ISSUE_1836_replace_overflow_libcom
756 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
757 : Flag Overflow = 0;
758 : move32();
759 : #endif
760 : #endif
761 :
762 :
763 2542235 : IF( exp0 == 0 )
764 : {
765 1054867907 : FOR( i = 0; i < lg; i++ )
766 : {
767 1053752900 : y[i] = L_deposit_l( x[i] );
768 1053752900 : move32();
769 : }
770 1115007 : return;
771 : }
772 1427228 : IF( exp0 < 0 )
773 : {
774 : /*Should not happen */
775 43253059 : FOR( i = 0; i < lg; i++ )
776 : {
777 : #ifdef ISSUE_1836_replace_overflow_libcom
778 43103232 : y[i] = L_deposit_l( shl_sat( x[i], exp0 ) );
779 : #else
780 : y[i] = L_deposit_l( shl_o( x[i], exp0, &Overflow ) );
781 : #endif
782 43103232 : move32();
783 : }
784 149827 : return;
785 : }
786 : #ifdef DEBUGGING
787 : if ( exp0 >= 16 )
788 : {
789 : printf( "Issue in Copy_Scale_sig_16_32_DEPREC\n" );
790 : }
791 : #else
792 1277401 : assert( exp0 < 16 );
793 : #endif
794 : #ifdef ISSUE_1836_replace_overflow_libcom
795 1277401 : tmp = shl_sat( 1, exp0 );
796 : #else
797 : tmp = shl_o( 1, exp0, &Overflow );
798 : #endif
799 354895701 : FOR( i = 0; i < lg; i++ )
800 : {
801 353618300 : y[i] = L_mult0( x[i], tmp );
802 353618300 : move32(); /* saturation can occur here */
803 : }
804 : }
805 :
806 11457880 : void Copy_Scale_sig_16_32_no_sat(
807 : const Word16 x[], /* i : signal to scale input Qx */
808 : Word32 y[], /* o : scaled signal output Qx */
809 : const Word16 lg, /* i : size of x[] Q0 */
810 : const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */
811 : )
812 : {
813 : Word16 i;
814 : Word32 L_tmp;
815 : #ifndef ISSUE_1836_replace_overflow_libcom
816 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
817 : Flag Overflow = 0;
818 : move32();
819 : #endif
820 : #endif
821 :
822 :
823 11457880 : IF( exp0 == 0 )
824 : {
825 9440625 : FOR( i = 0; i < lg; i++ )
826 : {
827 9417145 : y[i] = L_deposit_l( x[i] );
828 9417145 : move32();
829 : }
830 23480 : return;
831 : }
832 11434400 : IF( exp0 < 0 )
833 : {
834 : /*Should not happen */
835 268037422 : FOR( i = 0; i < lg; i++ )
836 : {
837 : #ifdef ISSUE_1836_replace_overflow_libcom
838 267507575 : y[i] = L_deposit_l( shl_sat( x[i], exp0 ) );
839 : #else
840 : y[i] = L_deposit_l( shl_o( x[i], exp0, &Overflow ) );
841 : #endif
842 267507575 : move32();
843 : }
844 529847 : return;
845 : }
846 : #ifdef ISSUE_1836_replace_overflow_libcom
847 10904553 : L_tmp = L_shl_sat( 1, exp0 - 1 );
848 : #else
849 : L_tmp = L_shl_o( 1, exp0 - 1, &Overflow );
850 : #endif
851 :
852 10904553 : IF( L_tmp >= 0x7FFF )
853 : {
854 26207142 : FOR( i = 0; i < lg; i++ )
855 : {
856 : // y[i] = L_mult0(x[i], L_tmp);
857 25575851 : y[i] = W_extract_l( W_mult_32_16( L_tmp, x[i] ) );
858 25575851 : move32(); /* Overflow can occur here */
859 : }
860 631291 : return;
861 : }
862 : // ELSE
863 : {
864 10273262 : Word16 tmp = extract_l( L_tmp );
865 5190937218 : FOR( i = 0; i < lg; i++ )
866 : {
867 5180663956 : y[i] = L_mult( x[i], tmp );
868 5180663956 : move32();
869 : }
870 : }
871 : }
872 :
873 6311568 : void Copy_Scale_sig_32_16(
874 : const Word32 x[], /* i : signal to scale input Qx */
875 : Word16 y[], /* o : scaled signal output Qx */
876 : const Word16 lg, /* i : size of x[] Q0 */
877 : const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */
878 : )
879 : {
880 : Word16 i;
881 : Word16 tmp;
882 : #ifndef ISSUE_1836_replace_overflow_libcom
883 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
884 : Flag Overflow = 0;
885 : move32();
886 : #endif
887 : #endif
888 :
889 6311568 : tmp = add( 16, exp0 );
890 6311568 : IF( tmp != 0 )
891 : {
892 4093910814 : FOR( i = 0; i < lg; i++ )
893 : {
894 : #ifdef ISSUE_1836_replace_overflow_libcom
895 4087612434 : y[i] = round_fx_sat( L_shl_sat( x[i], tmp ) );
896 : #else
897 : y[i] = round_fx_o( L_shl_o( x[i], tmp, &Overflow ), &Overflow );
898 : #endif
899 4087612434 : move16();
900 : }
901 : }
902 : ELSE
903 : {
904 12209152 : FOR( i = 0; i < lg; i++ )
905 : {
906 : #ifdef ISSUE_1836_replace_overflow_libcom
907 12195964 : y[i] = round_fx_sat( x[i] );
908 : #else
909 : y[i] = round_fx_o( x[i], &Overflow );
910 : #endif
911 12195964 : move16();
912 : }
913 : }
914 6311568 : }
915 :
916 : /*-------------------------------------------------------------------*
917 : * Scale_sig32
918 : *
919 : * Up/down scale a 32 bits vector
920 : *-------------------------------------------------------------------*/
921 97098624 : void Scale_sig32(
922 : Word32 x[], /* i/o: signal to scale Qx */
923 : const Word16 lg, /* i : size of x[] Q0 */
924 : const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */
925 : )
926 : {
927 : Word16 i;
928 : #ifndef ISSUE_1836_replace_overflow_libcom
929 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
930 : Flag Overflow = 0;
931 : move32();
932 : #endif
933 : #endif
934 97098624 : IF( 0 == exp0 )
935 : {
936 27134319 : return;
937 : }
938 :
939 23458939410 : FOR( i = 0; i < lg; i++ )
940 : {
941 : #ifdef ISSUE_1836_replace_overflow_libcom
942 23388975105 : x[i] = L_shl_sat( x[i], exp0 );
943 : #else
944 : x[i] = L_shl_o( x[i], exp0, &Overflow );
945 : #endif
946 23388975105 : move32(); /* saturation can occur here */
947 : }
948 : }
949 :
950 : /*------------------------------------------------------------------*
951 : * function Random_Fill
952 : *
953 : * Signed 16 bits random generator.
954 : * (Avoids Store of Seed to Memory for 'n' Random Values and
955 : * Combines Scaling Operation.)
956 : *------------------------------------------------------------------*/
957 60697 : void Random_Fill(
958 : Word16 *seed, /* i/o: random seed */
959 : Word16 n, /* i : number of values */
960 : Word16 *y, /* o : output values */
961 : Word16 scaling /* i : scaling of values */
962 : )
963 : {
964 : Word16 i;
965 : Word16 local_seed;
966 :
967 60697 : local_seed = *seed;
968 60697 : move16();
969 5158873 : FOR( i = 0; i < n; i++ )
970 : {
971 5098176 : local_seed = extract_l( L_mac0( 13849L, local_seed, 31821 ) );
972 5098176 : *y++ = shr( local_seed, scaling );
973 5098176 : move16();
974 : }
975 60697 : *seed = local_seed;
976 60697 : move16();
977 60697 : }
978 : /*-------------------------------------------------------------------*
979 : * Scale_sig
980 : * Up/down scale a 16 bits vector
981 : *-------------------------------------------------------------------*/
982 35471681 : void Scale_sig(
983 : Word16 x[], /* i/o: signal to scale Qx */
984 : const Word16 lg, /* i : size of x[] Q0 */
985 : const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */
986 : )
987 : {
988 : Word16 i;
989 : Word16 tmp;
990 :
991 35471681 : IF( exp0 > 0 )
992 : {
993 6095890022 : FOR( i = 0; i < lg; i++ )
994 : {
995 6088678200 : x[i] = shl_sat( x[i], exp0 );
996 6088678200 : move16(); /* saturation can occur here */
997 : }
998 7211822 : return;
999 : }
1000 28259859 : IF( exp0 < 0 )
1001 : {
1002 9212469 : tmp = shl_sat( -32768, exp0 ); /* we use negative to correctly represent 1.0 */
1003 5416121045 : FOR( i = 0; i < lg; i++ )
1004 : {
1005 5406908576 : x[i] = msu_r_sat( 0, x[i], tmp );
1006 5406908576 : move16(); /* msu instead of mac because factor is negative */
1007 : }
1008 9212469 : return;
1009 : }
1010 : }
1011 :
1012 : /*-------------------------------------------------------------------*
1013 : * scale_sig
1014 : * Up/down scale a 16 bits vector
1015 : *-------------------------------------------------------------------*/
1016 252898 : void scale_sig(
1017 : Word16 x[], /* i/o: signal to scale Qx */
1018 : const Word16 lg, /* i : size of x[] Q0 */
1019 : const Word16 exp0 /* i : exponent: x = round(x << exp) Qx exp */
1020 : )
1021 : {
1022 : Word16 i;
1023 :
1024 252898 : IF( exp0 != 0 )
1025 : {
1026 39384576 : FOR( i = 0; i < lg; i++ )
1027 : {
1028 39259990 : x[i] = shl( x[i], exp0 );
1029 39259990 : move16();
1030 : }
1031 : }
1032 252898 : }
1033 :
1034 : /*---------------------------------------------------------------------*
1035 : * mean_fx()
1036 : *
1037 : *---------------------------------------------------------------------*/
1038 18535 : Word16 mean_fx( /* o : mean of vector */
1039 : const Word16 *vec_fx, /* i : input vector */
1040 : const Word16 lvec_fx /* i : length of input vector */
1041 : )
1042 : {
1043 : Word16 tmp;
1044 : // PMT("TBV : this function could be written differently to minimize the risk of saturation");
1045 18535 : tmp = sum16_fx( vec_fx, lvec_fx );
1046 18535 : tmp = mult_r( tmp, div_s( 1, lvec_fx ) );
1047 :
1048 18535 : return tmp;
1049 : }
1050 :
1051 0 : Word16 mean_no_sat_fx( /* o : mean of vector Qx */
1052 : const Word16 *vec_fx, /* i : input vector Qx */
1053 : const Word16 lvec_fx /* i : length of input vector */
1054 : )
1055 : {
1056 : Word16 i;
1057 0 : Word32 L_tmp = 0;
1058 0 : move32();
1059 0 : FOR( i = 0; i < lvec_fx; ++i )
1060 : {
1061 0 : L_tmp = L_add( L_tmp, vec_fx[i] );
1062 : }
1063 0 : L_tmp = Mpy_32_16_1( L_tmp, div_s( 1, lvec_fx ) ); /* Qx */
1064 :
1065 0 : return extract_l( L_tmp );
1066 : }
1067 0 : Word32 mean_no_sat_Word32_fx( /* o : mean of vector Qx */
1068 : const Word32 *vec_fx, /* i : input vector Qx */
1069 : const Word16 lvec_fx, /* i : length of input vector */
1070 : const Word16 gb )
1071 : {
1072 : Word16 i;
1073 0 : Word32 L_tmp = 0;
1074 0 : move32();
1075 0 : FOR( i = 0; i < lvec_fx; ++i )
1076 : {
1077 0 : L_tmp = L_add( L_tmp, L_shr( vec_fx[i], gb ) );
1078 : }
1079 0 : L_tmp = Mpy_32_16_1( L_tmp, div_s( 1, lvec_fx ) ); /* Qx-gb */
1080 :
1081 0 : return L_tmp;
1082 : }
1083 : /*-------------------------------------------------------------------*
1084 : * Vr_add
1085 : *
1086 : * Add two Word16 vectors together integer by integer
1087 : *-------------------------------------------------------------------*/
1088 855698 : void Vr_add(
1089 : const Word16 *in1, /* i : Input vector 1 */
1090 : const Word16 *in2, /* i : Input vector 2 */
1091 : Word16 *out, /* o : Output vector that contains vector 1 + vector 2 */
1092 : Word16 Len /* i : Vector lenght */
1093 : )
1094 : {
1095 : Word16 i;
1096 :
1097 37111250 : FOR( i = 0; i < Len; i++ )
1098 : {
1099 36255552 : out[i] = add_sat( in1[i], in2[i] );
1100 36255552 : move16();
1101 : }
1102 855698 : }
1103 :
1104 349424 : void sort_fx(
1105 : Word16 *r, /* i/o: Vector to be sorted in place */
1106 : Word16 lo, /* i : Low limit of sorting range */
1107 : Word16 up /* I : High limit of sorting range */
1108 : )
1109 : {
1110 : Word16 i, j, i1;
1111 : Word16 tempr;
1112 :
1113 5585534 : FOR( i = sub( up, 1 ); i >= lo; i-- )
1114 : {
1115 5236110 : i1 = add( i, 1 );
1116 5236110 : tempr = r[i];
1117 5236110 : move16();
1118 5236110 : move16(); /*supplementary move for the j-1 PTR initialization*/
1119 5241958 : FOR( j = i1; j <= up; j++ )
1120 : {
1121 5241410 : IF( LE_16( tempr, r[j] ) )
1122 : {
1123 5235562 : BREAK;
1124 : }
1125 :
1126 5848 : r[j - 1] = r[j];
1127 5848 : move16();
1128 : }
1129 5236110 : r[j - 1] = tempr;
1130 5236110 : move16();
1131 : }
1132 349424 : }
1133 :
1134 0 : void sort_32_fx(
1135 : Word32 *r, /* i/o: Vector to be sorted in place */
1136 : const Word16 lo, /* i : Low limit of sorting range */
1137 : const Word16 up /* I : High limit of sorting range */
1138 : )
1139 : {
1140 : Word16 i, j;
1141 : Word32 tempr;
1142 0 : FOR( i = sub( up, 1 ); i >= lo; i-- )
1143 : {
1144 0 : tempr = r[i];
1145 0 : move32();
1146 0 : FOR( j = add( i, 1 ); j <= up; j++ )
1147 : {
1148 0 : IF( LE_32( tempr, r[j] ) )
1149 : {
1150 0 : BREAK;
1151 : }
1152 0 : r[j - 1] = r[j];
1153 0 : move32();
1154 : }
1155 :
1156 0 : r[j - 1] = tempr;
1157 0 : move32();
1158 : }
1159 :
1160 0 : return;
1161 : }
1162 :
1163 307894 : Word16 minimum_fx( /* o : index of the minimum value in the input vector */
1164 : const Word16 *vec_fx, /* i : input vector */
1165 : const Word16 lvec_fx, /* i : length of input vector */
1166 : Word16 *min_fx /* o : minimum value in the input vector */
1167 : )
1168 : {
1169 : Word16 j, ind;
1170 : Word16 tmp;
1171 307894 : ind = 0;
1172 307894 : move16();
1173 307894 : tmp = vec_fx[0];
1174 307894 : move16();
1175 :
1176 2905900 : FOR( j = 1; j < lvec_fx; j++ )
1177 : {
1178 2598006 : if ( LT_16( vec_fx[j], tmp ) )
1179 : {
1180 489137 : ind = j;
1181 489137 : move16();
1182 : /*tmp = vec_fx[j]; move16(); */
1183 : }
1184 2598006 : tmp = s_min( tmp, vec_fx[j] );
1185 : }
1186 :
1187 307894 : *min_fx = tmp;
1188 307894 : move16();
1189 :
1190 307894 : return ind;
1191 : }
1192 :
1193 1804863 : Word16 maximum_fx( /* o : index of the maximum value in the input vector */
1194 : const Word16 *vec_fx, /* i : input vector */
1195 : const Word16 lvec_fx, /* i : length of input vector */
1196 : Word16 *max_fx /* o : maximum value in the input vector */
1197 : )
1198 : {
1199 : Word16 j, ind;
1200 : Word16 tmp;
1201 1804863 : ind = 0;
1202 1804863 : move16();
1203 1804863 : tmp = vec_fx[0];
1204 1804863 : move16();
1205 :
1206 66487281 : FOR( j = 1; j < lvec_fx; j++ )
1207 : {
1208 64682418 : if ( GT_16( vec_fx[j], tmp ) )
1209 : {
1210 1926867 : ind = j;
1211 1926867 : move16();
1212 : }
1213 64682418 : tmp = s_max( tmp, vec_fx[j] );
1214 : }
1215 1804863 : *max_fx = tmp;
1216 1804863 : move16();
1217 :
1218 1804863 : return ind;
1219 : }
1220 :
1221 0 : Word16 maximum_exp_fx( /* o : index of the maximum value in the input vector */
1222 : const Word16 *vec_fx, /* i : input vector */
1223 : const Word16 *exp_vec, /* i : exponents of input vector */
1224 : const Word16 lvec_fx /* i : length of input vector */
1225 : )
1226 : {
1227 : Word16 j, ind;
1228 : Word16 tmp, exp;
1229 0 : ind = 0;
1230 0 : move16();
1231 0 : tmp = vec_fx[0];
1232 0 : move16();
1233 0 : exp = exp_vec[0];
1234 0 : move16();
1235 :
1236 0 : FOR( j = 1; j < lvec_fx; j++ )
1237 : {
1238 0 : IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) )
1239 : {
1240 0 : ind = j;
1241 0 : move16();
1242 0 : tmp = vec_fx[j];
1243 0 : move16();
1244 0 : exp = exp_vec[j];
1245 0 : move16();
1246 : }
1247 : }
1248 :
1249 0 : return ind;
1250 : }
1251 :
1252 : /*---------------------------------------------------------------------*
1253 : * maximum_abs_16_fx()
1254 : *
1255 : * Find index and value of the absolute maximum in a vector
1256 : *---------------------------------------------------------------------*/
1257 :
1258 1403 : Word16 maximum_abs_16_fx( /* o : index of the maximum abs value in the input vector */
1259 : const Word16 *vec, /* i : input vector */
1260 : const Word16 lvec, /* i : length of input vector */
1261 : Word16 *max_val /* o : maximum value in the input vector */
1262 : )
1263 : {
1264 : Word16 j, ind;
1265 : Word16 tmp;
1266 1403 : ind = 0;
1267 1403 : move16();
1268 1403 : tmp = abs_s( vec[0] );
1269 :
1270 530192 : FOR( j = 1; j < lvec; j++ )
1271 : {
1272 528789 : if ( GT_16( abs_s( vec[j] ), tmp ) )
1273 : {
1274 2843 : ind = j;
1275 2843 : move16();
1276 : }
1277 528789 : tmp = s_max( tmp, abs_s( vec[j] ) );
1278 : }
1279 1403 : *max_val = tmp;
1280 1403 : move16();
1281 :
1282 1403 : return ind;
1283 : }
1284 :
1285 : /*---------------------------------------------------------------------*
1286 : * minimum_abs32_fx()
1287 : *
1288 : * Find index and value of the absolute minimum in a vector
1289 : *---------------------------------------------------------------------*/
1290 0 : Word16 minimum_abs32_fx( /* o : index of the minimum value in the input vector */
1291 : const Word32 *vec_fx, /* i : input vector */
1292 : const Word16 lvec_fx, /* i : length of input vector */
1293 : Word32 *min_fx /* o : minimum value in the input vector */
1294 : )
1295 : {
1296 : Word16 j, ind;
1297 : Word32 tmp;
1298 0 : ind = 0;
1299 0 : move16();
1300 0 : tmp = vec_fx[0];
1301 0 : move16();
1302 :
1303 0 : FOR( j = 1; j < lvec_fx; j++ )
1304 : {
1305 0 : IF( LT_32( L_abs( vec_fx[j] ), tmp ) )
1306 : {
1307 0 : ind = j;
1308 0 : move16();
1309 : /*tmp = vec_fx[j]; move16(); */
1310 : }
1311 0 : tmp = L_min( tmp, L_abs( vec_fx[j] ) );
1312 : }
1313 :
1314 0 : *min_fx = tmp;
1315 0 : move16();
1316 :
1317 0 : return ind;
1318 : }
1319 :
1320 : /*---------------------------------------------------------------------*
1321 : * minimum_32_fx()
1322 : *
1323 : * Find index and value of the minimum in a vector
1324 : *---------------------------------------------------------------------*/
1325 :
1326 2 : Word16 minimum_32_fx( /* o : index of the minimum value in the input vector */
1327 : const Word32 *vec_fx, /* i : input vector */
1328 : const Word16 lvec_fx, /* i : length of input vector */
1329 : Word32 *min_fx /* o : minimum value in the input vector */
1330 : )
1331 : {
1332 : Word16 j, ind;
1333 : Word32 tmp;
1334 2 : ind = 0;
1335 2 : move16();
1336 2 : tmp = vec_fx[0];
1337 2 : move16();
1338 :
1339 8 : FOR( j = 1; j < lvec_fx; j++ )
1340 : {
1341 6 : if ( LT_32( vec_fx[j], tmp ) )
1342 : {
1343 0 : ind = j;
1344 0 : move16();
1345 : /*tmp = vec_fx[j]; move32(); */
1346 : }
1347 6 : tmp = L_min( tmp, vec_fx[j] );
1348 : }
1349 2 : if ( min_fx != NULL )
1350 : {
1351 2 : *min_fx = tmp;
1352 : }
1353 2 : move32();
1354 :
1355 2 : return ind;
1356 : }
1357 :
1358 : /*---------------------------------------------------------------------*
1359 : * maximum_32_fx()
1360 : *
1361 : * Find index and value of the maximum in a vector
1362 : *---------------------------------------------------------------------*/
1363 :
1364 480194 : Word16 maximum_32_fx( /* o : index of the maximum value in the input vector */
1365 : const Word32 *vec, /* i : input vector */
1366 : const Word16 lvec, /* i : length of input vector */
1367 : Word32 *max_val /* o : maximum value in the input vector */
1368 : )
1369 : {
1370 : Word16 j, ind;
1371 : Word32 tmp;
1372 480194 : ind = 0;
1373 480194 : move16();
1374 480194 : tmp = vec[0];
1375 480194 : move16();
1376 :
1377 8115492 : FOR( j = 1; j < lvec; j++ )
1378 : {
1379 7635298 : IF( GT_32( vec[j], tmp ) )
1380 : {
1381 362744 : ind = j;
1382 362744 : move16();
1383 : }
1384 7635298 : tmp = L_max( tmp, vec[j] );
1385 : }
1386 480194 : if ( max_val != NULL )
1387 : {
1388 480194 : *max_val = tmp;
1389 : }
1390 480194 : move32();
1391 :
1392 480194 : return ind;
1393 : }
1394 :
1395 2191440 : Word16 maximum_abs_32_fx( /* o : index of the maximum abs value in the input vector */
1396 : const Word32 *vec, /* i : input vector */
1397 : const Word16 lvec, /* i : length of input vector */
1398 : Word32 *max_val /* o : maximum value in the input vector */
1399 : )
1400 : {
1401 : Word16 j, ind;
1402 : Word32 tmp;
1403 2191440 : ind = 0;
1404 2191440 : move16();
1405 2191440 : tmp = L_abs( vec[0] );
1406 :
1407 613761202 : FOR( j = 1; j < lvec; j++ )
1408 : {
1409 611569762 : if ( GT_32( L_abs( vec[j] ), tmp ) )
1410 : {
1411 3341042 : ind = j;
1412 3341042 : move16();
1413 : }
1414 611569762 : tmp = L_max( tmp, L_abs( vec[j] ) );
1415 : }
1416 2191440 : *max_val = tmp;
1417 2191440 : move32();
1418 :
1419 2191440 : return ind;
1420 : }
1421 :
1422 :
1423 : /*----------------------------------------------------------------
1424 : *Function:
1425 : *Finds number of shifts to normalize a 16-bit array variable.
1426 : *Return value
1427 : *Number of shifts
1428 : *----------------------------------------------------------------*/
1429 26931 : Word16 Exp16Array(
1430 : const Word16 n, /* (i): Array size */
1431 : const Word16 *sx /* (i): Data array */
1432 : )
1433 : {
1434 : Word16 k;
1435 : Word16 exp;
1436 : Word16 sMax;
1437 : Word16 sAbs;
1438 :
1439 26931 : sMax = abs_s( sx[0] );
1440 26931 : move16();
1441 :
1442 1801856 : FOR( k = 1; k < n; k++ )
1443 : {
1444 1774925 : sAbs = abs_s( sx[k] );
1445 1774925 : sMax = s_max( sMax, sAbs );
1446 : }
1447 :
1448 26931 : exp = norm_s( sMax );
1449 26931 : return exp;
1450 : }
1451 :
1452 0 : Word16 Exp32Array(
1453 : const Word16 n, /* (i): Array size */
1454 : const Word32 *sx /* (i): Data array */
1455 : )
1456 : {
1457 : Word16 k;
1458 : Word16 exp;
1459 : Word32 L_Max;
1460 : Word32 L_Abs;
1461 :
1462 0 : L_Max = L_abs( sx[0] );
1463 0 : FOR( k = 1; k < n; k++ )
1464 : {
1465 0 : L_Abs = L_abs( sx[k] );
1466 0 : L_Max = L_max( L_Max, L_Abs );
1467 : }
1468 0 : exp = norm_l( L_Max );
1469 :
1470 0 : if ( L_Max == 0 )
1471 : {
1472 0 : exp = 31;
1473 0 : move16();
1474 : }
1475 0 : return exp;
1476 : }
1477 :
1478 4754 : Word32 sum16_32_fx( /* o : sum of all vector elements Qx*/
1479 : const Word16 *vec, /* i : input vector Qx*/
1480 : const Word16 lvec /* i : length of input vector */
1481 : )
1482 : {
1483 : Word16 i;
1484 : Word32 tmp, L_var;
1485 4754 : tmp = 0;
1486 4754 : move16();
1487 24788 : FOR( i = 0; i < lvec; i++ )
1488 : {
1489 20034 : L_var = L_deposit_l( vec[i] );
1490 20034 : tmp = L_add( tmp, L_var ); /*Qx */
1491 : }
1492 :
1493 4754 : return tmp;
1494 : }
1495 :
1496 1803 : Word32 sum32_sat( /* o : sum of all vector elements Qx*/
1497 : const Word32 *vec, /* i : input vector Qx*/
1498 : const Word16 lvec /* i : length of input vector */
1499 : )
1500 : {
1501 : Word16 i;
1502 : Word32 tmp;
1503 1803 : tmp = 0;
1504 1803 : move16();
1505 117195 : FOR( i = 0; i < lvec; i++ )
1506 : {
1507 115392 : tmp = L_add_sat( tmp, vec[i] ); /*Qx */
1508 : }
1509 :
1510 1803 : return tmp;
1511 : }
1512 :
1513 0 : Word32 var_fx_32( /* o: variance of vector Qx+16*/
1514 : const Word16 *x, /* i: input vector Qx*/
1515 : const Word16 Qx,
1516 : const Word16 len /* i: length of inputvector */
1517 : )
1518 : {
1519 : Word16 m;
1520 : Word32 v;
1521 : Word16 i;
1522 : Word16 tmp, exp, inv_len;
1523 : Word32 L_tmp;
1524 :
1525 :
1526 0 : L_tmp = L_add( x[0], 0 );
1527 0 : FOR( i = 1; i < len; i++ )
1528 : {
1529 0 : L_tmp = L_add( L_tmp, x[i] ); /*Qx */
1530 : }
1531 0 : exp = norm_s( len );
1532 0 : inv_len = div_s( shl( 1, sub( 14, exp ) ), len ); /*Q(29-exp) */
1533 0 : L_tmp = Mult_32_16( L_tmp, inv_len ); /*Q(14-exp+Qx) */
1534 0 : m = round_fx( L_shl( L_tmp, add( exp, 2 ) ) ); /*Qx */
1535 :
1536 0 : v = L_deposit_l( 0 );
1537 0 : FOR( i = 0; i < len; i++ )
1538 : {
1539 0 : tmp = sub( x[i], m ); /*Qx */
1540 0 : v = L_mac0_sat( v, tmp, tmp ); /*(Qx+Qx) */
1541 : }
1542 0 : L_tmp = Mult_32_16( v, inv_len ); /*Q(14-exp+Qx+Qx) */
1543 0 : v = L_shl( L_tmp, add( exp, sub( 2, Qx ) ) ); /*Qx+16 */
1544 :
1545 0 : return v;
1546 : }
1547 :
1548 0 : Word32 var_fx_32in_32out( /* o: variance of vector Qx*/
1549 : const Word32 *x, /* i: input vector Qx*/
1550 : Word16 *Qx, /*i/o:Q for input/output */
1551 : const Word16 len, /* i: length of inputvector */
1552 : const Word16 gb )
1553 : {
1554 : Word16 i;
1555 : Word16 shift;
1556 : Word32 L_tmp1, L_tmp;
1557 : Word64 W_temp;
1558 :
1559 0 : L_tmp = mean_no_sat_Word32_fx( x, len, gb ); /*Qx-gb */
1560 0 : W_temp = 0;
1561 0 : FOR( i = 0; i < len; i++ )
1562 : {
1563 0 : L_tmp1 = L_sub( L_shr( x[i], gb ), L_tmp ); /*Qx-gb */
1564 0 : W_temp = W_add( W_temp, W_mult0_32_32( L_tmp1, L_tmp1 ) ); /*Qx-gb +Qx-gb*/
1565 : }
1566 0 : shift = W_norm( W_temp );
1567 0 : L_tmp = Mult_32_16( W_extract_h( W_shl( W_temp, shift ) ), div_s( 1, len ) ); /*Q2*(Qx-gb)+shift -32 */
1568 :
1569 0 : *Qx = sub( add( shl( sub( *Qx, gb ), 1 ), shift ), 32 );
1570 0 : move16();
1571 0 : return L_tmp;
1572 : }
1573 : /*-------------------------------------------------------------------*
1574 : * conv()
1575 : *
1576 : * Convolution between vectors x[] and h[] written to y[]
1577 : * All vectors are of length L. Only the first L samples of the
1578 : * convolution are considered.
1579 : *-------------------------------------------------------------------*/
1580 :
1581 0 : Flag conv_fx(
1582 : const Word16 x[], /* i : input vector Q_new*/
1583 : const Word16 h[], /* i : impulse response (or second input vector) Q(15)*/
1584 : Word16 y[], /* o : output vetor (result of convolution) 12 bits*/
1585 : const Word16 L /* i : vector size */
1586 : )
1587 : {
1588 :
1589 : Word16 i, n;
1590 : Word32 L_sum;
1591 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1592 0 : Flag Overflow = 0;
1593 0 : move32();
1594 : #endif
1595 0 : y[0] = mult_r( x[0], h[0] );
1596 0 : move16();
1597 0 : FOR( n = 1; n < L; n++ )
1598 : {
1599 0 : L_sum = L_mult( x[0], h[n] );
1600 0 : FOR( i = 1; i < n; i++ )
1601 : {
1602 0 : L_sum = L_mac_o( L_sum, x[i], h[n - i], &Overflow );
1603 : }
1604 0 : y[n] = mac_ro( L_sum, x[i], h[0], &Overflow );
1605 0 : move16();
1606 : }
1607 0 : return Overflow;
1608 : }
1609 :
1610 : /*-------------------------------------------------------------------*
1611 : * conv_fx_32()
1612 : *
1613 : * Convolution between vectors x[] and h[] written to y[]
1614 : * All vectors are of length L. Only the first L samples of the
1615 : * convolution are considered.
1616 : *-------------------------------------------------------------------*/
1617 2474 : Flag conv_fx_32(
1618 : const Word16 x[], /* i : input vector Q_new*/
1619 : const Word16 h[], /* i : impulse response (or second input vector) Q(15)*/
1620 : Word32 y[], /* o : output vetor (result of convolution) 12 bits*/
1621 : const Word16 L /* i : vector size */
1622 : )
1623 : {
1624 :
1625 : Word16 i, n;
1626 : Word32 L_sum;
1627 2474 : Flag Overflow = 0;
1628 2474 : y[0] = L_mult( x[0], h[0] );
1629 2474 : move32();
1630 44532 : FOR( n = 1; n < L; n++ )
1631 : {
1632 42058 : L_sum = L_mult( x[0], h[n] );
1633 378522 : FOR( i = 1; i < n; i++ )
1634 : {
1635 336464 : L_sum = L_mac_o( L_sum, x[i], h[n - i], &Overflow );
1636 : }
1637 42058 : y[n] = L_mac_o( L_sum, x[i], h[0], &Overflow );
1638 42058 : move32();
1639 : }
1640 2474 : return Overflow;
1641 : }
1642 0 : Word16 var_fx( /* o: variance of vector Qx*/
1643 : const Word16 *x, /* i: input vector Qx*/
1644 : const Word16 Qx,
1645 : const Word16 len /* i: length of inputvector */
1646 : )
1647 : {
1648 : Word16 m;
1649 : Word32 v;
1650 : Word16 v_16;
1651 : Word16 i;
1652 : Word16 tmp, exp, inv_len;
1653 : Word32 L_tmp;
1654 :
1655 0 : L_tmp = x[0];
1656 0 : move32();
1657 0 : FOR( i = 1; i < len; i++ )
1658 : {
1659 0 : L_tmp = L_add( L_tmp, x[i] ); /*Qx */
1660 : }
1661 0 : exp = norm_s( len );
1662 0 : inv_len = div_s( shl( 1, sub( 14, exp ) ), len ); /*Q(29-exp) */
1663 0 : L_tmp = Mult_32_16( L_tmp, inv_len ); /*Q(14-exp+Qx) */
1664 0 : m = round_fx( L_shl( L_tmp, add( exp, 2 ) ) ); /*Qx */
1665 :
1666 0 : v = L_deposit_l( 0 );
1667 0 : FOR( i = 0; i < len; i++ )
1668 : {
1669 0 : tmp = sub_sat( x[i], m ); /*Qx */
1670 0 : v = L_mac0_sat( v, tmp, tmp ); /*(Qx+Qx) */
1671 : }
1672 0 : L_tmp = Mult_32_16( v, inv_len ); /*Q(14-exp+Qx+Qx) */
1673 0 : v_16 = round_fx_sat( L_shl_sat( L_tmp, add( exp, sub( 2, Qx ) ) ) ); /*Qx */
1674 :
1675 0 : return v_16;
1676 : }
1677 :
1678 : /*---------------------------------------------------------------------*
1679 : * std_fx()
1680 : *
1681 : * Calculate the standard deviation of a vector
1682 : *---------------------------------------------------------------------*/
1683 :
1684 0 : Word16 std_fx( /* o: standard deviation */
1685 : const Word16 x[], /* i: input vector */
1686 : const Word16 len /* i: length of the input vector */
1687 : )
1688 : {
1689 : Word16 i;
1690 : Word32 L_tmp;
1691 : Word16 exp1, exp2, tmp;
1692 : Word32 stdev;
1693 :
1694 0 : stdev = 0;
1695 0 : move16();
1696 0 : FOR( i = 0; i < len; i++ )
1697 : {
1698 0 : L_tmp = L_mult( x[i], x[i] ); /*29 */
1699 0 : stdev = L_add( stdev, L_shr( L_tmp, 3 ) ); /*26 */
1700 : }
1701 :
1702 0 : IF( stdev != 0 )
1703 : {
1704 0 : exp1 = norm_l( stdev );
1705 0 : tmp = div_s( 16384, extract_h( L_shl( stdev, exp1 ) ) ); /*15 + 14 - (26 + exp1 - 16) */
1706 0 : L_tmp = L_mult( tmp, len ); /*15 + 14 - (26 + exp1 - 16) + 1 */
1707 0 : exp2 = norm_l( L_tmp );
1708 0 : exp1 = add( sub( exp1, exp2 ), 11 );
1709 0 : stdev = Isqrt_lc( L_shl( L_tmp, exp2 ), &exp1 ); /*31-exp1 */
1710 0 : stdev = L_shl( stdev, sub( exp1, 1 ) ); /*30 */
1711 : }
1712 :
1713 :
1714 0 : return extract_h( stdev );
1715 : }
1716 :
1717 0 : Word32 dot_product_mat_fx( /* o : the dot product x'*A*x */
1718 : const Word16 *x, /* i : vector x Q15 */
1719 : const Word32 *A, /* i : matrix A Q0*/
1720 : const Word16 m /* i : vector & matrix size */
1721 :
1722 : )
1723 : {
1724 : Word16 i, j;
1725 : Word64 tmp_sum_64;
1726 : Word32 suma, tmp_sum;
1727 : const Word32 *pt_A;
1728 : const Word16 *pt_x;
1729 :
1730 0 : pt_A = A;
1731 0 : suma = L_deposit_l( 0 );
1732 :
1733 0 : FOR( i = 0; i < m; i++ )
1734 : {
1735 0 : tmp_sum_64 = 0;
1736 0 : move64();
1737 0 : pt_x = x;
1738 0 : FOR( j = 0; j < m; j++ )
1739 : {
1740 0 : tmp_sum_64 = W_mac_32_16( tmp_sum_64, *pt_A, *pt_x ); /*Q0 */
1741 0 : pt_A++;
1742 0 : pt_x++;
1743 : }
1744 0 : tmp_sum = W_sat_m( tmp_sum_64 );
1745 0 : suma = Madd_32_16( suma, tmp_sum, x[i] ); /*Q0 */
1746 : }
1747 0 : return suma;
1748 : }
1749 : /*-------------------------------------------------------------------*
1750 : * Vr_subt
1751 : *
1752 : * Subtract two Word16 vectors integer by integer
1753 : *-------------------------------------------------------------------*/
1754 81212 : void Vr_subt(
1755 : const Word16 x1[], /* i : Input vector 1 */
1756 : const Word16 x2[], /* i : Input vector 2 */
1757 : Word16 y[], /* o : Output vector that contains vector 1 - vector 2 */
1758 : Word16 N /* i : Vector lenght */
1759 : )
1760 : {
1761 : Word16 i;
1762 :
1763 1420780 : FOR( i = 0; i < N; i++ )
1764 : {
1765 1339568 : y[i] = sub_sat( x1[i], x2[i] );
1766 1339568 : move16();
1767 : }
1768 81212 : }
1769 : /*-------------------------------------------------------------------*
1770 : * vquant()
1771 : *
1772 : * Vector quantizer according to MMSE criterion (nearest neighbour in Euclidean space)
1773 : *
1774 : * Searches a given codebook to find the nearest neighbour in Euclidean space.
1775 : * Index of the winning codevector and the winning vector itself are returned.
1776 : *-------------------------------------------------------------------*/
1777 0 : Word16 vquant_ivas_fx( /* o: index of the winning codevector */
1778 : Word32 x[], /* i: vector to quantize Q25 */
1779 : const Word32 x_mean[], /* i: vector mean to subtract (0 if none) Q25 */
1780 : Word32 xq[], /* o: quantized vector Q25 */
1781 : const Word32 cb[], /* i: codebook Q25 */
1782 : const Word16 dim, /* i: dimension of codebook vectors */
1783 : const Word16 cbsize /* i: codebook size */
1784 : )
1785 : {
1786 : Word16 c, d, idx, j;
1787 : Word32 L_dist, L_tmp, L_mindist;
1788 :
1789 0 : idx = 0;
1790 0 : move16();
1791 0 : L_mindist = MAX_32;
1792 0 : move32();
1793 0 : IF( x_mean != 0 )
1794 : {
1795 0 : FOR( d = 0; d < dim; d++ )
1796 : {
1797 : /*x[d] -= x_mean[d]; */
1798 0 : x[d] = L_sub( x[d], x_mean[d] );
1799 0 : move32(); /*Qx */
1800 : }
1801 : }
1802 0 : j = 0;
1803 0 : move16();
1804 0 : FOR( c = 0; c < cbsize; c++ )
1805 : {
1806 0 : L_dist = 0;
1807 0 : move32();
1808 :
1809 0 : FOR( d = 0; d < dim; d++ )
1810 : {
1811 : /*tmp = x[d] - cb[j++];*/
1812 0 : L_tmp = L_sub( x[d], cb[j++] ); // Q25
1813 0 : L_dist = L_add( L_dist, Mpy_32_32( L_tmp, L_tmp ) ); // (Q25, Q25) -> Q19
1814 : }
1815 0 : if ( LT_32( L_dist, L_mindist ) ) // Q19
1816 : {
1817 0 : idx = c;
1818 0 : move16();
1819 : }
1820 0 : L_mindist = L_min( L_mindist, L_dist ); // Q19
1821 : }
1822 0 : IF( xq == 0 )
1823 : {
1824 0 : return idx;
1825 : }
1826 :
1827 : /*j = idx*dim;*/
1828 0 : j = i_mult2( idx, dim );
1829 0 : FOR( d = 0; d < dim; d++ )
1830 : {
1831 0 : xq[d] = cb[j++]; // Q25
1832 0 : move32();
1833 : }
1834 0 : IF( x_mean != 0 )
1835 : {
1836 0 : FOR( d = 0; d < dim; d++ )
1837 : {
1838 : /*xq[d] += x_mean[d]; */
1839 0 : xq[d] = L_add( xq[d], x_mean[d] ); // Q25
1840 0 : move32();
1841 : }
1842 : }
1843 :
1844 0 : return idx;
1845 : }
1846 :
1847 0 : Word16 vquant_fx( /* o: index of the winning codevector */
1848 : Word16 x[], /* i: vector to quantize Q13 */
1849 : const Word16 x_mean[], /* i: vector mean to subtract (0 if none) Q13 */
1850 : Word16 xq[], /* o: quantized vector Q13 */
1851 : const Word16 cb[], /* i: codebook Q13 */
1852 : const Word16 dim, /* i: dimension of codebook vectors */
1853 : const Word16 cbsize /* i: codebook size */
1854 : )
1855 : {
1856 : Word16 tmp;
1857 : Word16 c, d, idx, j;
1858 : Word32 L_dist, /*L_tmp,*/ L_mindist;
1859 :
1860 0 : idx = 0;
1861 0 : move16();
1862 0 : L_mindist = MAX_32;
1863 0 : move32();
1864 0 : IF( x_mean != 0 )
1865 : {
1866 0 : FOR( d = 0; d < dim; d++ )
1867 : {
1868 : /*x[d] -= x_mean[d]; */
1869 0 : x[d] = sub( x[d], x_mean[d] );
1870 0 : move16(); /*Qx */
1871 : }
1872 : }
1873 0 : j = 0;
1874 0 : move16();
1875 0 : FOR( c = 0; c < cbsize; c++ )
1876 : {
1877 0 : L_dist = 0;
1878 0 : move32();
1879 :
1880 0 : FOR( d = 0; d < dim; d++ )
1881 : {
1882 : /*tmp = x[d] - cb[j++];*/
1883 0 : tmp = sub( x[d], cb[j++] ); /*Qx */
1884 0 : L_dist = L_mac0( L_dist, tmp, tmp );
1885 : }
1886 0 : if ( LT_32( L_dist, L_mindist ) )
1887 : {
1888 0 : idx = c;
1889 0 : move16();
1890 : }
1891 0 : L_mindist = L_min( L_mindist, L_dist );
1892 : }
1893 0 : IF( xq == 0 )
1894 : {
1895 0 : return idx;
1896 : }
1897 :
1898 : /*j = idx*dim;*/
1899 0 : j = i_mult2( idx, dim );
1900 0 : FOR( d = 0; d < dim; d++ )
1901 : {
1902 0 : xq[d] = cb[j++];
1903 0 : move16();
1904 : }
1905 0 : IF( x_mean != 0 )
1906 : {
1907 0 : FOR( d = 0; d < dim; d++ )
1908 : {
1909 : /*xq[d] += x_mean[d]; */
1910 0 : xq[d] = add( xq[d], x_mean[d] );
1911 0 : move16();
1912 : }
1913 : }
1914 :
1915 0 : return idx;
1916 : }
1917 :
1918 : /*-------------------------------------------------------------------*
1919 : * w_vquant_fx()
1920 : *
1921 : * Vector quantizer according to MMSE criterion (nearest neighbour in Euclidean space)
1922 : *
1923 : * Searches a given codebook to find the nearest neighbour in Euclidean space.
1924 : * Weights are put on the error for each vector element.
1925 : * Index of the winning codevector and the winning vector itself are returned.
1926 : *-------------------------------------------------------------------*/
1927 0 : Word16 w_vquant_fx(
1928 : Word16 x[], /* i: vector to quantize in Q10 */
1929 : Word16 Qx,
1930 : const Word16 weights[], /* i: error weights in Q0 */
1931 : Word16 xq[], /* o: quantized vector in Q15 */
1932 : const Word16 cb[], /* i: codebook in Q15 */
1933 : const Word16 cbsize, /* i: codebook size */
1934 : const Word16 rev_vect /* i: reverse codebook vectors */
1935 : )
1936 : {
1937 : Word16 tmp;
1938 : Word16 c, idx, j;
1939 : Word32 dist, minDist;
1940 : #ifndef ISSUE_1836_replace_overflow_libcom
1941 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1942 : Flag Overflow = 0;
1943 : move32();
1944 : #endif
1945 : #endif
1946 :
1947 :
1948 0 : idx = 0;
1949 0 : move16();
1950 0 : minDist = 0x7fffffffL;
1951 0 : move32();
1952 0 : Qx = sub( 15, Qx );
1953 :
1954 0 : j = 0;
1955 0 : move16();
1956 0 : IF( rev_vect )
1957 : {
1958 0 : FOR( c = 0; c < cbsize; c++ )
1959 : {
1960 0 : dist = L_deposit_l( 0 );
1961 :
1962 : #ifdef ISSUE_1836_replace_overflow_libcom
1963 0 : tmp = sub_sat( x[3], shr( cb[j++], Qx ) );
1964 0 : if ( weights[3] != 0 )
1965 : {
1966 0 : dist = L_mac0_sat( dist, tmp, tmp );
1967 : }
1968 0 : tmp = sub_sat( x[2], shr( cb[j++], Qx ) );
1969 0 : if ( weights[2] != 0 )
1970 : {
1971 0 : dist = L_mac0_sat( dist, tmp, tmp );
1972 : }
1973 0 : tmp = sub_sat( x[1], shr( cb[j++], Qx ) );
1974 0 : if ( weights[1] != 0 )
1975 : {
1976 0 : dist = L_mac0_sat( dist, tmp, tmp );
1977 : }
1978 0 : tmp = sub_sat( x[0], shr( cb[j++], Qx ) );
1979 0 : if ( weights[0] != 0 )
1980 : {
1981 0 : dist = L_mac0_sat( dist, tmp, tmp );
1982 : }
1983 : #else
1984 : tmp = sub_o( x[3], shr( cb[j++], Qx ), &Overflow );
1985 : if ( weights[3] != 0 )
1986 : {
1987 : dist = L_mac0_o( dist, tmp, tmp, &Overflow );
1988 : }
1989 : tmp = sub_o( x[2], shr( cb[j++], Qx ), &Overflow );
1990 : if ( weights[2] != 0 )
1991 : {
1992 : dist = L_mac0_o( dist, tmp, tmp, &Overflow );
1993 : }
1994 : tmp = sub_o( x[1], shr( cb[j++], Qx ), &Overflow );
1995 : if ( weights[1] != 0 )
1996 : {
1997 : dist = L_mac0_o( dist, tmp, tmp, &Overflow );
1998 : }
1999 : tmp = sub_o( x[0], shr( cb[j++], Qx ), &Overflow );
2000 : if ( weights[0] != 0 )
2001 : {
2002 : dist = L_mac0_o( dist, tmp, tmp, &Overflow );
2003 : }
2004 : #endif
2005 0 : if ( LT_32( dist, minDist ) )
2006 : {
2007 0 : idx = c;
2008 0 : move16();
2009 : }
2010 0 : minDist = L_min( minDist, dist );
2011 : }
2012 :
2013 0 : IF( xq == 0 )
2014 : {
2015 0 : return idx;
2016 : }
2017 :
2018 0 : j = shl( idx, 2 );
2019 0 : xq[3] = cb[j++];
2020 0 : move16(); /* in Q15 */
2021 0 : xq[2] = cb[j++];
2022 0 : move16(); /* in Q15 */
2023 0 : xq[1] = cb[j++];
2024 0 : move16(); /* in Q15 */
2025 0 : xq[0] = cb[j++];
2026 0 : move16(); /* in Q15 */
2027 : }
2028 : ELSE
2029 : {
2030 0 : FOR( c = 0; c < cbsize; c++ )
2031 : {
2032 0 : dist = L_deposit_l( 0 );
2033 :
2034 : #ifdef ISSUE_1836_replace_overflow_libcom
2035 0 : tmp = sub_sat( x[0], shr( cb[j++], Qx ) );
2036 0 : if ( weights[0] != 0 )
2037 : {
2038 0 : dist = L_mac0_sat( dist, tmp, tmp );
2039 : }
2040 0 : tmp = sub_sat( x[1], shr( cb[j++], Qx ) );
2041 0 : if ( weights[1] != 0 )
2042 : {
2043 0 : dist = L_mac0_sat( dist, tmp, tmp );
2044 : }
2045 0 : tmp = sub_sat( x[2], shr( cb[j++], Qx ) );
2046 0 : if ( weights[2] != 0 )
2047 : {
2048 0 : dist = L_mac0_sat( dist, tmp, tmp );
2049 : }
2050 0 : tmp = sub_sat( x[3], shr( cb[j++], Qx ) );
2051 0 : if ( weights[3] != 0 )
2052 : {
2053 0 : dist = L_mac0_sat( dist, tmp, tmp );
2054 : }
2055 : #else
2056 : tmp = sub_o( x[0], shr( cb[j++], Qx ), &Overflow );
2057 : if ( weights[0] != 0 )
2058 : {
2059 : dist = L_mac0_o( dist, tmp, tmp, &Overflow );
2060 : }
2061 : tmp = sub_o( x[1], shr( cb[j++], Qx ), &Overflow );
2062 : if ( weights[1] != 0 )
2063 : {
2064 : dist = L_mac0_o( dist, tmp, tmp, &Overflow );
2065 : }
2066 : tmp = sub_o( x[2], shr( cb[j++], Qx ), &Overflow );
2067 : if ( weights[2] != 0 )
2068 : {
2069 : dist = L_mac0_o( dist, tmp, tmp, &Overflow );
2070 : }
2071 : tmp = sub_o( x[3], shr( cb[j++], Qx ), &Overflow );
2072 : if ( weights[3] != 0 )
2073 : {
2074 : dist = L_mac0_o( dist, tmp, tmp, &Overflow );
2075 : }
2076 : #endif
2077 0 : if ( LT_32( dist, minDist ) )
2078 : {
2079 0 : idx = c;
2080 0 : move16();
2081 : }
2082 0 : minDist = L_min( minDist, dist );
2083 : }
2084 :
2085 0 : IF( xq == 0 )
2086 : {
2087 0 : return idx;
2088 : }
2089 :
2090 0 : j = shl( idx, 2 );
2091 0 : xq[0] = cb[j++];
2092 0 : move16(); /* in Q15 */
2093 0 : xq[1] = cb[j++];
2094 0 : move16(); /* in Q15 */
2095 0 : xq[2] = cb[j++];
2096 0 : move16(); /* in Q15 */
2097 0 : xq[3] = cb[j++];
2098 0 : move16(); /* in Q15 */
2099 : }
2100 :
2101 0 : return idx;
2102 : }
2103 : /*-------------------------------------------------------------------*
2104 : * Emaximum:
2105 : *
2106 : * Find index of a maximum energy in a vector
2107 : *-------------------------------------------------------------------*/
2108 91377 : Word16 emaximum_fx( /* o : return index with max energy value in vector Q0 */
2109 : const Word16 Qvec, /* i : Q of input vector Q0 */
2110 : const Word16 *vec, /* i : input vector Qx */
2111 : const Word16 lvec, /* i : length of input vector Q0 */
2112 : Word32 *ener_max /* o : maximum energy value Q0 */
2113 : )
2114 : {
2115 : Word16 j, ind;
2116 : Word32 L_tmp, L_tmp1;
2117 : Word32 emax;
2118 :
2119 91377 : emax = L_mult0( vec[0], vec[0] );
2120 91377 : ind = 0;
2121 91377 : move16();
2122 :
2123 8475877 : FOR( j = 1; j < lvec; j++ )
2124 : {
2125 8384500 : L_tmp = L_mult0( vec[j], vec[j] );
2126 8384500 : L_tmp1 = L_sub( L_tmp, emax );
2127 8384500 : if ( L_tmp1 > 0 )
2128 : {
2129 664416 : ind = j;
2130 664416 : move16();
2131 : }
2132 8384500 : emax = L_max( emax, L_tmp );
2133 : }
2134 :
2135 91377 : *ener_max = L_shr_sat( emax, add( Qvec, Qvec ) );
2136 91377 : move32();
2137 :
2138 91377 : return ind;
2139 : }
2140 :
2141 0 : Word16 emaximum_32fx( /* o : return index with max energy value in vector Q0 */
2142 : const Word16 Qvec, /* i : Q of input vector Q0 */
2143 : const Word32 *vec, /* i : input vector Qx */
2144 : const Word16 lvec, /* i : length of input vector Q0 */
2145 : Word32 *ener_max /* o : maximum energy value Q0 */
2146 : )
2147 : {
2148 : Word16 j, ind;
2149 : Word64 W_tmp, W_tmp1;
2150 : Word64 emax;
2151 :
2152 0 : emax = W_mult0_32_32( vec[0], vec[0] );
2153 0 : ind = 0;
2154 0 : move16();
2155 :
2156 0 : FOR( j = 1; j < lvec; j++ )
2157 : {
2158 0 : W_tmp = W_mult0_32_32( vec[j], vec[j] );
2159 0 : W_tmp1 = W_sub( W_tmp, emax );
2160 0 : if ( W_tmp1 > 0 )
2161 : {
2162 0 : ind = j;
2163 0 : move16();
2164 : }
2165 0 : if ( LE_64( emax, W_tmp ) )
2166 : {
2167 0 : emax = W_tmp;
2168 0 : move64();
2169 : }
2170 : }
2171 :
2172 0 : *ener_max = W_extract_l( W_shr( emax, add( Qvec, Qvec ) ) );
2173 0 : move32();
2174 :
2175 0 : return ind;
2176 : }
2177 :
2178 : /*-------------------------------------------------------------------*
2179 : * mean32:
2180 : *
2181 : * Find the mean of a 32 bits vector
2182 : *-------------------------------------------------------------------*/
2183 0 : Word32 Mean32( /* o : mean of the elements of the vector */
2184 : const Word32 in[], /* i : input vector */
2185 : const Word16 L /* i : length of input vector */
2186 : )
2187 : {
2188 : Word32 Ltmp;
2189 : Word16 inv_L;
2190 :
2191 0 : inv_L = INV_BANDS9;
2192 0 : move16();
2193 0 : if ( EQ_16( L, 10 ) )
2194 : {
2195 0 : inv_L = INV_BANDS10;
2196 0 : move16();
2197 : }
2198 :
2199 0 : Ltmp = sum32_fx( in, L );
2200 :
2201 0 : Ltmp = Mult_32_16( Ltmp, inv_L );
2202 :
2203 0 : return Ltmp;
2204 : }
2205 128477 : Word32 sum32_fx( /* o : sum of all vector elements Qx*/
2206 : const Word32 *vec, /* i : input vector Qx*/
2207 : const Word16 lvec /* i : length of input vector */
2208 : )
2209 : {
2210 : Word16 i;
2211 : Word32 tmp;
2212 :
2213 128477 : tmp = L_deposit_l( 0 );
2214 6666765 : FOR( i = 0; i < lvec; i++ )
2215 : {
2216 6538288 : tmp = L_add_sat( tmp, vec[i] ); /*Qx */
2217 : }
2218 :
2219 128477 : return tmp;
2220 : }
2221 707605 : Word16 sum16_fx( /* o : sum of all vector elements Qx*/
2222 : const Word16 *vec, /* i : input vector Qx*/
2223 : const Word16 lvec /* i : length of input vector */
2224 : )
2225 : {
2226 : Word16 i;
2227 : Word16 tmp;
2228 707605 : tmp = 0;
2229 707605 : move16();
2230 5476190 : FOR( i = 0; i < lvec; i++ )
2231 : {
2232 4768585 : tmp = add_sat( tmp, vec[i] ); /*Qx */
2233 : }
2234 :
2235 707605 : return tmp;
2236 : }
2237 : /*------------------------------------------------------------------*
2238 : * function Random
2239 : *
2240 : * Signed 16 bits random generator.
2241 : *------------------------------------------------------------------*/
2242 618204462 : Word16 Random( /* o : output random value */
2243 : Word16 *seed /* i/o: random seed */
2244 : )
2245 : {
2246 618204462 : *seed = extract_l( L_mac0( 13849L, *seed, 31821 ) );
2247 618204462 : move16();
2248 618204462 : return *seed;
2249 : }
2250 :
2251 123036 : Word16 own_random2_fx( Word16 seed )
2252 : {
2253 123036 : return extract_l( L_mac0( 13849, seed, 31821 ) );
2254 : }
2255 :
2256 : /*---------------------------------------------------------------------
2257 : * sign_fx()
2258 : *
2259 : *---------------------------------------------------------------------*/
2260 :
2261 : /*! r: sign of x (+1/-1) */
2262 0 : Word16 sign_fx(
2263 : const Word32 x /* i : input value of x */
2264 : )
2265 : {
2266 0 : IF( LT_32( x, 0 ) )
2267 : {
2268 0 : return -1;
2269 : }
2270 : ELSE
2271 : {
2272 0 : return 1;
2273 : }
2274 : }
2275 :
2276 0 : Word16 sign16_fx(
2277 : const Word16 x /* i : input value of x */
2278 : )
2279 : {
2280 0 : IF( LT_16( x, 0 ) )
2281 : {
2282 0 : return -1;
2283 : }
2284 : ELSE
2285 : {
2286 0 : return 1;
2287 : }
2288 : }
2289 :
2290 : /*------------------------------------------------------------------*
2291 : * function Div_32_optmz
2292 : *
2293 : * Performs 32 bits interger division
2294 : *------------------------------------------------------------------*/
2295 3675473 : static Word32 Div_32_optmz( Word32 L_num, Word16 denom_hi )
2296 : {
2297 : Word16 approx, hi, lo, n_hi, n_lo;
2298 : Word32 L_32;
2299 :
2300 : /* First approximation: 1 / L_denom = 1/denom_hi */
2301 :
2302 3675473 : approx = div_s( (Word16) 0x3fff, denom_hi );
2303 :
2304 : /* 1/L_denom = approx * (2.0 - L_denom * approx) */
2305 :
2306 3675473 : L_32 = L_msu( (Word32) 0x7fffffffL, denom_hi, approx );
2307 :
2308 3675473 : lo = L_Extract_lc( L_32, &hi );
2309 3675473 : L_32 = Mpy_32_16( hi, lo, approx );
2310 :
2311 : /* L_num * (1/L_denom) */
2312 :
2313 3675473 : lo = L_Extract_lc( L_32, &hi );
2314 3675473 : n_lo = L_Extract_lc( L_num, &n_hi );
2315 3675473 : L_32 = Mpy_32( n_hi, n_lo, hi, lo );
2316 :
2317 3675473 : return ( L_32 );
2318 : }
2319 : /*------------------------------------------------------------------*
2320 : * function iDiv_and_mod_32
2321 : *
2322 : * return the quotient and the modulo 32 bits numerator divided by a 16 bit denominator
2323 : * The denominator might be right shifted by 1
2324 : *------------------------------------------------------------------*/
2325 3675473 : void iDiv_and_mod_32(
2326 : const Word32 Numer, /* i : 32 bits numerator */
2327 : const Word16 Denom, /* i : 16 bits denominator */
2328 : Word32 *Int_quotient, /* o : integer result of the division (int)(num/den) */
2329 : Word32 *Int_mod, /* o : modulo result of the division num-((int)(num/den)*den)*/
2330 : const Word16 rshift /* i : 0 if no right shift / 1 if the denom is right shifted by 1 */
2331 : )
2332 : {
2333 : Word32 Quotient;
2334 : Word16 expA, expB;
2335 : Word32 N, TEMP;
2336 : Word16 D;
2337 :
2338 : /* Normalize 'Numer' & 'Denom' */
2339 : /* Use Temporary to Preserve the Original Value */
2340 3675473 : expA = norm_l( Numer );
2341 3675473 : N = L_shl( Numer, expA );
2342 3675473 : expB = norm_s( Denom );
2343 3675473 : D = shl( Denom, expB );
2344 :
2345 : /* Need to shift right 'Numer' by 1? */
2346 3675473 : if ( L_mac( N, D, -32768L ) >= 0 )
2347 : {
2348 2020724 : expA = sub( expA, 1 );
2349 : }
2350 3675473 : N = L_shl( Numer, expA );
2351 :
2352 : /* Perform Approximation of the Division
2353 : * Since 'lo' part is '0' AND 'denom' is supposed to be constant in the targeted usage
2354 : * one could import the Div32 code and pre-calc the div_s and eliminate all calcs
2355 : * with 'lo' to save some complexity */
2356 :
2357 3675473 : Quotient = Div_32_optmz( N, D ); /* takes 36 clocks */
2358 : /* Bring Back to Q0 (minus 2 because we removed the left shift by 2 in the Div32_optmz) */
2359 3675473 : IF( rshift )
2360 : {
2361 0 : Quotient = L_shr( Quotient, add( 15 - 2, sub( expA, sub( expB, 1 ) ) ) );
2362 : }
2363 : ELSE
2364 : {
2365 3675473 : Quotient = L_shr( Quotient, add( 15 - 2, sub( expA, expB ) ) );
2366 : }
2367 :
2368 : /* Cross Check (do Quotient x Divisor)
2369 : * The Quotient is unsigned but we cannot just use extract_h because
2370 : * extract_l on the low part will get the sign of the bit #15.
2371 : * In a 32 bits value, what is in bits 0-15 is un unsigned 16 bits value.
2372 : * So, we shift left by 1, extract the hi part and mult it by 32768 (hence the L_shl by 16-1.
2373 : * Then we take 15 bits left (mask the others) and multiply by Denom.
2374 : * Technically this could overflow. But since we are mutiplying to get
2375 : * back to the Numer value that fitted in a 32 bits, doing Divisor x Quotient
2376 : * must necessarily fit in a 32 bits
2377 : * It is assumed that all are positive values. If not, one could
2378 : * check the sign of the numer and denom, turn them into abs values
2379 : * and restore the sign after*/
2380 3675473 : TEMP = L_shl( L_mult0( extract_h( L_shl( Quotient, 1 ) ), Denom ), 16 - 1 );
2381 3675473 : TEMP = L_mac0( TEMP, extract_l( L_and( 0x7FFF, Quotient ) ), Denom );
2382 :
2383 :
2384 : /* Here we test to see if the previous "Quotient x Divisor" (or TEMP) is too small
2385 : * that is the "Numer" minus TEMP is bigger or Equal to the Divisor.
2386 : * If it is then the quotient is too small. We need to increase it by 1.
2387 : * That is caused by our Div32 fractionnal division that can be off by 1
2388 : * sometimes.
2389 : * In some cases, when the divisor is very small (like 10 or something)
2390 : * the quotient could be off by more than 1 and we would need a loop
2391 : * to check again. That is not the case here with the current divisor */
2392 3675473 : IF( rshift )
2393 : {
2394 0 : TEMP = L_shl( TEMP, 1 );
2395 0 : WHILE( L_msu0( L_sub( Numer, TEMP ), 2, Denom ) >= 0 )
2396 : {
2397 0 : Quotient = L_add( Quotient, 1 );
2398 0 : TEMP = L_shl( L_mult0( extract_h( L_shl( Quotient, 1 ) ), Denom ), 16 - 1 );
2399 0 : TEMP = L_mac0( TEMP, extract_l( L_and( 0x7FFF, Quotient ) ), Denom );
2400 0 : TEMP = L_shl( TEMP, 1 );
2401 : }
2402 : }
2403 : ELSE{
2404 6007118 : WHILE( L_msu0( L_sub( Numer, TEMP ), 1, Denom ) >= 0 ){
2405 2331645 : Quotient = L_add( Quotient, 1 );
2406 2331645 : TEMP = L_shl( L_mult0( extract_h( L_shl( Quotient, 1 ) ), Denom ), 16 - 1 );
2407 2331645 : TEMP = L_mac0( TEMP, extract_l( L_and( 0x7FFF, Quotient ) ), Denom );
2408 : }
2409 : }
2410 3675473 : *Int_quotient = Quotient;
2411 3675473 : move32();
2412 3675473 : IF( L_msu0( L_sub( Numer, TEMP ), 1, Denom ) == 0 )
2413 : {
2414 0 : *Int_mod = 0L;
2415 0 : move32();
2416 : }
2417 : ELSE
2418 : {
2419 3675473 : *Int_mod = L_sub( Numer, TEMP );
2420 3675473 : move32();
2421 : }
2422 3675473 : }
2423 :
2424 : /*===================================================================*/
2425 : /* FUNCTION : pz_filter_sp_fx () */
2426 : /*-------------------------------------------------------------------*/
2427 : /* PURPOSE : Generic pole-zero filter routine, with single */
2428 : /* precision memory */
2429 : /*-------------------------------------------------------------------*/
2430 : /* INPUT ARGUMENTS : */
2431 : /* */
2432 : /* _ (Word16 []) b : zero filter coefficients (Qc). */
2433 : /* _ (Word16 []) a : pole filter coefficients (Qc), a(0)=1 in Qc */
2434 : /* _ (Word16 []) x : input signal (Qn). */
2435 : /* _ (Word16) PNR : NR filter order */
2436 : /* _ (Word16) PDR : DR filter order */
2437 : /* _ (Word16) N : number of input samples. */
2438 : /* _ (Word16) Qa : Q factor compensation (Qa=16-Qc) */
2439 : /*-------------------------------------------------------------------*/
2440 : /* OUTPUT ARGUMENTS : */
2441 : /* */
2442 : /* _ (Word16 []) y : output signal (Qn) */
2443 : /*-------------------------------------------------------------------*/
2444 : /* INPUT/OUTPUT ARGUMENTS : */
2445 : /* */
2446 : /* _ (Word16 []) buf : filter memory (Qn-Qa). */
2447 : /*-------------------------------------------------------------------*/
2448 : /* RETURN ARGUMENTS : _ None. */
2449 : /*===================================================================*/
2450 :
2451 0 : void pz_filter_sp_fx(
2452 : const Word16 b[],
2453 : const Word16 a[],
2454 : Word16 x[],
2455 : Word16 y[],
2456 : Word16 buf[],
2457 : Word16 PNR,
2458 : Word16 PDR,
2459 : Word16 N,
2460 : Word16 Qa )
2461 : {
2462 : Word16 i, j;
2463 : Word16 s;
2464 : Word16 s_mem;
2465 : Word32 Ltemp1;
2466 : Word32 Lacc;
2467 0 : s = negate( Qa );
2468 0 : s = add( s, s ); /* s=-2Qa*/
2469 0 : s = add( s, 1 );
2470 0 : FOR( i = 0; i < N; i++ )
2471 : {
2472 0 : Lacc = L_deposit_h( x[i] ); /* Lacc in Q(16+Qn)*/
2473 0 : Lacc = L_shl( Lacc, s ); /* Lacc=x[i] in Q(16+Qn-2Qa+1)*/
2474 0 : FOR( j = PDR - 1; j >= 0; j-- )
2475 0 : Lacc = L_msu_sat( Lacc, buf[j], a[j + 1] ); /*Q(16+Qn-2Qa+1)*/
2476 :
2477 :
2478 0 : Lacc = L_shr( Lacc, 1 );
2479 0 : Ltemp1 = L_add_sat( L_shl_sat( Lacc, Qa ), 0x08000 );
2480 0 : s_mem = extract_h( Ltemp1 );
2481 :
2482 0 : Lacc = L_deposit_l( 0 );
2483 0 : FOR( j = PNR - 1; j >= 0; j-- )
2484 0 : Lacc = L_mac_sat( Lacc, buf[j], b[j + 1] );
2485 0 : Lacc = L_mac_sat( Lacc, s_mem, b[0] );
2486 : /* Lacc in Q(1+Qc+Qn-Qa)*/
2487 :
2488 0 : FOR( j = s_max( PDR, PNR ) - 1; j > 0; j-- )
2489 : {
2490 : /* Update filter memory */
2491 0 : buf[j] = buf[j - 1];
2492 0 : move16();
2493 : }
2494 0 : buf[0] = s_mem;
2495 0 : move16();
2496 :
2497 0 : Ltemp1 = L_add_sat( L_shr_sat( Lacc, s ), 0x08000 ); /* Ltemp1 in Qc+Qa+Qn=Q(Qn) */
2498 0 : y[i] = extract_h( Ltemp1 ); /* y[i] in Qn */
2499 0 : move16();
2500 : }
2501 0 : }
2502 :
2503 :
2504 33076 : Word32 root_a_fx(
2505 : Word32 a,
2506 : Word16 Q_a,
2507 : Word16 *exp_out )
2508 : {
2509 : Word16 exp, tmp;
2510 : Word32 L_tmp;
2511 :
2512 33076 : IF( a <= 0 )
2513 : {
2514 366 : *exp_out = 0;
2515 366 : move16();
2516 366 : return 0;
2517 : }
2518 :
2519 32710 : exp = norm_l( a );
2520 32710 : tmp = extract_h( L_shl( a, exp ) );
2521 32710 : exp = sub( exp, sub( 30, Q_a ) );
2522 32710 : tmp = div_s( 16384, tmp );
2523 32710 : L_tmp = L_deposit_h( tmp );
2524 32710 : L_tmp = Isqrt_lc( L_tmp, &exp );
2525 :
2526 32710 : *exp_out = exp;
2527 32710 : move16();
2528 :
2529 32710 : return L_tmp;
2530 : }
2531 :
2532 :
2533 592092 : Word32 root_a_over_b_fx(
2534 : Word32 a, /* Q(Q_a) */
2535 : Word16 Q_a,
2536 : Word32 b, /* Q(Q_b) */
2537 : Word16 Q_b,
2538 : Word16 *exp_out )
2539 : {
2540 : Word16 tmp, num, den, scale;
2541 : Word16 exp, exp_num, exp_den;
2542 : Word32 L_tmp;
2543 : #ifndef ISSUE_1836_replace_overflow_libcom
2544 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
2545 : Flag Overflow = 0;
2546 : move32();
2547 : #endif
2548 : #endif
2549 592092 : test();
2550 592092 : IF( ( a <= 0 ) || ( b <= 0 ) )
2551 : {
2552 1717 : *exp_out = 0;
2553 1717 : move16();
2554 1717 : return 0;
2555 : }
2556 :
2557 590375 : exp_num = norm_l( b );
2558 : #ifdef ISSUE_1836_replace_overflow_libcom
2559 590375 : num = round_fx_sat( L_shl_sat( b, exp_num ) );
2560 : #else
2561 : num = round_fx_o( L_shl_o( b, exp_num, &Overflow ), &Overflow );
2562 : #endif
2563 590375 : exp_num = sub( sub( 30, exp_num ), Q_b );
2564 :
2565 590375 : exp_den = norm_l( a );
2566 : #ifdef ISSUE_1836_replace_overflow_libcom
2567 590375 : den = round_fx_sat( L_shl_sat( a, exp_den ) );
2568 : #else
2569 : den = round_fx_o( L_shl_o( a, exp_den, &Overflow ), &Overflow );
2570 : #endif
2571 590375 : exp_den = sub( sub( 30, exp_den ), Q_a );
2572 :
2573 590375 : scale = shr( sub( den, num ), 15 );
2574 : #ifdef ISSUE_1836_replace_overflow_libcom
2575 590375 : num = shl_sat( num, scale );
2576 : #else
2577 : num = shl_o( num, scale, &Overflow );
2578 : #endif
2579 590375 : exp_num = sub( exp_num, scale );
2580 :
2581 590375 : tmp = div_s( num, den );
2582 590375 : exp = sub( exp_num, exp_den );
2583 :
2584 590375 : L_tmp = L_deposit_h( tmp );
2585 590375 : L_tmp = Isqrt_lc( L_tmp, &exp );
2586 :
2587 590375 : *exp_out = exp;
2588 590375 : move16();
2589 :
2590 590375 : return L_tmp;
2591 : }
2592 :
2593 0 : Word32 root_a_over_b_ivas_fx(
2594 : Word32 a, /* Q(Q_a) */
2595 : Word16 Q_a,
2596 : Word32 b, /* Q(Q_b) */
2597 : Word16 Q_b,
2598 : Word16 *q_out )
2599 : {
2600 : Word16 shift_a, shift_b, shift;
2601 : Word32 mod_a, mod_b, one_in_Q_a, one_in_Q_b, half_in_Q_a, half_in_Q_b;
2602 : Word32 a_sqr, b_sqr, p0, p1, p2, approx;
2603 : Word16 exp;
2604 :
2605 0 : test();
2606 0 : IF( ( a <= 0 ) || ( b <= 0 ) )
2607 : {
2608 0 : *q_out = 0;
2609 0 : move16();
2610 0 : return 0;
2611 : }
2612 :
2613 0 : one_in_Q_a = L_shl( 1, Q_a ); // 1.0f in Q_a
2614 0 : one_in_Q_b = L_shl( 1, Q_b ); // 1.0f in Q_b
2615 0 : half_in_Q_a = L_shr( one_in_Q_a, 1 ); // 0.5f in Q_a
2616 0 : half_in_Q_b = L_shr( one_in_Q_b, 1 ); // 0.5f in Q_b
2617 :
2618 0 : a = L_add( a, one_in_Q_a );
2619 0 : b = L_add( b, one_in_Q_b );
2620 :
2621 : /* This next piece of code implements a "norm" function */
2622 : /* and returns the shift needed to scale "a" to have a */
2623 : /* 1 in the (MSB-1) position. This is equivalent to */
2624 : /* giving a value between 0.5 & 1.0. */
2625 :
2626 0 : mod_a = a;
2627 0 : move32();
2628 :
2629 0 : shift_a = 0;
2630 0 : move16();
2631 0 : WHILE( GT_32( mod_a, one_in_Q_a ) )
2632 : {
2633 0 : mod_a = L_shr( mod_a, 1 );
2634 0 : shift_a = sub( shift_a, 1 );
2635 : }
2636 :
2637 0 : WHILE( LT_32( mod_a, half_in_Q_a ) )
2638 : {
2639 0 : mod_a = L_shl( mod_a, 1 );
2640 0 : shift_a = add( shift_a, 1 );
2641 : }
2642 :
2643 0 : shift_a = s_and( shift_a, -2 );
2644 0 : mod_a = L_shl( a, shift_a ); // Q_a
2645 :
2646 : /* This next piece of code implements a "norm" function */
2647 : /* and returns the shift needed to scale "b" to have a */
2648 : /* 1 in the (MSB-1) position. This is equivalent to */
2649 : /* giving a value between 0.5 & 1.0. */
2650 0 : mod_b = b;
2651 0 : move32();
2652 :
2653 0 : shift_b = 0;
2654 0 : move16();
2655 0 : WHILE( GT_32( mod_b, one_in_Q_b ) )
2656 : {
2657 0 : mod_b = L_shr( mod_b, 1 );
2658 0 : shift_b = sub( shift_b, 1 );
2659 : }
2660 :
2661 0 : WHILE( LT_32( mod_b, half_in_Q_b ) )
2662 : {
2663 0 : mod_b = L_shl( mod_b, 1 );
2664 0 : shift_b = add( shift_b, 1 );
2665 : }
2666 :
2667 0 : shift_b = s_and( shift_b, -2 );
2668 0 : mod_b = L_shl( b, shift_b ); // Q_b
2669 :
2670 0 : shift = shr( sub( shift_b, shift_a ), 1 );
2671 :
2672 0 : a_sqr = W_extract_h( W_shl( W_mult0_32_32( mod_a, mod_a ), sub( 32, Q_a ) ) ); // Q_a
2673 0 : b_sqr = W_extract_h( W_shl( W_mult0_32_32( mod_b, mod_b ), sub( 32, Q_b ) ) ); // Q_b
2674 :
2675 0 : p2 = L_shl( -408505077 /* -0.7609f in Q29 */, sub( Q_b, 31 ) ); // Qb-2
2676 0 : p1 = L_shl( 1444612250 /* 2.6908f in Q29 */, sub( Q_b, 31 ) ); // Qb-2
2677 0 : p0 = L_shl( 385258566 /* 0.7176f in Q29 */, sub( Q_b, 31 ) ); // Qb-2
2678 :
2679 0 : p2 = Madd_32_32( Madd_32_32( p2, 501759554 /* 0.9346f in Q29*/, mod_b ), -252060893 /* -0.4695f in Q29 */, b_sqr ); // Q_b-2
2680 0 : p1 = Madd_32_32( Madd_32_32( p1, -1774680487 /* -3.3056f in Q29 */, mod_b ), 891635211 /* 1.6608f in Q29 */, b_sqr ); // Q_b-2
2681 0 : p0 = Madd_32_32( Madd_32_32( p0, -473251709 /* -0.8815f in Q29 */, mod_b ), 237780127 /* 0.4429f in Q29 */, b_sqr ); // Q_b-2
2682 :
2683 : /* approx = p0 + p1 * mod_a + p2 * mod_a * mod_a; */
2684 0 : approx = Madd_32_32( Mpy_32_32( p1, mod_a ), p2, a_sqr ); // Q_a+Q_b-33
2685 0 : approx = L_add( approx, L_shl( p0, sub( Q_a, 31 ) ) ); // Q_a+Q_b-33
2686 :
2687 0 : exp = sub( norm_l( approx ), 1 );
2688 0 : approx = L_shl( approx, exp ); // // Q_a+Q_b-33+exp
2689 :
2690 0 : *q_out = sub( add( sub( add( Q_a, Q_b ), 33 ), exp ), shift );
2691 0 : move16();
2692 :
2693 0 : return approx;
2694 : }
2695 :
2696 : /*===================================================================*/
2697 : /* FUNCTION : fir_fx () */
2698 : /*-------------------------------------------------------------------*/
2699 : /* PURPOSE : Generic FIR filter routine */
2700 : /*-------------------------------------------------------------------*/
2701 : /* INPUT ARGUMENTS : */
2702 : /* */
2703 : /* _ (Word16 []) b : filter coefficients (Qc). */
2704 : /* _ (Word16 []) x : input signal (Qn). */
2705 : /* _ (Word16) P : filter order. */
2706 : /* _ (Word16) N : number of input samples. */
2707 : /* _ (Word16) Qa : Q factor compensation (Qa=16-Qc) */
2708 : /*-------------------------------------------------------------------*/
2709 : /* OUTPUT ARGUMENTS : */
2710 : /* */
2711 : /* _ (Word16 []) y : output signal (Qn) */
2712 : /*-------------------------------------------------------------------*/
2713 : /* INPUT/OUTPUT ARGUMENTS : */
2714 : /* */
2715 : /* _ : None */
2716 : /*-------------------------------------------------------------------*/
2717 : /* RETURN ARGUMENTS : _ None. */
2718 : /*===================================================================*/
2719 112628 : void fir_fx( const Word16 x[], /* i : input vector Qx*/
2720 : const Word16 h[], /* i : impulse response of the FIR filter Q12*/
2721 : Word16 y[], /* o : output vector (result of filtering) Qx*/
2722 : Word16 mem[], /* i/o: memory of the input signal (L samples) Qx*/
2723 : const Word16 L, /* i : input vector size */
2724 : const Word16 K, /* i : order of the FIR filter (K+1 coefs.) */
2725 : const Word16 upd /* i : 1 = update the memory, 0 = not */
2726 : ,
2727 : Word16 shift /* i : difference between Q15 and scaling of h[] */
2728 : )
2729 : {
2730 :
2731 : Word16 buf_in[L_FRAME32k + L_FILT_MAX];
2732 : Word16 i, j;
2733 : Word32 s;
2734 : #ifndef ISSUE_1836_replace_overflow_libcom
2735 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
2736 : Flag Overflow = 0;
2737 : move32();
2738 : #endif
2739 : #endif
2740 : /* prepare the input buffer (copy and update memory) */
2741 112628 : Copy( mem, buf_in, K );
2742 112628 : Copy( x, buf_in + K, L );
2743 112628 : IF( upd )
2744 : {
2745 25 : Copy( buf_in + L, mem, K );
2746 : }
2747 :
2748 : /* do the filtering */
2749 34599428 : FOR( i = 0; i < L; i++ )
2750 : {
2751 : #ifdef ISSUE_1836_replace_overflow_libcom
2752 34486800 : s = L_mult_sat( buf_in[K + i], h[0] );
2753 : #else
2754 : s = L_mult_o( buf_in[K + i], h[0], &Overflow );
2755 : #endif
2756 :
2757 171875760 : FOR( j = 1; j <= K; j++ )
2758 : {
2759 : #ifdef ISSUE_1836_replace_overflow_libcom
2760 137388960 : s = L_mac_sat( s, h[j], buf_in[K + i - j] );
2761 : #else
2762 : s = L_mac_o( s, h[j], buf_in[K + i - j], &Overflow );
2763 : #endif
2764 : }
2765 : #ifdef ISSUE_1836_replace_overflow_libcom
2766 34486800 : s = L_shl_sat( s, shift );
2767 34486800 : y[i] = round_fx_sat( s ); /*Qx */
2768 : #else
2769 : s = L_shl_o( s, shift, &Overflow );
2770 : y[i] = round_fx_o( s, &Overflow ); /*Qx */
2771 : #endif
2772 34486800 : move16();
2773 : }
2774 112628 : }
2775 :
2776 : /*-------------------------------------------------------------------*
2777 : * v_add_32()
2778 : *
2779 : * Addition of two vectors sample by sample
2780 : *-------------------------------------------------------------------*/
2781 :
2782 4901854 : void v_add_32(
2783 : const Word32 x1[], /* i : Input vector 1 */
2784 : const Word32 x2[], /* i : Input vector 2 */
2785 : Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */
2786 : const Word16 N /* i : Vector length */
2787 : )
2788 : {
2789 : Word16 i;
2790 :
2791 910913555 : FOR( i = 0; i < N; i++ )
2792 : {
2793 906011701 : y[i] = L_add( x1[i], x2[i] );
2794 906011701 : move32();
2795 : }
2796 :
2797 4901854 : return;
2798 : }
2799 :
2800 51422 : void v_shr_32(
2801 : Word32 x1[], /* i : Input vector 1 */
2802 : Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */
2803 : const Word16 N, /* i : Vector length */
2804 : Word16 shift /*shift value*/
2805 : )
2806 : {
2807 : Word16 i;
2808 :
2809 15904712 : FOR( i = 0; i < N; i++ )
2810 : {
2811 15853290 : y[i] = L_shr( x1[i], shift );
2812 15853290 : move32();
2813 : }
2814 :
2815 51422 : return;
2816 : }
2817 :
2818 :
2819 : /*-------------------------------------------------------------------*
2820 : * v_sub_32()
2821 : *
2822 : * Subtraction of two vectors sample by sample
2823 : *-------------------------------------------------------------------*/
2824 :
2825 2511085 : void v_sub_32(
2826 : const Word32 x1[], /* i : Input vector 1 */
2827 : const Word32 x2[], /* i : Input vector 2 */
2828 : Word32 y[], /* o : Output vector that contains vector 1 - vector 2 */
2829 : const Word16 N /* i : Vector length */
2830 : )
2831 : {
2832 : Word16 i;
2833 :
2834 205293052 : FOR( i = 0; i < N; i++ )
2835 : {
2836 202781967 : y[i] = L_sub( x1[i], x2[i] );
2837 202781967 : move32();
2838 : }
2839 :
2840 2511085 : return;
2841 : }
2842 :
2843 :
2844 : /*-------------------------------------------------------------------*
2845 : * v_add_16()
2846 : *
2847 : * Addition of two vectors sample by sample
2848 : *-------------------------------------------------------------------*/
2849 :
2850 62682 : void v_add_16(
2851 : const Word16 x1[], /* i : Input vector 1 */
2852 : const Word16 x2[], /* i : Input vector 2 */
2853 : Word16 y[], /* o : Output vector that contains vector 1 + vector 2 */
2854 : const Word16 N /* i : Vector length */
2855 : )
2856 : {
2857 : Word16 i;
2858 :
2859 4902890 : FOR( i = 0; i < N; i++ )
2860 : {
2861 4840208 : y[i] = add_sat( x1[i], x2[i] );
2862 4840208 : move16();
2863 : }
2864 :
2865 62682 : return;
2866 : }
2867 :
2868 :
2869 : /*-------------------------------------------------------------------*
2870 : * v_sub_16()
2871 : *
2872 : * Subtraction of two vectors sample by sample
2873 : *-------------------------------------------------------------------*/
2874 :
2875 96944 : void v_sub_16(
2876 : const Word16 x1[], /* i : Input vector 1 */
2877 : const Word16 x2[], /* i : Input vector 2 */
2878 : Word16 y[], /* o : Output vector that contains vector 1 - vector 2 */
2879 : const Word16 N /* i : Vector length */
2880 : )
2881 : {
2882 : Word16 i;
2883 :
2884 346267 : FOR( i = 0; i < N; i++ )
2885 : {
2886 249323 : y[i] = sub_sat( x1[i], x2[i] );
2887 249323 : move16();
2888 : }
2889 :
2890 96944 : return;
2891 : }
2892 :
2893 :
2894 : /*--------------------------------------------------------------------------------*/
2895 : /* squant_fx() */
2896 : /*--------------------------------------------------------------------------------*/
2897 0 : Word16 squant_fx( /* o: index of the winning codeword */
2898 : const Word16 x, /* i: scalar value to quantize */
2899 : Word16 *xq, /* o: quantized value */
2900 : const Word16 cb[], /* i: codebook */
2901 : const Word16 cbsize /* i: codebook size */
2902 : )
2903 : {
2904 : Word16 tmp;
2905 : Word16 c, idx;
2906 : Word32 L_mindist, L_dist;
2907 : #ifndef ISSUE_1836_replace_overflow_libcom
2908 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
2909 : Flag Overflow = 0;
2910 : #endif
2911 : #endif
2912 :
2913 0 : idx = 0;
2914 0 : move16();
2915 0 : L_mindist = MAX_32;
2916 0 : move32();
2917 :
2918 0 : FOR( c = 0; c < cbsize; c++ )
2919 : {
2920 0 : L_dist = L_deposit_l( 0 );
2921 : #ifdef ISSUE_1836_replace_overflow_libcom
2922 0 : tmp = sub_sat( x, cb[c] );
2923 : #else
2924 : tmp = sub_o( x, cb[c], &Overflow );
2925 : #endif
2926 :
2927 : /*dist += tmp*tmp; */
2928 : #ifdef ISSUE_1836_replace_overflow_libcom
2929 0 : L_dist = L_mac_sat( L_dist, tmp, tmp );
2930 : #else
2931 : L_dist = L_mac_o( L_dist, tmp, tmp, &Overflow );
2932 : #endif
2933 :
2934 0 : if ( LT_32( L_dist, L_mindist ) )
2935 : {
2936 0 : idx = c;
2937 0 : move16();
2938 : }
2939 0 : L_mindist = L_min( L_mindist, L_dist );
2940 : }
2941 :
2942 0 : *xq = cb[idx];
2943 0 : move16();
2944 :
2945 0 : return idx;
2946 : }
2947 :
2948 : /*! r: index of the winning codeword */
2949 0 : Word16 squant_int_fx(
2950 : UWord8 x, /* i : scalar value to quantize */
2951 : UWord8 *xq, /* o : quantized value */
2952 : const UWord8 *cb, /* i : codebook */
2953 : const Word16 cbsize /* i : codebook size */
2954 : )
2955 : {
2956 : Word16 i, idx;
2957 : Word32 mindist, d;
2958 :
2959 0 : idx = 0;
2960 0 : move16();
2961 0 : mindist = 10000000; // Q0
2962 0 : move32();
2963 0 : FOR( i = 0; i < cbsize; i++ )
2964 : {
2965 0 : d = L_mult0( sub( x, cb[i] ), sub( x, cb[i] ) );
2966 0 : IF( LT_32( d, mindist ) )
2967 : {
2968 0 : mindist = d;
2969 0 : move32();
2970 0 : idx = i;
2971 0 : move16();
2972 : }
2973 : }
2974 0 : *xq = cb[idx];
2975 0 : move16();
2976 :
2977 0 : return idx;
2978 : }
2979 :
2980 : /*===================================================================*/
2981 : /* FUNCTION : pz_filter_dp_fx () */
2982 : /*-------------------------------------------------------------------*/
2983 : /* PURPOSE : Generic pole-zero filter routine, with double */
2984 : /* precision memory, transposed direct form II */
2985 : /*-------------------------------------------------------------------*/
2986 : /* INPUT ARGUMENTS : */
2987 : /* */
2988 : /* _ (Word16 []) b : zero filter coefficients (Qc). */
2989 : /* _ (Word16 []) a : pole filter coefficients (Qc), a(0)=1 */
2990 : /* _ (Word16 []) x : input signal (Qx). */
2991 : /* _ (Word16) P : filter order. */
2992 : /* _ (Word16) N : number of input samples. */
2993 : /* _ (Word16) Qa : Q factor compensation (Qa=16-Qc) */
2994 : /*-------------------------------------------------------------------*/
2995 : /* OUTPUT ARGUMENTS : */
2996 : /* */
2997 : /* _ (Word16 []) y : output signal (Qx) */
2998 : /*-------------------------------------------------------------------*/
2999 : /* INPUT/OUTPUT ARGUMENTS : */
3000 : /* */
3001 : /* _ (Word32 []) buf : filter memory (Qx+Qc) */
3002 : /*-------------------------------------------------------------------*/
3003 : /* RETURN ARGUMENTS : _ None. */
3004 : /*===================================================================*/
3005 :
3006 0 : void pz_filter_dp_fx(
3007 : const Word16 b[],
3008 : const Word16 a[],
3009 : Word16 x[],
3010 : Word16 y[],
3011 : Word32 buf[],
3012 : Word16 PNR,
3013 : Word16 PDR,
3014 : Word16 N,
3015 : Word16 Qa )
3016 : {
3017 : Word16 i, j;
3018 : Word16 s;
3019 : Word32 s_mem;
3020 : Word32 Ltemp1;
3021 : Word32 Lacc;
3022 :
3023 0 : s = negate( Qa );
3024 0 : s = add( s, s ); /* s=-2Qa */
3025 0 : s = add( s, 1 );
3026 0 : FOR( i = 0; i < N; i++ )
3027 : {
3028 0 : Lacc = L_deposit_h( x[i] ); /* Lacc in Q(16+Qn)*/
3029 0 : Lacc = L_shl( Lacc, s ); /* Lacc=x[i] in Q(16+Qn-2Qa+1)*/
3030 0 : FOR( j = PDR - 1; j >= 0; j-- )
3031 0 : Lacc = Msub_32_16( Lacc, buf[j], a[j + 1] ); /*Q(16+Qn-2Qa+1)*/
3032 :
3033 0 : s_mem = L_shl_sat( Lacc, sub( Qa, 1 ) ); /*Qn-Qa+16=Qn+Qc*/
3034 0 : Lacc = L_deposit_l( 0 );
3035 0 : FOR( j = PNR - 1; j >= 0; j-- )
3036 0 : Lacc = Madd_32_16( Lacc, buf[j], b[j + 1] );
3037 0 : Lacc = Madd_32_16( Lacc, s_mem, b[0] );
3038 : /* Lacc in Q(1+Qc+Qn-Qa) */
3039 :
3040 0 : FOR( j = s_max( PDR, PNR ) - 1; j > 0; j-- )
3041 : {
3042 : /* Update filter memory */
3043 0 : buf[j] = buf[j - 1];
3044 0 : move16();
3045 : }
3046 0 : buf[0] = s_mem;
3047 0 : move16();
3048 :
3049 0 : Ltemp1 = L_shr_sat( Lacc, s ); /* Ltemp1 in Qc+Qa+Qn=Q(16+Qn) */
3050 0 : y[i] = extract_h( Ltemp1 ); /* y[i] in Qn */
3051 0 : move16();
3052 : }
3053 0 : }
3054 :
3055 : /*-------------------------------------------------------------------*
3056 : * Copy_Scale_sig
3057 : *
3058 : * Up/down scale a 16 bits vector x and move it into y
3059 : *-------------------------------------------------------------------*/
3060 4538384 : void Copy_Scale_sig32(
3061 : const Word32 x[], /* i : signal to scale input Qx */
3062 : Word32 y[], /* o : scaled signal output Qx */
3063 : const Word16 lg, /* i : size of x[] Q0 */
3064 : const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */
3065 : )
3066 : {
3067 : Word16 i;
3068 : Word32 L_tmp;
3069 4538384 : Word16 tmp = exp0;
3070 : #ifndef ISSUE_1836_replace_overflow_libcom
3071 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
3072 : Flag Overflow = 0;
3073 : move32();
3074 : #endif
3075 : #endif
3076 4538384 : IF( exp0 == 0 )
3077 : {
3078 15116712 : FOR( i = 0; i < lg; i++ )
3079 : {
3080 14889824 : y[i] = x[i];
3081 14889824 : move32();
3082 : }
3083 226888 : return;
3084 : }
3085 4311496 : IF( exp0 < 0 )
3086 : {
3087 395654722 : FOR( i = 0; i < lg; i++ )
3088 : {
3089 : #ifdef ISSUE_1836_replace_overflow_libcom
3090 392456235 : y[i] = L_shl_sat( x[i], tmp );
3091 : #else
3092 : y[i] = L_shl_o( x[i], tmp, &Overflow );
3093 : #endif
3094 392456235 : move16();
3095 : }
3096 3198487 : return;
3097 : }
3098 : #ifdef ISSUE_1836_replace_overflow_libcom
3099 1113009 : L_tmp = L_shl_sat( 1, exp0 - 1 );
3100 : #else
3101 : L_tmp = L_shl_o( 1, exp0 - 1, &Overflow );
3102 : #endif
3103 124218346 : FOR( i = 0; i < lg; i++ )
3104 : {
3105 123105337 : y[i] = W_extract_l( W_mult_32_32( L_tmp, x[i] ) );
3106 123105337 : move32(); /* saturation can occur here */
3107 : }
3108 : }
3109 :
3110 :
3111 : /*-------------------------------------------------------------------*
3112 : * Copy_Scale_sig32_16
3113 : *
3114 : * Up/down scale a 32 bits vector and round to 16 bits vector
3115 : *-------------------------------------------------------------------*/
3116 928420 : void Copy_Scale_sig32_16(
3117 : const Word32 *src, /* i : signal to scale Qx */
3118 : Word16 *dst, /* o : scaled signal Qx */
3119 : Word16 len, /* i : size of x[] Q0 */
3120 : Word16 exp0 ) /* i : exponent: x = round(x << exp) Qx ?exp */
3121 : {
3122 : Word16 i;
3123 : Word32 L_temp;
3124 :
3125 928420 : IF( exp0 == 0 )
3126 : {
3127 53407605 : FOR( i = 0; i < len; i++ )
3128 : {
3129 53208768 : *dst++ = round_fx_sat( *src++ );
3130 53208768 : move16();
3131 : }
3132 198837 : return;
3133 : }
3134 :
3135 60957197 : FOR( i = 0; i < len; i++ )
3136 : {
3137 60227614 : L_temp = L_shl_sat( *src++, exp0 );
3138 :
3139 60227614 : *dst++ = round_fx_sat( L_temp );
3140 60227614 : move16();
3141 : }
3142 : }
3143 :
3144 : /*-------------------------------------------------------------------*
3145 : * v_multc_att()
3146 : *
3147 : * Attenuation of a vector,, attenuation factor in Q15
3148 : *-------------------------------------------------------------------*/
3149 :
3150 0 : void v_multc_att(
3151 : const Word16 x[], /* i : Input vector Qx */
3152 : const Word16 att, /* i : Constant Q15, <= MAX_16 */
3153 : Word16 y[], /* o : Output vector that contains att*x */
3154 : const Word16 N /* i : Vector length */
3155 : )
3156 : {
3157 : Word16 i;
3158 0 : IF( LT_16( att, 32767 ) )
3159 : {
3160 0 : FOR( i = 0; i < N; i++ )
3161 : {
3162 0 : y[i] = mult_r( x[i], att );
3163 0 : move16();
3164 : }
3165 : }
3166 0 : } /*-------------------------------------------------------------------*
3167 : * v_multc_att32()
3168 : *
3169 : * Attenuation of a vector,, attenuation factor in Q15
3170 : *-------------------------------------------------------------------*/
3171 :
3172 0 : void v_multc_att32(
3173 : const Word32 x[], /* i : Input vector Qx */
3174 : const Word16 att, /* i : Constant Q15, <= MAX_16 */
3175 : Word32 y[], /* o : Output vector that contains att*x */
3176 : const Word16 N /* i : Vector length */
3177 : )
3178 : {
3179 : Word16 i;
3180 0 : IF( LT_16( att, 32767 ) )
3181 : {
3182 0 : FOR( i = 0; i < N; i++ )
3183 : {
3184 0 : y[i] = Mpy_32_16_r( x[i], att );
3185 0 : move32();
3186 : }
3187 : }
3188 0 : }
3189 :
3190 : /*-------------------------------------------------------------------*
3191 : * v_multc_att3232()
3192 : *
3193 : * Attenuation of a vector, attenuation factor in Q31
3194 : *-------------------------------------------------------------------*/
3195 :
3196 0 : void v_multc_att3232(
3197 : const Word32 x[], /* i : Input vector Qx */
3198 : const Word32 att, /* i : Constant Q32, <= MAX_32 */
3199 : Word32 y[], /* o : Output vector that contains att*x */
3200 : const Word16 N /* i : Vector length */
3201 : )
3202 : {
3203 : Word16 i;
3204 0 : IF( LE_32( att, MAX_32 ) )
3205 : {
3206 0 : FOR( i = 0; i < N; i++ )
3207 : {
3208 0 : y[i] = Mpy_32_32_r( x[i], att );
3209 0 : move32();
3210 : }
3211 : }
3212 0 : }
3213 :
3214 : /*-------------------------------------------------------------------*
3215 : * v_L_mult_1616()
3216 : *
3217 : * Multiplication of two vectors, Output in Word32
3218 : *-------------------------------------------------------------------*/
3219 :
3220 0 : void v_L_mult_1616(
3221 : const Word16 x1[], /* i : Input vector 1 */
3222 : const Word16 x2[], /* i : Input vector 2 */
3223 : Word32 y[], /* o : Output vector that contains vector 1 .* vector 2 */
3224 : const Word16 N /* i : Vector length */
3225 : )
3226 : {
3227 : Word16 i;
3228 :
3229 0 : for ( i = 0; i < N; i++ )
3230 : {
3231 0 : y[i] = L_mult( x1[i], x2[i] );
3232 0 : move32();
3233 : }
3234 :
3235 0 : return;
3236 : }
3237 :
3238 : /*-------------------------------------------------------------------*
3239 : * v_L_mult_3216()
3240 : *
3241 : * Multiplication of two vectors, Output in Word32
3242 : *-------------------------------------------------------------------*/
3243 :
3244 90653 : void v_L_mult_3216(
3245 : const Word32 x1[], /* i : Input vector 1 */
3246 : const Word16 x2[], /* i : Input vector 2 */
3247 : Word32 y[], /* o : Output vector that contains vector 1 .* vector 2 */
3248 : const Word16 N /* i : Vector length */
3249 : )
3250 : {
3251 : Word16 i;
3252 :
3253 52558237 : for ( i = 0; i < N; i++ )
3254 : {
3255 52467584 : y[i] = Mpy_32_16_1( x1[i], x2[i] );
3256 52467584 : move32();
3257 : }
3258 :
3259 90653 : return;
3260 : }
3261 :
3262 : /*-------------------------------------------------------------------*
3263 : * add_vec()
3264 : *
3265 : * Addition of two vectors sample by sample
3266 : *-------------------------------------------------------------------*/
3267 :
3268 2036 : void add_vec_fx(
3269 : const Word16 x1[], /* i : Input vector 1 */
3270 : const Word16 Qx1, /* i : SCaling of input 1 */
3271 : const Word16 x2[], /* i : Input vector 2 */
3272 : const Word16 Qx2, /* i : SCaling of input 1 */
3273 : Word16 y[], /* o : Output vector that contains vector 1 + vector 2 */
3274 : const Word16 Qy, /* i : SCaling of output 1 */
3275 : const Word16 N /* i : Vector lenght */
3276 : )
3277 : {
3278 : Word16 i, Qyx1, Qyx2;
3279 : #ifndef ISSUE_1836_replace_overflow_libcom
3280 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
3281 : Flag Overflow = 0;
3282 : move32();
3283 : #endif
3284 : #endif
3285 2036 : Qyx1 = sub( Qx1, Qy );
3286 2036 : Qyx2 = sub( Qx2, Qy );
3287 2036 : IF( Qyx1 == 0 )
3288 : {
3289 1719476 : FOR( i = 0; i < N; i++ )
3290 : {
3291 : #ifdef ISSUE_1836_replace_overflow_libcom
3292 1717440 : y[i] = add_sat( x1[i], shr_r_sat( x2[i], Qyx2 ) );
3293 : #else
3294 : y[i] = add_o( x1[i], shr_r_sat( x2[i], Qyx2 ), &Overflow );
3295 : #endif
3296 1717440 : move16();
3297 : }
3298 : }
3299 : ELSE
3300 : {
3301 0 : FOR( i = 0; i < N; i++ )
3302 : {
3303 : #ifdef ISSUE_1836_replace_overflow_libcom
3304 0 : y[i] = add_sat( shr_r_sat( x1[i], Qyx1 ), shr_r_sat( x2[i], Qyx2 ) ); //!!sat //!!sat
3305 : #else
3306 : y[i] = add_o( shr_r_sat( x1[i], Qyx1 ), shr_r_sat( x2[i], Qyx2 ), &Overflow );
3307 : #endif
3308 0 : move16();
3309 : }
3310 : }
3311 2036 : return;
3312 : }
3313 :
3314 : /*-------------------------------------------------------------------*
3315 : * Add_flt32_flt32
3316 : *
3317 : * Add two Pseudo Float Value that are 32 Bits Mantisa and 16 Bits Exp
3318 : *-------------------------------------------------------------------*/
3319 5352 : Word32 Add_flt32_flt32( /* o: Result (Normalized) */
3320 : Word32 a, /* i: 1st Value */
3321 : Word16 exp_a, /* i: Exponent of 1st Value (Q of Value) */
3322 : Word32 b, /* i: 2nd Value */
3323 : Word16 exp_b, /* i: Exponent of 2nd Value (Q of Value) */
3324 : Word16 *exp_out /* o: Exponent of Result */
3325 : )
3326 : {
3327 : Word16 temp, temp2;
3328 : Word32 L_temp;
3329 :
3330 : /* Subract 1 to further divide by 2 to avoid overflow on L_add */
3331 5352 : temp = sub( s_min( exp_a, exp_b ), 1 );
3332 :
3333 : /* Put both to same exponent */
3334 5352 : exp_a = sub( exp_a, temp );
3335 5352 : a = L_shr( a, exp_a );
3336 5352 : exp_b = sub( exp_b, temp );
3337 5352 : b = L_shr( b, exp_b );
3338 :
3339 : /* add them together */
3340 5352 : L_temp = L_add( a, b );
3341 5352 : temp2 = norm_l( L_temp );
3342 :
3343 5352 : *exp_out = add( temp, temp2 );
3344 5352 : move16();
3345 :
3346 5352 : return L_shl( L_temp, temp2 );
3347 : }
3348 :
3349 : /*-------------------------------------------------------------------*
3350 : * Mul_flt32_Q15
3351 : *
3352 : * Multiply one Pseudo Float Value (32 Bits Mantisa and 16 Bits Exp)
3353 : * with a Q15 value
3354 : *-------------------------------------------------------------------*/
3355 0 : Word32 Mul_flt32_Q15( /* o: Result (Normalized) */
3356 : Word32 value, /* i: Pseudo_float Value */
3357 : Word16 *exp_v, /*i/o: Exponent of Value (Q of Value) */
3358 : Word16 frac /* i: Q15 value */
3359 : )
3360 : {
3361 : Word16 temp;
3362 : Word32 L_temp;
3363 :
3364 0 : L_temp = Mult_32_16( value, frac );
3365 0 : temp = norm_l( L_temp );
3366 :
3367 0 : *exp_v = add( temp, *exp_v );
3368 0 : move16();
3369 :
3370 0 : return L_shl( L_temp, temp );
3371 : }
3372 :
3373 : /*-------------------------------------------------------------------*
3374 : * Div_flt32_flt32
3375 : *
3376 : * Divide one Pseudo Float Value (32 Bits Mantisa and 16 Bits Exp)
3377 : * by another one
3378 : *-------------------------------------------------------------------*/
3379 2 : Word32 Div_flt32_flt32( /* o: Result (Normalized) */
3380 : Word32 a, /* i: 1st Value */
3381 : Word16 exp_a, /* i: Exponent of 1st Value (Q of Value) */
3382 : Word32 b, /* i: 2nd Value */
3383 : Word16 exp_b, /* i: Exponent of 2nd Value (Q of Value) */
3384 : Word16 *exp_out /* o: Exponent of Result */
3385 : )
3386 : {
3387 : Word16 temp, temp2;
3388 : Word32 L_temp;
3389 :
3390 2 : temp = div_s( 16384, round_fx( b ) );
3391 2 : L_temp = Mult_32_16( a, temp );
3392 2 : temp2 = sub( 31 - 1, exp_b );
3393 2 : temp2 = add( temp2, exp_a );
3394 :
3395 2 : temp = norm_l( L_temp );
3396 :
3397 2 : *exp_out = add( temp, temp2 );
3398 2 : move16();
3399 :
3400 2 : return L_shl( L_temp, temp );
3401 : }
3402 :
3403 :
3404 : /*-------------------------------------------------------------------*
3405 : * Calc_Energy_Autoscaled
3406 : *
3407 : * Calculate Energy with overflow protection
3408 : *-------------------------------------------------------------------*/
3409 2775366 : Word32 Calc_Energy_Autoscaled( /* o: Result (Energy) */
3410 : const Word16 *signal, /* i: Signal */
3411 : Word16 signal_exp, /* i: Exponent of Signal (Q of Signal) */
3412 : Word16 len, /* i: Frame Length */
3413 : Word16 *energy_exp /* o: Exponent of Energy (Q of Energy) */
3414 : )
3415 : {
3416 : Word16 temp, temp2;
3417 : Word32 L_temp, L_Energy;
3418 : Word16 i, j;
3419 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
3420 2775366 : Flag Overflow = 0;
3421 2775366 : move32();
3422 : #endif
3423 :
3424 2775366 : Overflow = 0;
3425 2775366 : move16();
3426 :
3427 2775366 : temp2 = 0;
3428 2775366 : move16();
3429 2775366 : L_Energy = L_deposit_l( 1 );
3430 2775366 : j = s_and( 7, len );
3431 2775366 : FOR( i = 0; i < j; i++ )
3432 : {
3433 : /* divide by 2 so energy will be divided by 4 */
3434 : #ifdef ISSUE_1836_replace_overflow_libcom
3435 0 : temp = mult_r( *signal++, 16384 );
3436 : #else
3437 : temp = mult_ro( *signal++, 16384, &Overflow );
3438 : #endif
3439 0 : L_Energy = L_mac0_o( L_Energy, temp, temp, &Overflow );
3440 : }
3441 8974376 : FOR( i = j; i < len; i += 8 ) /* Process 8 Samples at a time */
3442 : {
3443 : /* divide by 2 so energy will be divided by 4 */
3444 6199010 : temp = mult_ro( *signal++, 16384, &Overflow );
3445 6199010 : L_temp = L_mult0( temp, temp );
3446 49592080 : FOR( j = 1; j < 8; j++ )
3447 : {
3448 : #ifdef ISSUE_1836_replace_overflow_libcom
3449 43393070 : temp = mult_r( *signal++, 16384 );
3450 : #else
3451 : temp = mult_ro( *signal++, 16384, &Overflow );
3452 : #endif
3453 43393070 : L_temp = L_mac0_o( L_temp, temp, temp, &Overflow );
3454 : }
3455 : /*Overfloe will never happen because temp2 is always positive*/
3456 6199010 : L_temp = L_shr( L_temp, temp2 );
3457 : /* Here we try the addition just to check if we can sum
3458 : the energy of the small (8 Iterations) loop with the
3459 : total energy calculated so far without an overflow.
3460 : The result is discarded. If there is an overflow both
3461 : energies are div by 2. Otherwise, nothing is done.
3462 : After the 'IF', the sum is done again and will always
3463 : be without an overflow. */
3464 6199010 : L_add_o( L_Energy, L_temp, &Overflow );
3465 6199010 : IF( Overflow != 0 )
3466 : {
3467 47 : L_Energy = L_shr( L_Energy, 1 );
3468 47 : L_temp = L_shr( L_temp, 1 );
3469 47 : temp2 = add( temp2, 1 );
3470 47 : Overflow = 0;
3471 47 : move16();
3472 : }
3473 6199010 : L_Energy = L_add_o( L_Energy, L_temp, &Overflow );
3474 : }
3475 : /* Calc Final Exponent (sub 2 because of the mult_r by 16384 that already divs the ener by 4) */
3476 2775366 : temp2 = sub( sub( shl( signal_exp, 1 ), temp2 ), 2 );
3477 :
3478 2775366 : *energy_exp = temp2;
3479 2775366 : move16();
3480 :
3481 2775366 : return L_Energy;
3482 : }
3483 :
3484 3584128 : Word16 Find_Max_Norm16( const Word16 *src, Word16 len )
3485 : {
3486 : Word16 i;
3487 : Word16 max16;
3488 :
3489 : /* it starts at '0' and not '1' like in Find_Max_Norm32() */
3490 : /* and that is necessary. */
3491 3584128 : max16 = 0;
3492 3584128 : move16();
3493 :
3494 2275061410 : FOR( i = 0; i < len; i++ )
3495 : {
3496 2271477282 : max16 = s_max( max16, abs_s( *src++ ) );
3497 : }
3498 :
3499 3584128 : return norm_s( max16 );
3500 : }
3501 :
3502 3553385 : Word16 Find_Max_Norm32( const Word32 *src, Word16 len )
3503 : {
3504 : Word16 i;
3505 : Word32 max32;
3506 :
3507 3553385 : max32 = L_deposit_l( 1 );
3508 :
3509 2840854324 : FOR( i = 0; i < len; i++ )
3510 : {
3511 2837300939 : max32 = L_max( max32, L_abs( *src++ ) );
3512 : }
3513 :
3514 3553385 : return norm_l( max32 );
3515 : }
3516 :
3517 : /*-------------------------------------------------------------------*
3518 : * Sqrt_Ratio32
3519 : *
3520 : * Calculate Sqrt of Val1/Val2
3521 : *-------------------------------------------------------------------*/
3522 1091 : Word32 Sqrt_Ratio32( /* o: Result in Q31 */
3523 : Word32 L_val1, /* i: Mantisa of Val1 */
3524 : Word16 exp1, /* i: Exp of Val1 (>0: Val was Left Shifted, <0:Right Shifted) */
3525 : Word32 L_val2, /* i: Mantisa of Val2 */
3526 : Word16 exp2, /* i: Exp of Val2 (same as exp1) */
3527 : Word16 *exp /* o: Exp of Result (# of 'L_shl' Req to get to Final Value) */
3528 : )
3529 : {
3530 : Word16 temp;
3531 :
3532 : /* Normalize Energy #1 */
3533 1091 : temp = norm_l( L_val1 );
3534 1091 : L_val1 = L_shl( L_val1, temp );
3535 : /* Adjust Exponent of Energy #1 */
3536 1091 : exp1 = add( exp1, temp );
3537 :
3538 : /* Normalize Energy #2 */
3539 1091 : temp = norm_l( L_val2 );
3540 1091 : L_val2 = L_shl( L_val2, temp );
3541 : /* Adjust Exponent of Energy #1 */
3542 1091 : exp2 = add( exp2, temp );
3543 :
3544 : /* Prepare for Inverse */
3545 1091 : temp = round_fx_sat( L_val1 );
3546 1091 : temp = div_s( 16384, temp );
3547 : /* Mult Now */
3548 1091 : L_val2 = Mult_32_16( L_val2, temp );
3549 1091 : exp1 = add( sub( exp2, exp1 ), 15 * 2 );
3550 :
3551 : /* Here Result of ('L_val2' / 2^'exp2') / ('L_val1' / 2^'exp1') is */
3552 : /* 'L_val2' / 2^'exp1' */
3553 : /* Which is val2/val1 instead of val1/val2 because we will use Inverted Square Root */
3554 : /* Normalize before Square Root */
3555 1091 : temp = norm_l( L_val2 );
3556 1091 : L_val2 = L_shl( L_val2, temp );
3557 1091 : exp1 = add( temp, exp1 );
3558 : /* Do Sqrt */
3559 1091 : temp = sub( 31, exp1 );
3560 1091 : L_val1 = Isqrt_lc( L_val2, &temp );
3561 :
3562 1091 : *exp = temp;
3563 1091 : move16();
3564 :
3565 1091 : return L_val1;
3566 : }
3567 :
3568 0 : Word16 Invert16( /* result in Q'15 + 'exp' */
3569 : Word16 val,
3570 : Word16 *exp )
3571 : {
3572 : Word16 temp;
3573 :
3574 : /* prevent 0 input */
3575 0 : val = s_max( val, 1 );
3576 : /* Normalize Value */
3577 0 : temp = norm_s( val );
3578 0 : val = shl( val, temp );
3579 :
3580 0 : *exp = sub( sub( 15 - 1, *exp ), temp );
3581 0 : move16(); /* -1 because of 0x4000 is 1.0 in Q14 (and not Q15) */
3582 :
3583 0 : temp = div_s( 0x4000, val );
3584 :
3585 0 : return temp;
3586 : }
3587 :
3588 0 : Word16 find_rem( Word16 n, Word16 m, Word16 *r )
3589 : {
3590 : Word16 i, q1, q2, qd;
3591 : Word32 Ltemp2;
3592 : Word32 Lacc;
3593 :
3594 0 : test();
3595 0 : test();
3596 0 : IF( n <= 0 || m <= 0 || n < m )
3597 : {
3598 0 : *r = n;
3599 0 : move16();
3600 0 : return ( 0 );
3601 : }
3602 :
3603 0 : q1 = norm_s( n );
3604 0 : q1 = sub( q1, 1 );
3605 0 : Lacc = L_deposit_h( shl( n, q1 ) );
3606 0 : qd = sub( q1, 1 );
3607 0 : q2 = norm_s( m );
3608 0 : q2 = sub( q2, 1 );
3609 0 : Ltemp2 = L_deposit_h( shl( m, q2 ) );
3610 0 : qd = sub( q2, qd );
3611 0 : q2 = add( q2, 1 );
3612 :
3613 0 : FOR( i = 0; i < qd; i++ )
3614 : {
3615 0 : Lacc = L_sub( Lacc, Ltemp2 );
3616 0 : IF( Lacc >= 0 )
3617 : {
3618 0 : Lacc = L_add( L_shl( Lacc, 1 ), 1 );
3619 : }
3620 : ELSE
3621 : {
3622 0 : Lacc = L_add( Lacc, Ltemp2 );
3623 0 : Lacc = L_shl( Lacc, 1 );
3624 : }
3625 : }
3626 0 : q1 = extract_l( Lacc );
3627 0 : Ltemp2 = L_shr( Lacc, q2 );
3628 0 : *r = extract_h( Ltemp2 );
3629 0 : move16();
3630 0 : return ( q1 );
3631 : }
3632 :
3633 :
3634 0 : Word32 find_remd( Word32 n, Word32 m, Word32 *r )
3635 : {
3636 : Word16 i, q1, q2, qd;
3637 : Word32 Ltemp2, qo;
3638 : Word32 Lacc;
3639 :
3640 0 : test();
3641 0 : test();
3642 0 : IF( n <= 0 || m <= 0 || n < m )
3643 : {
3644 0 : *r = n;
3645 0 : move16();
3646 0 : return ( 0 );
3647 : }
3648 :
3649 0 : q1 = norm_l( n );
3650 0 : q1 = sub( q1, 1 );
3651 0 : Lacc = L_shl( n, q1 );
3652 0 : qd = sub( q1, 1 );
3653 0 : q2 = norm_l( m );
3654 0 : q2 = sub( q2, 1 );
3655 0 : Ltemp2 = L_shl( m, q2 );
3656 0 : qd = sub( q2, qd );
3657 0 : q2 = add( q2, 1 );
3658 0 : qo = 0;
3659 0 : move16();
3660 :
3661 0 : FOR( i = 0; i < qd; i++ )
3662 : {
3663 0 : Lacc = L_sub( Lacc, Ltemp2 );
3664 0 : qo = L_shl( qo, 1 );
3665 0 : IF( Lacc >= 0 )
3666 : {
3667 0 : Lacc = L_shl( Lacc, 1 );
3668 0 : qo = L_add( qo, 1 );
3669 : }
3670 : ELSE
3671 : {
3672 0 : Lacc = L_add( Lacc, Ltemp2 );
3673 0 : Lacc = L_shl( Lacc, 1 );
3674 : }
3675 : }
3676 0 : *r = L_shr( Lacc, q2 );
3677 0 : move16();
3678 0 : return ( qo );
3679 : }
3680 :
3681 0 : Word16 rint_new_fx(
3682 : Word32 x /*Q16 */
3683 : )
3684 : {
3685 : Word16 a;
3686 : Word32 L_tmp;
3687 : Word16 frac, tmp;
3688 :
3689 : /* middle value point test */
3690 0 : frac = lshr( extract_l( x ), 1 ); /*Q15 */
3691 0 : tmp = sub( frac, 0x4000 );
3692 :
3693 0 : IF( !tmp )
3694 : {
3695 0 : a = add( extract_h( x ), 1 );
3696 :
3697 0 : IF( s_and( a, 1 ) == 0 )
3698 : {
3699 0 : return a;
3700 : }
3701 0 : IF( s_and( a, 1 ) != 0 )
3702 : {
3703 0 : return extract_h( x );
3704 : }
3705 0 : return extract_h( x );
3706 : }
3707 : ELSE
3708 : {
3709 0 : L_tmp = L_add( x, 32768 ); /*Q16 */
3710 0 : return extract_h( L_tmp );
3711 : }
3712 : }
3713 :
3714 :
3715 : /*===================================================================*/
3716 : /* FUNCTION : erb_diff_search_fx () */
3717 : /*-------------------------------------------------------------------*/
3718 : /* PURPOSE : erb amplitude VQ search for QPPP */
3719 : /*-------------------------------------------------------------------*/
3720 : /* INPUT ARGUMENTS : */
3721 : /* _ (Word16 []) prev_erb : Previous erb amplitude, Q13 */
3722 : /* _ (Word16 []) curr_erb : Current erb amplitude, Q13 */
3723 : /* _ (Word16 []) dif_erb: erb differential, Q13 */
3724 : /* _ (Word16 []) pow_spec : LPC power spectrum, Q7 */
3725 : /* _ (Word16 [][]) cb_fx : differential erb codebook, Q13 */
3726 : /* _ (Word16) cb_size : codebook size */
3727 : /* _ (Word16) cb_dim : codebook dimension */
3728 : /* _ (Word16) offset : index to current segment of erb array */
3729 : /* for quantization */
3730 : /*-------------------------------------------------------------------*/
3731 : /* OUTPUT ARGUMENTS : */
3732 : /* _ None */
3733 : /*-------------------------------------------------------------------*/
3734 : /* INPUT/OUTPUT ARGUMENTS : */
3735 : /* _ None */
3736 : /*-------------------------------------------------------------------*/
3737 : /* RETURN ARGUMENTS : */
3738 : /* _ (Word16) index: best codebook index */
3739 : /*-------------------------------------------------------------------*/
3740 : /* CALLED FROM : TX */
3741 : /*===================================================================*/
3742 :
3743 0 : Word16 erb_diff_search_fx( Word16 *prev_erb, const Word16 *curr_erb, Word16 *dif_erb, Word16 *pow_spec, const Word16 *cb_fx, Word16 cb_size, Word16 cb_dim, Word16 offset )
3744 : {
3745 : Word16 i, j, mmseindex;
3746 : Word16 dh, dl;
3747 : Word32 mmse;
3748 : Word32 Ltemp1;
3749 : Word32 Lacc;
3750 :
3751 0 : mmse = EVS_LW_MAX;
3752 0 : move32();
3753 0 : mmseindex = -1;
3754 0 : move16();
3755 0 : FOR( j = 0; j < cb_size; j++ )
3756 : {
3757 :
3758 0 : Lacc = L_deposit_l( 0 );
3759 0 : FOR( i = 0; i < cb_dim; i++ )
3760 : {
3761 0 : IF( add_sat( cb_fx[j * cb_dim + i], prev_erb[i + offset] ) < 0 )
3762 : {
3763 0 : Ltemp1 = L_mult( curr_erb[i + offset], curr_erb[i + offset] ); /* Q27 */
3764 0 : dh = extract_h( Ltemp1 );
3765 0 : dl = extract_l( Ltemp1 );
3766 0 : IF( dl < 0 )
3767 : {
3768 0 : Ltemp1 = L_shl( L_add( 65536, dl ), 14 ); /* */
3769 0 : Ltemp1 = Mult_32_16( Ltemp1, pow_spec[i + offset] );
3770 0 : Ltemp1 = L_shl( Ltemp1, 1 );
3771 : }
3772 : ELSE
3773 : {
3774 0 : Ltemp1 = (Word32) L_mult0( pow_spec[i + offset], dl );
3775 : }
3776 0 : Ltemp1 = L_add( L_shr( Ltemp1, 15 ), L_mult( pow_spec[i + offset], dh ) );
3777 : }
3778 : ELSE
3779 : {
3780 0 : dh = sub_sat( dif_erb[i + offset], cb_fx[j * cb_dim + i] ); /* Q13 */
3781 0 : Ltemp1 = L_mult_sat( dh, dh ); /* Q27 */
3782 0 : dh = extract_h( Ltemp1 );
3783 0 : dl = extract_l( Ltemp1 );
3784 :
3785 0 : IF( dl < 0 )
3786 : {
3787 0 : Ltemp1 = L_shl( L_add( 65536, dl ), 14 ); /* */
3788 0 : Ltemp1 = Mult_32_16( Ltemp1, pow_spec[i + offset] );
3789 0 : Ltemp1 = L_shl( Ltemp1, 1 );
3790 : }
3791 : ELSE
3792 : {
3793 0 : Ltemp1 = (Word32) L_mult0( pow_spec[i + offset], dl ); /* Q33 */
3794 : }
3795 :
3796 0 : Ltemp1 = L_add( L_shr( Ltemp1, 15 ), L_mult( pow_spec[i + offset], dh ) ); /* Q18 */
3797 : }
3798 :
3799 0 : IF( LT_16( cb_fx[j * cb_dim + i], dif_erb[i + offset] ) )
3800 : {
3801 0 : dh = extract_h( Ltemp1 );
3802 0 : dl = extract_l( Ltemp1 );
3803 0 : IF( dl < 0 )
3804 : {
3805 0 : Ltemp1 = L_shl( L_add( 65536, dl ), 14 ); /* */
3806 0 : Ltemp1 = Mult_32_16( Ltemp1, 29491 );
3807 0 : Ltemp1 = L_shl( Ltemp1, 1 );
3808 : }
3809 : ELSE
3810 : {
3811 0 : Ltemp1 = (Word32) L_mult0( 29491, dl ); /* 29491=0.9 in Q15 */
3812 : }
3813 0 : Ltemp1 = L_add( L_shr( Ltemp1, 15 ), L_mult( dh, 29491 ) );
3814 : }
3815 0 : Lacc = L_add( Lacc, Ltemp1 ); /* Q18 */
3816 : }
3817 :
3818 0 : IF( LT_32( Lacc, mmse ) )
3819 : {
3820 0 : mmse = L_add( Lacc, 0 );
3821 0 : mmseindex = j;
3822 0 : move16();
3823 : }
3824 : }
3825 :
3826 0 : return ( mmseindex );
3827 : }
3828 491688 : void Acelp_dec_total_exc(
3829 : Word16 *exc_fx, /* i/o: adapt. excitation exc */
3830 : Word16 *exc2_fx, /* i/o: adapt. excitation/total exc */
3831 : const Word16 gain_code16, /* i : Gain code Q0 */
3832 : const Word16 gain_pit_fx, /* i ; Pitch gain in Q14 */
3833 : const Word16 i_subfr, /* i ; subfr */
3834 : const Word16 *code_fx, /* i : code in Q9 */
3835 : const Word16 L_subfr /* i : Subframne lenght */
3836 : )
3837 : {
3838 : Word16 i;
3839 : Word32 L_tmp;
3840 :
3841 31959720 : FOR( i = 0; i < L_subfr; i++ )
3842 : {
3843 31468032 : L_tmp = L_shl_sat( L_mult( gain_pit_fx, exc_fx[i + i_subfr] ), 1 ); /*Q16+Q_exc*/
3844 31468032 : exc2_fx[i + i_subfr] = round_fx_sat( L_tmp ); /*Q_exc*/
3845 31468032 : L_tmp = L_add_sat( L_tmp, L_shl_sat( L_mult( gain_code16, code_fx[i] ), 6 ) ); /*Q16+Q_exc*/
3846 31468032 : exc_fx[i + i_subfr] = round_fx_sat( L_tmp ); /*Q_exc*/
3847 31468032 : move16();
3848 31468032 : move16();
3849 : }
3850 491688 : }
3851 :
3852 : /*-------------------------------------------------------------------*
3853 : * UL_inverse
3854 : *
3855 : * Calculate inverse of UL_val. Output in Q_exp.
3856 : *-------------------------------------------------------------------*/
3857 306303 : UWord32 UL_inverse( const UWord32 UL_val, Word16 *exp )
3858 : {
3859 : UWord32 UL_tmp;
3860 :
3861 306303 : *exp = norm_ul( UL_val );
3862 306303 : move16();
3863 306303 : UL_tmp = UL_lshl( UL_val, *exp ); /* Q32 */
3864 :
3865 306303 : *exp = add( 32, sub( 31, *exp ) );
3866 306303 : move16();
3867 :
3868 306303 : return UL_div( 0x80000000, UL_tmp );
3869 : }
3870 :
3871 : /*-------------------------------------------------------------------*
3872 : * UL_div
3873 : *
3874 : * Calculate UL_num/UL_den. UL_num assumed to be Q31, UL_den assumed
3875 : * to be Q32, then result is in Q32.
3876 : *-------------------------------------------------------------------*/
3877 612606 : UWord32 UL_div( const UWord32 UL_num, const UWord32 UL_den )
3878 : {
3879 : UWord32 UL_e, UL_Q;
3880 : UWord32 UL_msb, UL_lsb;
3881 : Word16 i;
3882 :
3883 612606 : UL_e = UL_subNsD( 0xffffffff, UL_den );
3884 612606 : UL_Q = UL_num;
3885 612606 : move32();
3886 :
3887 3675636 : FOR( i = 0; i < 5; i++ )
3888 : {
3889 3063030 : Mpy_32_32_uu( UL_Q, UL_e, &UL_msb, &UL_lsb ); /*31+32-32=31 */
3890 3063030 : UL_Q = UL_addNsD( UL_Q, UL_msb );
3891 3063030 : Mpy_32_32_uu( UL_e, UL_e, &UL_e, &UL_lsb ); /*32+32-32=32 */
3892 : }
3893 :
3894 612606 : return UL_Q;
3895 : }
3896 :
3897 : /*-----------------------------------------------------------------------------
3898 : * ratio()
3899 : *
3900 : * Divide the numerator by the denominator.
3901 : *----------------------------------------------------------------------------*/
3902 6849384 : Word16 ratio( const Word32 numer, const Word32 denom, Word16 *expo )
3903 : {
3904 : Word16 expNumer, expDenom;
3905 : Word16 manNumer, manDenom;
3906 : Word16 quotient;
3907 :
3908 6849384 : expDenom = norm_l( denom ); /* exponent */
3909 6849384 : manDenom = extract_h( L_shl( denom, expDenom ) ); /* mantissa */
3910 6849384 : expNumer = norm_l( numer ); /* exponent */
3911 6849384 : manNumer = extract_h( L_shl( numer, expNumer ) ); /* mantissa */
3912 6849384 : manNumer = shr( manNumer, 1 ); /* Ensure the numerator < the denominator */
3913 6849384 : quotient = div_s( manNumer, manDenom ); /* in Q14 */
3914 :
3915 6849384 : *expo = sub( expNumer, expDenom );
3916 6849384 : move16();
3917 6849384 : return quotient; /* Q14 */
3918 : }
3919 :
3920 : /*-----------------------------------------------------------------------*
3921 : * Function hp400_12k8() *
3922 : * *
3923 : * 2nd order Cheb2 high pass filter with cut off frequency at 400 Hz. *
3924 : * Optimized for fixed-point to get the following frequency response : *
3925 : * *
3926 : * frequency : 0Hz 100Hz 200Hz 300Hz 400Hz 630Hz 1.5kHz 3kHz *
3927 : * dB loss : -infdB -30dB -20dB -10dB -3dB +6dB +1dB 0dB *
3928 : * *
3929 : * Algorithm : *
3930 : * *
3931 : * y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] *
3932 : * + a[1]*y[i-1] + a[2]*y[i-2]; *
3933 : * *
3934 : * short b[3] = {3660, -7320, 3660}; in Q12 *
3935 : * short a[3] = {4096, 7320, -3540}; in Q12 *
3936 : * *
3937 : * float --> b[3] = {0.893554687, -1.787109375, 0.893554687}; *
3938 : * a[3] = {1.000000000, 1.787109375, -0.864257812}; *
3939 : *-----------------------------------------------------------------------*/
3940 0 : void hp400_12k8_fx(
3941 : Word16 signal[], /* i/o: input signal / output is divided by 16 */
3942 : const Word16 lg, /* i : lenght of signal */
3943 : Word16 mem[] /* i/o: filter memory [6] */
3944 : )
3945 : {
3946 : Word16 i;
3947 : Word16 y1_hi, y1_lo;
3948 : Word32 L_tmp, L_tmp2, L_tmp3;
3949 :
3950 0 : y1_hi = mem[2];
3951 0 : move16();
3952 0 : y1_lo = mem[3];
3953 0 : move16();
3954 :
3955 0 : L_tmp3 = L_mac( 16384L, mem[1], a_hp400_fx[2] ); /* rounding to maximize precision */
3956 0 : L_tmp3 = L_mac( L_tmp3, y1_lo, a_hp400_fx[1] );
3957 0 : L_tmp3 = L_shr( L_tmp3, 15 );
3958 0 : L_tmp2 = L_mac( L_tmp3, mem[0], a_hp400_fx[2] );
3959 0 : L_tmp2 = L_mac( L_tmp2, mem[5], b_hp400_fx[2] );
3960 0 : L_tmp2 = L_mac( L_tmp2, mem[4], b_hp400_fx[1] );
3961 0 : L_tmp3 = L_mult( mem[4], b_hp400_fx[2] );
3962 :
3963 0 : mem[5] = signal[lg - 2];
3964 0 : move16();
3965 0 : FOR( i = 1; i < lg; i++ )
3966 : {
3967 : /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] */
3968 : /* + a[1]*y[i-1] + a[2] * y[i-2] */
3969 :
3970 0 : L_tmp = L_mac( L_tmp2, y1_hi, a_hp400_fx[1] );
3971 0 : L_tmp = L_mac( L_tmp, *signal, b_hp400_fx[0] );
3972 :
3973 0 : L_tmp = L_shl( L_tmp, 1 ); /* coeff Q12 --> Q13 */
3974 :
3975 0 : L_tmp2 = L_mac( L_tmp3, y1_hi, a_hp400_fx[2] );
3976 0 : L_tmp2 = L_mac( L_tmp2, *signal, b_hp400_fx[1] );
3977 0 : L_tmp3 = L_mac( 16384L, y1_lo, a_hp400_fx[2] ); /* rounding to maximize precision */
3978 :
3979 0 : y1_lo = L_Extract_lc( L_tmp, &y1_hi );
3980 :
3981 0 : L_tmp3 = L_mac( L_tmp3, y1_lo, a_hp400_fx[1] );
3982 0 : L_tmp3 = L_shr( L_tmp3, 15 );
3983 :
3984 0 : L_tmp2 = L_add( L_tmp3, L_tmp2 );
3985 :
3986 0 : L_tmp3 = L_mult( *signal, b_hp400_fx[2] );
3987 :
3988 : /* signal is divided by 16 to avoid overflow in energy computation */
3989 0 : *signal++ = round_fx( L_tmp );
3990 0 : move16();
3991 : }
3992 :
3993 : /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] */
3994 : /* + a[1]*y[i-1] + a[2] * y[i-2] */
3995 :
3996 0 : L_tmp = L_mac( L_tmp2, y1_hi, a_hp400_fx[1] );
3997 :
3998 0 : mem[4] = *signal;
3999 0 : move16();
4000 0 : L_tmp = L_mac( L_tmp, mem[4], b_hp400_fx[0] );
4001 :
4002 0 : L_tmp = L_shl( L_tmp, 1 ); /* coeff Q12 --> Q13 */
4003 :
4004 0 : mem[0] = y1_hi;
4005 0 : move16();
4006 0 : mem[1] = y1_lo;
4007 0 : move16();
4008 0 : L_Extract( L_tmp, &mem[2], &mem[3] );
4009 :
4010 : /* signal is divided by 16 to avoid overflow in energy computation */
4011 0 : *signal++ = round_fx( L_tmp );
4012 0 : move16();
4013 :
4014 0 : return;
4015 : }
4016 :
4017 59556 : void hp400_12k8_ivas_fx(
4018 : Word16 signal[], /* i/o: input signal / output is divided by 16 */
4019 : const Word16 lg, /* i : lenght of signal */
4020 : Word16 mem[] /* i/o: filter memory [6] */
4021 : )
4022 : {
4023 : Word16 i;
4024 : Word16 x0, x1, x2;
4025 : Word32 L_tmp, yy1, y2;
4026 :
4027 59556 : yy1 = L_Comp( mem[2], mem[3] ); /* Q_syn + 13 */
4028 59556 : y2 = L_Comp( mem[0], mem[1] ); /* Q_syn + 13 */
4029 59556 : x0 = mem[4]; /* Q_syn */
4030 59556 : move16();
4031 59556 : x1 = mem[5]; /* Q_syn */
4032 59556 : move16();
4033 :
4034 3871140 : FOR( i = 0; i < lg; i++ )
4035 : {
4036 3811584 : x2 = x1; /* Q_syn */
4037 3811584 : move16();
4038 3811584 : x1 = x0; /* Q_syn */
4039 3811584 : move16();
4040 3811584 : x0 = signal[i]; /* Q_syn */
4041 3811584 : move16();
4042 :
4043 3811584 : L_tmp = Mpy_32_16_1( yy1, a_hp400_ivas_fx[1] ); /*yy1 * a_hp400[1]*/ /* Qx(Q_of_yy1) + 10 ---->( (Q_syn+13) + 12 - 15)*/
4044 3811584 : L_tmp = Madd_32_16( L_tmp, y2, a_hp400_ivas_fx[2] ); /*y2 * a_hp400[2]*/ /* Qx + 10 ---->( (Q_syn+13) + 12 - 15)*/
4045 3811584 : L_tmp = L_shl( L_tmp, 3 ); /* shifting by 3 to maintain same Q (Q_syn+13) */
4046 :
4047 3811584 : L_tmp = L_mac( L_tmp, x0, b_hp400_fx[0] ); /* Q_syn + 13 */
4048 3811584 : L_tmp = L_mac( L_tmp, x1, b_hp400_fx[1] ); /* Q_syn + 13 */
4049 3811584 : L_tmp = L_mac( L_tmp, x2, b_hp400_fx[2] ); /* Q_syn + 13 */
4050 :
4051 3811584 : y2 = yy1; /* Q_syn + 13 */
4052 3811584 : move32();
4053 3811584 : yy1 = L_tmp; /* Q_syn + 13 */
4054 3811584 : move32();
4055 :
4056 3811584 : signal[i] = round_fx( L_tmp ); /* Q_syn - 3 */
4057 3811584 : move16();
4058 : }
4059 :
4060 59556 : L_Extract( yy1, &mem[2], &mem[3] );
4061 59556 : L_Extract( y2, &mem[0], &mem[1] );
4062 59556 : mem[4] = x0; /* Q_syn */
4063 59556 : mem[5] = x1; /* Q_syn */
4064 59556 : move16();
4065 59556 : move16();
4066 59556 : return;
4067 : }
4068 :
4069 0 : Word16 dot_prod_satcontr( const Word16 *x, const Word16 *y, Word16 qx, Word16 qy, Word16 *qo, Word16 len )
4070 : {
4071 : Word16 tmp_tab_x[L_FRAME16k];
4072 : Word16 tmp_tab_y[L_FRAME16k];
4073 : Word16 shift, q, ener, i;
4074 : Word32 L_tmp;
4075 : Word16 *pt1, *pt2;
4076 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
4077 0 : Flag Overflow = 0;
4078 0 : move32();
4079 : #endif
4080 :
4081 :
4082 0 : Copy( x, tmp_tab_x, len ); /* OPTIMIZE !!!!! the copy into local table is not necessary */
4083 0 : Copy( y, tmp_tab_y, len ); /* could be reworked to do a 1st iteration with the original x[] and y[] */
4084 : /* then check if there is an overflow and do a more complex 2nd, 3rd, ... processing */
4085 0 : shift = 0;
4086 0 : move16();
4087 : BASOP_SATURATE_WARNING_OFF_EVS
4088 : DO
4089 : {
4090 0 : Overflow = 0;
4091 0 : move16();
4092 0 : L_tmp = L_shl_o( 1, s_max( sub( add( add( qx, qy ), 7 ), shift ), 0 ), &Overflow );
4093 0 : pt1 = tmp_tab_x;
4094 0 : pt2 = tmp_tab_y;
4095 0 : FOR( i = 0; i < len; i++ )
4096 : {
4097 0 : L_tmp = L_mac0_o( L_tmp, *pt1++, *pt2++, &Overflow ); /*Q(qx+qy-shift) */
4098 : }
4099 :
4100 0 : IF( Overflow != 0 )
4101 : {
4102 0 : Scale_sig( tmp_tab_x, len, -2 );
4103 0 : Scale_sig( tmp_tab_y, len, -2 );
4104 0 : shift = add( shift, 4 );
4105 : }
4106 : }
4107 0 : WHILE( Overflow != 0 );
4108 : BASOP_SATURATE_WARNING_ON_EVS
4109 :
4110 0 : q = norm_l( L_tmp );
4111 0 : L_tmp = L_shl( L_tmp, q ); /*Q(qx+qy-shift+q) */
4112 0 : ener = extract_h( L_tmp ); /*Q(qx+qy-shift+q-16) */
4113 0 : q = add( q, add( qx, qy ) );
4114 0 : *qo = sub( q, add( shift, 16 ) );
4115 0 : move16();
4116 0 : return ener;
4117 : }
4118 :
4119 :
4120 : /*
4121 : * E_UTIL_f_convolve
4122 : *
4123 : * Parameters:
4124 : * x I: input vector <14bits
4125 : * h I: impulse response (or second input vector) (1Q14)
4126 : * y O: output vetor (result of convolution)
4127 : *
4128 : * Function:
4129 : * Perform the convolution between two vectors x[] and h[] and
4130 : * write the result in the vector y[]. All vectors are of length L.
4131 : * Only the first L samples of the convolution are considered.
4132 : * Vector size = L_SUBFR
4133 : *
4134 : * Returns:
4135 : * void
4136 : */
4137 0 : void E_UTIL_f_convolve( const Word16 x[], const Word16 h[], Word16 y[], const Word16 size )
4138 : {
4139 : Word16 i, n;
4140 : Word32 L_sum;
4141 : Word64 L64_sum;
4142 :
4143 0 : FOR( n = 0; n < size; n++ )
4144 : {
4145 0 : L64_sum = 0;
4146 0 : move64();
4147 0 : FOR( i = 0; i < n; i++ )
4148 : {
4149 0 : L64_sum = W_mac_16_16( L64_sum, x[i], h[n - i] );
4150 : }
4151 0 : L_sum = W_sat_l( L64_sum );
4152 0 : y[n] = mac_r( L_sum, x[i], h[0] );
4153 0 : move16();
4154 : }
4155 0 : return;
4156 : }
4157 :
4158 : /*-----------------------------------------------------------------------------
4159 : * floating_point_add:
4160 : *
4161 : * Add two floating point numbers: x <- x + y.
4162 : *----------------------------------------------------------------------------*/
4163 21121 : void floating_point_add(
4164 : Word32 *mx, /* io: mantissa of the addend Q31 */
4165 : Word16 *ex, /* io: exponent of the addend Q0 */
4166 : const Word32 my, /* i: mantissa of the adder Q31 */
4167 : const Word16 ey /* i: exponent of the adder Q0 */
4168 : )
4169 : {
4170 : Word32 accX, accY;
4171 : Word16 align, expo;
4172 : /* NB: This function will not work properly if the mantissa is zero and the exponent is not 32.
4173 : It is up to the caller function to avoid this condition. */
4174 : /* Ensure 1 bit headroom before addition. */
4175 21121 : accX = L_shr( *mx, 1 );
4176 21121 : accY = L_shr( my, 1 );
4177 : /* First, align the Q-points of the two operands. Then, add. */
4178 21121 : align = sub( *ex, ey );
4179 :
4180 21121 : IF( align < 0 )
4181 : {
4182 16697 : accX = L_add( accX, L_shl( accY, align ) );
4183 : }
4184 : ELSE
4185 : {
4186 4424 : accX = L_add( accY, L_shr( accX, align ) );
4187 4424 : *ex = ey;
4188 4424 : move16();
4189 : }
4190 : /* Normalize the result and update the mantissa and exponent. */
4191 21121 : expo = norm_l( accX );
4192 21121 : *mx = L_shl( accX, expo );
4193 21121 : *ex = sub( add( *ex, expo ), 1 ); /* Subtract 1 due to 1-bit down-shift above ensuring 1 bit headroom before addition. */
4194 21121 : move32();
4195 21121 : move16();
4196 21121 : return;
4197 : }
4198 :
4199 : /*-------------------------------------------------------------------*
4200 : * delay_signal_fx()
4201 : *
4202 : * Delay buffer by defined number of samples
4203 : *-------------------------------------------------------------------*/
4204 :
4205 940034 : void delay_signal_fx(
4206 : Word16 x[], /* i/o: signal to be delayed */
4207 : const Word16 len, /* i : length of the input signal */
4208 : Word16 mem[], /* i/o: synchronization memory */
4209 : const Word16 delay /* i : delay in samples */
4210 : )
4211 : {
4212 : Word16 tmp_buffer[L_FRAME48k];
4213 :
4214 940034 : Copy( mem, tmp_buffer, delay );
4215 940034 : Copy( x + sub( len, delay ), mem, delay );
4216 940034 : Copy( x, x + delay, sub( len, delay ) );
4217 940034 : Copy( tmp_buffer, x, delay );
4218 :
4219 940034 : return;
4220 : }
4221 :
4222 2454926 : void delay_signal32_fx(
4223 : Word32 x[], /* i/o: signal to be delayed */
4224 : const Word16 len, /* i : length of the input signal */
4225 : Word32 mem[], /* i/o: synchronization memory */
4226 : const Word16 delay /* i : delay in samples */
4227 : )
4228 : {
4229 : Word32 tmp_buffer[L_FRAME48k];
4230 :
4231 2454926 : Copy32( mem, tmp_buffer, delay );
4232 2454926 : Copy32( x + sub( len, delay ), mem, delay );
4233 2454926 : Copy32( x, x + delay, sub( len, delay ) );
4234 2454926 : Copy32( tmp_buffer, x, delay );
4235 :
4236 2454926 : return;
4237 : }
4238 :
4239 54184 : void delay_signal_q_adj_fx(
4240 : Word32 x[], /* i/o: signal to be delayed */
4241 : const Word16 len, /* i : length of the input signal */
4242 : Word32 mem[], /* i/o: synchronization memory */
4243 : const Word16 delay, /* i : delay in samples */
4244 : const Word16 q_x,
4245 : const Word16 q_mem )
4246 : {
4247 :
4248 : Word32 tmp_buffer[L_FRAME48k];
4249 :
4250 54184 : Copy32( mem, tmp_buffer, delay );
4251 54184 : Copy32( x + sub( len, delay ), mem, delay );
4252 54184 : Copy32( x, x + delay, sub( len, delay ) );
4253 :
4254 :
4255 54184 : IF( EQ_16( q_x, q_mem ) )
4256 : {
4257 46208 : Copy32( tmp_buffer, x, delay );
4258 : }
4259 : ELSE
4260 : {
4261 7976 : v_shr( tmp_buffer, sub( q_mem, q_x ), x, delay );
4262 : }
4263 :
4264 54184 : return;
4265 : }
4266 :
4267 24118300 : void v_add_fx(
4268 : const Word32 x1[], /* i : Input vector 1 */
4269 : const Word32 x2[], /* i : Input vector 2 */
4270 : Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */
4271 : const Word16 N /* i : Vector length */
4272 : )
4273 : {
4274 : Word16 i;
4275 :
4276 2800023470 : FOR( i = 0; i < N; i++ )
4277 : {
4278 2775905170 : y[i] = L_add_sat( x1[i], x2[i] );
4279 2775905170 : move32();
4280 : }
4281 :
4282 24118300 : return;
4283 : }
4284 915 : Word16 floor_log_2( Word32 num )
4285 : {
4286 :
4287 915 : IF( num == 0 )
4288 : {
4289 0 : return 0;
4290 : }
4291 :
4292 915 : return ( sub( 30, norm_l( num ) ) );
4293 : }
4294 :
4295 3577750 : void v_shr(
4296 : const Word32 x[], /* i : Input vector */
4297 : const Word16 shift, /* i : Constant */
4298 : Word32 y[], /* o : Output vector that contains x >> shift */
4299 : const Word16 N /* i : Vector length */
4300 : )
4301 : {
4302 : Word16 i;
4303 :
4304 636115997 : FOR( i = 0; i < N; i++ )
4305 : {
4306 632538247 : y[i] = L_shr( x[i], shift );
4307 632538247 : move32();
4308 : }
4309 :
4310 3577750 : return;
4311 : }
4312 :
4313 0 : void v_shr_16(
4314 : const Word16 x[], /* i : Input vector */
4315 : const Word16 shift, /* i : Constant */
4316 : Word16 y[], /* o : Output vector that contains x >> shift */
4317 : const Word16 N /* i : Vector length */
4318 : )
4319 : {
4320 : Word16 i;
4321 :
4322 0 : FOR( i = 0; i < N; i++ )
4323 : {
4324 0 : y[i] = shr( x[i], shift );
4325 0 : move16();
4326 : }
4327 :
4328 0 : return;
4329 : }
4330 :
4331 : /*---------------------------------------------------------------------*
4332 : * lin_interp_fx()
4333 : *
4334 : * Linearly maps x from source range <x1, x2> to the target range <y1, y2>
4335 : *---------------------------------------------------------------------*/
4336 :
4337 : /*! r: mapped output value */
4338 728 : Word16 lin_interp_fx(
4339 : const Word16 x, /* i : Q15 the value to be mapped */
4340 : const Word16 x1, /* i : Q15 source range interval: low end */
4341 : const Word16 y1, /* i : Q15 source range interval: high end */
4342 : const Word16 x2, /* i : Q15 target range interval: low */
4343 : const Word16 y2, /* i : Q15 target range interval: high */
4344 : const Word16 flag_sat /* i : flag to indicate whether to apply saturation */
4345 : )
4346 : {
4347 728 : IF( sub( x2, x1 ) == 0 )
4348 : {
4349 0 : return y1;
4350 : }
4351 728 : ELSE IF( flag_sat )
4352 : {
4353 728 : IF( GE_16( x, s_max( x1, x2 ) ) )
4354 : {
4355 0 : IF( GT_16( x1, x2 ) )
4356 : {
4357 0 : return y1;
4358 : }
4359 : ELSE
4360 : {
4361 0 : return y2;
4362 : }
4363 : }
4364 728 : ELSE IF( LE_16( x, s_min( x1, x2 ) ) )
4365 : {
4366 16 : IF( LT_16( x1, x2 ) )
4367 : {
4368 16 : return y1;
4369 : }
4370 : ELSE
4371 : {
4372 0 : return y2;
4373 : }
4374 : }
4375 : }
4376 :
4377 712 : return add_sat( y1, mult( sub( x, x1 ), div_s( sub( y2, y1 ), sub( x2, x1 ) ) ) );
4378 : }
4379 :
4380 :
4381 0 : Word16 lin_interp_ivas_fx(
4382 : const Word16 x, /* i : Q15 the value to be mapped */
4383 : const Word16 x1, /* i : Q15 source range interval: low end */
4384 : const Word16 y1, /* i : Q15 source range interval: high end */
4385 : const Word16 x2, /* i : Q15 target range interval: low */
4386 : const Word16 y2, /* i : Q15 target range interval: high */
4387 : const Word16 flag_sat /* i : flag to indicate whether to apply saturation */
4388 : )
4389 : {
4390 0 : IF( EQ_16( sub( x2, x1 ), 0 ) )
4391 : {
4392 0 : return y1;
4393 : }
4394 0 : ELSE IF( flag_sat )
4395 : {
4396 0 : IF( GE_16( x, s_max( x1, x2 ) ) )
4397 : {
4398 0 : return GT_16( x1, x2 ) ? y1 : y2;
4399 : }
4400 0 : ELSE IF( LE_16( x, s_min( x1, x2 ) ) )
4401 : {
4402 0 : return LT_16( x1, x2 ) ? y1 : y2;
4403 : }
4404 : }
4405 : Word16 div_res_e;
4406 0 : Word16 div_res = BASOP_Util_Divide1616_Scale( sub( y2, y1 ), sub( x2, x1 ), &div_res_e );
4407 : // div_res = shl( div_res, div_res_e );
4408 0 : return add_sat( y1, round_fx( L_shl( L_mult( sub( x, x1 ), div_res ), div_res_e ) ) );
4409 : }
4410 :
4411 : /*---------------------------------------------------------------------
4412 : * sign_l()
4413 : *
4414 : *---------------------------------------------------------------------*/
4415 :
4416 : /*! r: sign of x (+1/-1) */
4417 56280 : Word32 sign_l(
4418 : const Word32 x /* i : input value of x */
4419 : )
4420 : {
4421 56280 : IF( x < 0 )
4422 : {
4423 26038 : return MIN_32;
4424 : }
4425 : ELSE
4426 : {
4427 30242 : return MAX_32;
4428 : }
4429 : }
4430 :
4431 143 : void v_mult16_fixed(
4432 : const Word16 x1[], /* i : Input vector 1 */
4433 : const Word16 x2[], /* i : Input vector 2 */
4434 : Word16 y[], /* o : Output vector that contains vector 1 .* vector 2 */
4435 : const Word16 N /* i : Vector length */
4436 : )
4437 : {
4438 : Word16 i;
4439 :
4440 10413 : FOR( i = 0; i < N; i++ )
4441 : {
4442 10270 : y[i] = mult_r( x1[i], x2[i] );
4443 10270 : move16();
4444 : }
4445 :
4446 143 : return;
4447 : }
4448 :
4449 : /*---------------------------------------------------------------------*
4450 : * set_zero_fx()
4451 : *
4452 : * Set a vector vec[] of dimension lvec to zero
4453 : *---------------------------------------------------------------------*/
4454 :
4455 142561364 : void set_zero_fx(
4456 : Word32 *vec, /* o : input vector */
4457 : const Word16 lvec /* i : length of the vector */
4458 : )
4459 : {
4460 : Word16 i;
4461 :
4462 17361839134 : FOR( i = 0; i < lvec; i++ )
4463 : {
4464 17219277770 : *vec++ = 0;
4465 17219277770 : move32();
4466 : }
4467 :
4468 142561364 : return;
4469 : }
4470 9059 : void set_zero2_fx(
4471 : Word32 *vec, /* o : input vector */
4472 : const Word32 lvec /* i : length of the vector */
4473 : )
4474 : {
4475 : Word32 i;
4476 :
4477 34153899 : FOR( i = 0; i < lvec; i++ )
4478 : {
4479 34144840 : *vec++ = 0;
4480 34144840 : move32();
4481 : }
4482 :
4483 9059 : return;
4484 : }
4485 :
4486 6193 : void set16_zero_fx(
4487 : Word16 *vec, /* o : input vector */
4488 : const Word16 lvec /* i : length of the vector */
4489 : )
4490 : {
4491 : Word16 i;
4492 :
4493 676153 : FOR( i = 0; i < lvec; i++ )
4494 : {
4495 669960 : *vec++ = 0;
4496 669960 : move16();
4497 : }
4498 :
4499 6193 : return;
4500 : }
4501 :
4502 1532725 : UWord32 mvl2s_r(
4503 : const Word32 x[], /* i : input vector */
4504 : const Word16 q_x,
4505 : Word16 y[], /* o : output vector */
4506 : const Word16 n /* i : vector size */
4507 : )
4508 : {
4509 : Word16 i;
4510 : Word32 temp;
4511 1532725 : UWord32 noClipping = 0;
4512 1532725 : move32();
4513 :
4514 1532725 : IF( n <= 0 )
4515 : {
4516 : /* cannot transfer vectors with size 0 */
4517 174 : return 0;
4518 : }
4519 :
4520 1532551 : IF( (void *) y <= (const void *) x )
4521 : {
4522 0 : Word32 tempd = L_shl( 1, sub( q_x, 1 ) );
4523 0 : FOR( i = 0; i < n; i++ )
4524 : {
4525 0 : temp = L_add( x[i], tempd );
4526 0 : temp = L_shr( temp, q_x );
4527 :
4528 0 : IF( GT_32( temp, MAX16B ) )
4529 : {
4530 0 : temp = MAX16B;
4531 0 : move32();
4532 0 : noClipping = L_add( (Word32) noClipping, 1 );
4533 : }
4534 0 : ELSE IF( LT_32( temp, MIN16B ) )
4535 : {
4536 0 : temp = MIN16B;
4537 0 : move32();
4538 0 : noClipping = L_add( (Word32) noClipping, 1 );
4539 : }
4540 :
4541 0 : y[i] = extract_l( temp );
4542 0 : move16();
4543 : }
4544 : }
4545 : ELSE
4546 : {
4547 1532551 : Word32 tempd = L_shl( 1, sub( q_x, 1 ) );
4548 1227499631 : FOR( i = n - 1; i >= 0; i-- )
4549 : {
4550 1225967080 : temp = L_add( x[i], tempd );
4551 1225967080 : temp = L_shr( temp, q_x );
4552 :
4553 1225967080 : IF( GT_32( temp, MAX16B ) )
4554 : {
4555 270 : temp = MAX16B;
4556 270 : move32();
4557 270 : noClipping = L_add( (Word32) noClipping, 1 );
4558 : }
4559 1225966810 : ELSE IF( LT_32( temp, MIN16B ) )
4560 : {
4561 344 : temp = MIN16B;
4562 344 : move32();
4563 344 : noClipping = L_add( (Word32) noClipping, 1 );
4564 : }
4565 :
4566 1225967080 : y[i] = extract_l( temp );
4567 1225967080 : move16();
4568 : }
4569 : }
4570 :
4571 1532551 : return noClipping;
4572 : }
4573 :
4574 0 : Word32 dotp_me_fx(
4575 : const Word32 x[], /* i : vector x[] */
4576 : const Word32 y[], /* i : vector y[] */
4577 : const Word16 n, /* i : vector length */
4578 : Word16 exp_x,
4579 : Word16 exp_y,
4580 : Word16 *exp_suma )
4581 : {
4582 : Word16 i;
4583 : Word32 suma;
4584 : Word32 mul;
4585 0 : Word16 mul_exp = add( exp_x, exp_y );
4586 0 : suma = Mpy_32_32( x[0], y[0] );
4587 0 : *exp_suma = mul_exp;
4588 0 : FOR( i = 1; i < n; i++ )
4589 : {
4590 0 : mul = Mpy_32_32( x[i], y[i] );
4591 0 : suma = BASOP_Util_Add_Mant32Exp( suma, *exp_suma, mul, mul_exp, exp_suma ); // exp_x+exp_A
4592 : }
4593 :
4594 0 : return suma;
4595 : }
4596 :
4597 0 : Word32 dotp_fixed_guarded(
4598 : const Word32 x[], /* i : vector x[] */
4599 : const Word32 y[], /* i : vector y[] */
4600 : const Word16 n /* i : vector length */
4601 : )
4602 : {
4603 : Word16 i;
4604 : Word32 suma;
4605 0 : Word16 guarded_bits = find_guarded_bits_fx( n );
4606 0 : suma = L_shr( Mpy_32_32( x[0], y[0] ), guarded_bits );
4607 :
4608 0 : FOR( i = 1; i < n; i++ )
4609 : {
4610 0 : suma = L_add( suma, L_shr( Mpy_32_32( x[i], y[i] ), guarded_bits ) );
4611 : }
4612 :
4613 0 : return suma;
4614 : }
4615 :
4616 :
4617 0 : Word32 dotp_fixed_ivas_fx(
4618 : const Word32 x[], /* i : vector x[] */
4619 : Word16 x_e,
4620 : const Word32 y[], /* i : vector y[] */
4621 : Word16 y_e,
4622 : const Word16 n, /* i : vector length */
4623 : Word16 *out_e )
4624 : {
4625 : Word16 i, exp;
4626 0 : Word32 suma = 0;
4627 :
4628 0 : exp = 31;
4629 0 : move16();
4630 :
4631 0 : FOR( i = 0; i < n; i++ )
4632 : {
4633 0 : suma = BASOP_Util_Add_Mant32Exp( suma, exp, Mpy_32_32( x[i], y[i] ), x_e + y_e, &exp );
4634 : }
4635 :
4636 0 : *out_e = exp;
4637 0 : move16();
4638 0 : return suma;
4639 : }
4640 :
4641 : /*-------------------------------------------------------------------*
4642 : * v_mult()
4643 : *
4644 : * Multiplication of two vectors
4645 : *-------------------------------------------------------------------*/
4646 :
4647 :
4648 14162715 : void v_mult_fixed(
4649 : const Word32 x1[], /* i : Input vector 1 */
4650 : const Word32 x2[], /* i : Input vector 2 */
4651 : Word32 y[], /* o : Output vector that contains vector 1 .* vector 2 */
4652 : const Word16 N /* i : Vector length */
4653 : )
4654 : {
4655 : Word16 i;
4656 :
4657 554894968 : FOR( i = 0; i < N; i++ )
4658 : {
4659 540732253 : y[i] = Mpy_32_32( x1[i], x2[i] );
4660 540732253 : move32();
4661 : }
4662 :
4663 14162715 : return;
4664 : }
4665 :
4666 : /*-------------------------------------------------------------------*
4667 : * anint_fixed()
4668 : *
4669 : * Round to the nearest integer.
4670 : *-------------------------------------------------------------------*/
4671 9400 : Word32 anint_fixed( Word32 x, Word16 exp )
4672 : {
4673 9400 : IF( x == 0 )
4674 : {
4675 856 : return 0;
4676 : }
4677 8544 : IF( x >= 0 )
4678 : {
4679 8544 : return L_add( x, L_shl( 1, sub( exp, 1 ) ) );
4680 : }
4681 : ELSE
4682 : {
4683 0 : return L_sub( x, L_shl( 1, sub( exp, 1 ) ) );
4684 : }
4685 : }
4686 :
4687 : /*-------------------------------------------------------------------*
4688 : * ceil_fixed()
4689 : *
4690 : * Ceil to the next multiple of (1 << exp).
4691 : *-------------------------------------------------------------------*/
4692 25503 : Word32 ceil_fixed( Word32 x, Word16 exp )
4693 : {
4694 : Word32 step;
4695 : // step = x / L_shl( 1, exp );
4696 25503 : step = L_shr( x, exp );
4697 25503 : IF( ( x % L_shl( 1, exp ) ) > 0 )
4698 : {
4699 15376 : step = L_add( step, 1 );
4700 : }
4701 25503 : return L_shl( step, exp );
4702 : }
4703 :
4704 783 : void sort_l(
4705 : Word32 *x, /* i/o: Vector to be sorted */
4706 : Word16 len /* i/o: vector length */
4707 : )
4708 : {
4709 : Word16 i, j;
4710 : Word32 tempr;
4711 :
4712 7133 : FOR( i = len - 2; i >= 0; i-- )
4713 : {
4714 6350 : tempr = x[i];
4715 6350 : move32();
4716 23195 : FOR( j = i + 1; ( j < len ) && ( tempr > x[j] ); j++ )
4717 : {
4718 16845 : x[j - 1] = x[j];
4719 16845 : move32();
4720 : }
4721 6350 : x[j - 1] = tempr;
4722 6350 : move32();
4723 : }
4724 :
4725 783 : return;
4726 : }
4727 :
4728 : /*-------------------------------------------------------------------*
4729 : * v_add_fixed()
4730 : *
4731 : * Subtraction of two vectors sample by sample
4732 : *-------------------------------------------------------------------*/
4733 :
4734 4623239 : void v_add_fixed(
4735 : const Word32 x1[], /* i : Input vector 1 */
4736 : const Word32 x2[], /* i : Input vector 2 */
4737 : Word32 y[], /* o : Output vector that contains vector 1 - vector 2 */
4738 : const Word16 N, /* i : Vector length */
4739 : const Word16 hdrm /* i : headroom for when subtraction result > 1 or < -1 */
4740 : )
4741 : {
4742 : Word16 i;
4743 :
4744 146524009 : FOR( i = 0; i < N; i++ )
4745 : {
4746 141900770 : y[i] = L_add( L_shr( x1[i], hdrm ), L_shr( x2[i], hdrm ) );
4747 141900770 : move32();
4748 : }
4749 :
4750 4623239 : return;
4751 : }
4752 :
4753 471874554 : void v_add_fixed_no_hdrm(
4754 : const Word32 x1[], /* i : Input vector 1 */
4755 : const Word32 x2[], /* i : Input vector 2 */
4756 : Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */
4757 : const Word16 N /* i : Vector length */
4758 : )
4759 : {
4760 : Word16 i;
4761 :
4762 2587716980 : FOR( i = 0; i < N; i++ )
4763 : {
4764 2115842426 : y[i] = L_add( x1[i], x2[i] );
4765 2115842426 : move32();
4766 : }
4767 :
4768 471874554 : return;
4769 : }
4770 :
4771 8862603 : void v_add_fixed_me(
4772 : const Word32 x1[], /* i : Input vector 1 */
4773 : const Word16 x1_e, /* i : Exponent for input vector 1 */
4774 : const Word32 x2[], /* i : Input vector 2 */
4775 : const Word16 x2_e, /* i : Exponent for input vector 2 */
4776 : Word32 y[], /* o : Output vector that contains vector 1 - vector 2 */
4777 : Word16 *y_e, /* i : Exponent for output vector */
4778 : const Word16 N, /* i : Vector length */
4779 : const Word16 hdrm /* i : headroom for when subtraction result > 1 or < -1 */
4780 : )
4781 : {
4782 : Word16 i;
4783 8862603 : Word16 x1_shift = sub( s_max( x1_e, x2_e ), x1_e );
4784 8862603 : Word16 x2_shift = sub( s_max( x1_e, x2_e ), x2_e );
4785 :
4786 138828619 : FOR( i = 0; i < N; i++ )
4787 : {
4788 129966016 : y[i] = L_add( L_shr( x1[i], hdrm + x1_shift ), L_shr( x2[i], hdrm + x2_shift ) );
4789 129966016 : move32();
4790 : }
4791 :
4792 8862603 : *y_e = add( s_max( x1_e, x2_e ), hdrm );
4793 8862603 : move16();
4794 :
4795 8862603 : return;
4796 : }
4797 :
4798 39522955 : Word16 find_guarded_bits_fx( Word32 n )
4799 : {
4800 : // return n <= 1 ? 0 : n <= 2 ? 1
4801 : // : n <= 4 ? 2
4802 : // : n <= 8 ? 3
4803 : // : n <= 16 ? 4
4804 : // : n <= 32 ? 5
4805 : // : n <= 64 ? 6
4806 : // : n <= 128 ? 7
4807 : // : n <= 256 ? 8
4808 : // : n <= 512 ? 9
4809 : // : n <= 1024 ? 10
4810 : // : n <= 2048 ? 11
4811 : // : n <= 4096 ? 12
4812 : // : n <= 8192 ? 13
4813 : // : n <= 16384 ? 14
4814 : // : 15;
4815 : /*Word16 val = 0;
4816 : move32();
4817 : test();
4818 : WHILE( GT_32( n, L_shl( 1, val ) ) && LT_32( val, 16 ) )
4819 : {
4820 : val = add( val, 1 );
4821 : }*/
4822 39522955 : IF( LE_32( n, 1 ) )
4823 : {
4824 219910 : return 0;
4825 : }
4826 : ELSE
4827 : {
4828 :
4829 39303045 : return sub( 31, norm_l( L_sub( n, 1 ) ) );
4830 : }
4831 : }
4832 :
4833 577507370 : Word16 L_norm_arr( const Word32 *arr, Word16 size )
4834 : {
4835 577507370 : Word16 q = 31;
4836 577507370 : move16();
4837 9503461315 : FOR( Word16 i = 0; i < size; i++ )
4838 : {
4839 : Word16 q_tst;
4840 :
4841 8925953945 : q_tst = norm_l( arr[i] );
4842 8925953945 : if ( arr[i] != 0 )
4843 : {
4844 6128934228 : q = s_min( q, q_tst );
4845 : }
4846 : }
4847 :
4848 577507370 : return q;
4849 : }
4850 :
4851 8412303 : Word16 norm_arr( Word16 *arr, Word16 size )
4852 : {
4853 8412303 : Word16 q = 15;
4854 8412303 : Word16 exp = 0;
4855 8412303 : move16();
4856 8412303 : move16();
4857 3702108983 : FOR( Word16 i = 0; i < size; i++ )
4858 : {
4859 3693696680 : if ( arr[i] != 0 )
4860 : {
4861 2564459191 : exp = norm_s( arr[i] );
4862 : }
4863 3693696680 : if ( arr[i] != 0 )
4864 : {
4865 2564459191 : q = s_min( q, exp );
4866 : }
4867 : }
4868 8412303 : return q;
4869 : }
4870 :
4871 635836 : Word16 W_norm_arr( Word64 *arr, Word16 size )
4872 : {
4873 635836 : Word16 q = 63;
4874 635836 : Word16 exp = 0;
4875 635836 : move16();
4876 635836 : move16();
4877 343264828 : FOR( Word16 i = 0; i < size; i++ )
4878 : {
4879 342628992 : if ( arr[i] != 0 )
4880 : {
4881 315946415 : exp = W_norm( arr[i] );
4882 : }
4883 342628992 : if ( arr[i] != 0 )
4884 : {
4885 315946415 : q = s_min( q, exp );
4886 : }
4887 : }
4888 635836 : return q;
4889 : }
4890 :
4891 271967070 : Word16 get_min_scalefactor( Word32 x, Word32 y )
4892 : {
4893 : Word16 scf_y;
4894 271967070 : Word16 scf = Q31;
4895 271967070 : move16();
4896 :
4897 271967070 : test();
4898 271967070 : if ( x == 0 && y == 0 )
4899 : {
4900 20102724 : scf = 0;
4901 20102724 : move16();
4902 : }
4903 :
4904 271967070 : if ( x != 0 )
4905 : {
4906 251808878 : scf = norm_l( x );
4907 : }
4908 :
4909 271967070 : scf_y = norm_l( y );
4910 271967070 : if ( y != 0 )
4911 : {
4912 194160583 : scf = s_min( scf_y, scf );
4913 : }
4914 :
4915 271967070 : return scf;
4916 : }
4917 :
4918 :
4919 358716951 : Flag is_zero_arr( Word32 *arr, Word16 size )
4920 : {
4921 649752955 : FOR( Word16 i = 0; i < size; i++ )
4922 586664243 : IF( arr[i] != 0 )
4923 : {
4924 295628239 : return 0;
4925 : }
4926 :
4927 63088712 : return 1;
4928 : }
4929 :
4930 767111 : Flag is_zero_arr16( Word16 *arr, Word16 size )
4931 : {
4932 224751917 : FOR( Word16 i = 0; i < size; i++ )
4933 224594167 : IF( arr[i] != 0 )
4934 : {
4935 609361 : return 0;
4936 : }
4937 :
4938 157750 : return 1;
4939 : }
4940 :
4941 0 : Flag is_zero_arr64( Word64 *arr, Word16 size )
4942 : {
4943 0 : FOR( Word16 i = 0; i < size; i++ )
4944 : {
4945 0 : IF( arr[i] != 0 )
4946 : {
4947 0 : return 0;
4948 : }
4949 : }
4950 0 : return 1;
4951 : }
4952 :
4953 0 : void Scale_sig64(
4954 : Word64 x[], /* i/o: signal to scale Qx */
4955 : Word16 len, /* i : size of x[] Q0 */
4956 : Word16 exp /* i : exponent: x = round(x << exp) Qx exp */
4957 : )
4958 : {
4959 : Word16 i;
4960 0 : assert( exp <= 63 && exp >= -63 );
4961 0 : IF( exp == 0 )
4962 : {
4963 0 : return;
4964 : }
4965 :
4966 0 : FOR( i = 0; i < len; i++ )
4967 : {
4968 : /* saturation can occur here */
4969 0 : x[i] = W_shl( x[i], exp );
4970 0 : move64();
4971 : }
4972 : }
|