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