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 : EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
35 : ====================================================================================*/
36 :
37 : #include <assert.h>
38 : #include <stdint.h>
39 : #include "options.h"
40 : #ifdef DEBUGGING
41 : #include "debug.h"
42 : #endif
43 : #include <math.h>
44 : #include "cnst.h"
45 : #include "rom_com.h"
46 : #include "prot.h"
47 : #include "wmc_auto.h"
48 :
49 : /*-------------------------------------------------------------------*
50 : * LOCAL DEFINITIONS
51 : *-------------------------------------------------------------------*/
52 :
53 : #define N_OPT 5 /* complexity setting, direct functional calculation limit */
54 : #define TABLE_LIM_OPT 96 /* odd divisor table recursion limit setting, due to dim 6 */
55 :
56 : /* local typedefs for optimized pvq indexing, used only in this c-file to vectorize common function calls for c-code clarity */
57 : typedef void ( *VEC2INDFUNCM )( const int16_t *, int16_t *, uint32_t *, uint32_t * );
58 : typedef uint32_t ( *NFUNCM )( int16_t );
59 : typedef uint32_t ( *H_FUNCM )( uint32_t );
60 : typedef void ( *IND2VECFUNCM )( int16_t, int16_t, uint32_t, int16_t * );
61 : typedef void ( *NDIM_FUNCM )( int16_t, int16_t, uint32_t, int16_t * );
62 :
63 : /* local constants for indexing functions c-code clarity */
64 : #ifndef ONE_U
65 :
66 : #define ZERO 0
67 : #define ONE 1
68 : #define ONE_U 1u
69 : #define TWO 2
70 : #define SIGNBIT 0x80000000u
71 :
72 : #define MAXBIT 0x40000000L /* if Word32 */
73 : #define MINNEG 0xffffffffL
74 :
75 : #define UDIVBY3 2863311531U
76 :
77 :
78 : /*-------------------------------------------------------------------*
79 : * local_norm_l_opt
80 : *
81 : * rewritten version of STL norm_l for integer fixed point normalization
82 : * in floating point c-code.
83 : *-------------------------------------------------------------------*/
84 :
85 : /*! r: shifts needed for normalization */
86 2834943 : static int16_t local_norm_l_opt(
87 : int32_t l32var /* i/o: signed 32-bit input value */
88 : )
89 : {
90 : int16_t l32res;
91 :
92 : #define WMC_TOOL_SKIP
93 :
94 2834943 : if ( l32var == (int32_t) MINNEG )
95 : {
96 0 : return ( 32 - ONE );
97 : }
98 : else
99 : {
100 2834943 : if ( l32var == ZERO )
101 : {
102 0 : return ZERO;
103 : }
104 : else
105 : {
106 2834943 : if ( l32var < ZERO )
107 : {
108 0 : l32var = ~l32var;
109 : }
110 :
111 83415966 : for ( l32res = ZERO; l32var < (int32_t) MAXBIT; l32res++ )
112 : {
113 80581023 : l32var <<= ONE;
114 : }
115 : }
116 : }
117 : #undef WMC_TOOL_SKIP
118 :
119 2834943 : return ( l32res );
120 : }
121 :
122 :
123 : /*-------------------------------------------------------------------*
124 : * floor_sqrt_exact()
125 : * returns x = floor(sqrt(input)); where (x*x) <= input
126 : *-------------------------------------------------------------------*/
127 :
128 : /*! r: floor(sqrt(input)) */
129 126675 : uint32_t floor_sqrt_exact(
130 : const uint32_t input /* i : unsigned input [0.. UINT_MAX/4] */
131 : )
132 : {
133 : double _tmp;
134 : uint32_t x;
135 126675 : if ( input == ZERO )
136 : {
137 0 : return ZERO;
138 : }
139 :
140 126675 : _tmp = (double) input;
141 126675 : x = (uint32_t) ( sqrt( _tmp ) ); /* floor is a part of the cast */
142 :
143 126675 : return x;
144 : }
145 :
146 : /*-------------------------------------------------------------------*
147 : * f_odd_exact_div_opt()
148 : *
149 : * find 1/(den1*2+1) * ( num1p*num2p - num3) ,
150 : * if the result is known a priori to be exactly a 32bit unsigned integer
151 : *-------------------------------------------------------------------*/
152 :
153 : /*! r: see Eq. */
154 2560857 : static uint32_t f_odd_exact_div_opt(
155 : const int16_t num1p, /* i : see Eq. */
156 : const uint32_t num2p, /* i : see Eq. */
157 : const uint32_t num3, /* i : see Eq. */
158 : const int16_t den1 /* i : see Eq. */
159 : )
160 : {
161 : uint32_t tmp;
162 2560857 : tmp = exactdivodd[den1] * ( num1p * num2p - num3 );
163 :
164 2560857 : return ( tmp );
165 : }
166 :
167 : /*---------------------------------------------------------------------------*
168 : * f_even_exact_div_opt()
169 : *
170 : * returns (num1p*num2p - num3 )/ den1
171 : * if the result is known a priori to be exactly a 32bit unsigned integer
172 : *--------------------------------------------------------------------------*/
173 :
174 : /*! r: see Eq. */
175 2834943 : static uint32_t f_even_exact_div_opt(
176 : const int16_t num1p, /* i : see Eq. */
177 : const uint32_t num2p, /* i : see Eq. range should be larger than num1p */
178 : const uint32_t num3, /* i : see Eq. */
179 : const int16_t den1 /* i : see Eq. */
180 : )
181 : {
182 : uint32_t tmp1, oddfactor, UL_tmp;
183 : int16_t den1_m1;
184 : int16_t even_sh;
185 : uint32_t UL_tmp_h;
186 : uint64_t ULL_tmp;
187 :
188 2834943 : den1_m1 = den1 - ONE; /* remove top bit */
189 2834943 : even_sh = ( 31 ) - local_norm_l_opt( ( den1_m1 ) ^ den1 ); /* NB STL operation defined for signed positive 32 bit variable */
190 2834943 : oddfactor = exactdivodd[den1_m1 >> even_sh];
191 2834943 : even_sh -= ONE;
192 :
193 2834943 : ULL_tmp = (uint64_t) num1p * (uint64_t) num2p; /* use STL Mpy_32_32_uu functionality */
194 2834943 : UL_tmp_h = (uint32_t) ( ULL_tmp >> 32 ); /* high output from basicop */
195 2834943 : UL_tmp = (uint32_t) ( ULL_tmp ); /* low output from basicop */
196 :
197 2834943 : if ( num3 > UL_tmp )
198 : {
199 348 : UL_tmp_h = UL_tmp_h - ONE_U;
200 : }
201 2834943 : UL_tmp = ( UL_tmp - num3 ); /* can and should underflow */
202 2834943 : UL_tmp = ( UL_tmp_h << ( 32 - even_sh ) ) | ( UL_tmp >> even_sh ); /* bitwise OR */
203 :
204 : /* use tabled modular multiplicative inverse for the odd part division */
205 2834943 : tmp1 = UL_tmp * oddfactor;
206 :
207 2834943 : return tmp1;
208 : }
209 :
210 : /*-------------------------------------------------------------------*
211 : * a_three()
212 : *-------------------------------------------------------------------*/
213 :
214 : /*! r: offset for dim 3 */
215 43122 : static uint32_t a_three(
216 : const uint32_t k_val /* i : nb unit pulses; k_val may be higher than 16 bit signed */
217 : )
218 : {
219 43122 : if ( k_val )
220 : {
221 42897 : return ( ONE_U + k_val * ( ( k_val - ONE_U ) << ONE ) );
222 : }
223 : else
224 : {
225 225 : return ZERO;
226 : }
227 : }
228 :
229 : /*-------------------------------------------------------------------*
230 : * a_four()
231 : *-------------------------------------------------------------------*/
232 :
233 : /*! r: offset for dim 4 */
234 208408 : static uint32_t a_four(
235 : const uint32_t k_val /* i : nb unit pulses */
236 : )
237 : {
238 208408 : if ( k_val )
239 : {
240 207974 : return UDIVBY3 * ( ( k_val << ONE ) * ( 4 + ( ( k_val << ONE ) - 3 ) * k_val ) - 3 );
241 : }
242 :
243 434 : return ZERO;
244 : }
245 :
246 : /*-------------------------------------------------------------------*
247 : * a_five()
248 : *-------------------------------------------------------------------*/
249 :
250 : /*! r: offset for dim 5 */
251 6104 : static uint32_t a_five(
252 : const uint32_t k_val /* i : nb unit pulses */
253 : )
254 : {
255 : uint32_t offset;
256 :
257 6104 : if ( k_val == 0 )
258 : {
259 46 : offset = 0;
260 : }
261 6058 : else if ( k_val == 1 )
262 : {
263 100 : offset = 1;
264 : }
265 : else
266 : {
267 5958 : offset = ( ONE_U + ( ( ( ( ( ( k_val - TWO ) * k_val + 5 ) * k_val - 4 ) * k_val ) * ( UDIVBY3 ) ) << ONE ) );
268 : }
269 6104 : return offset;
270 : }
271 :
272 : /*-------------------------------------------------------------------*
273 : * direct_msize()
274 : *-------------------------------------------------------------------*/
275 : /*! r: Enumeration size */
276 44366 : static uint32_t direct_msize(
277 : const int16_t dim_in, /* i : Number of dimensions */
278 : const int16_t k_in ) /* i : Number of pulses */
279 : {
280 : uint32_t msize, k, ksq;
281 :
282 44366 : msize = ONE_U; /* k==0 or dim==1, and base */
283 44366 : if ( k_in )
284 : {
285 44366 : k = (uint32_t) k_in;
286 44366 : ksq = k * k;
287 44366 : switch ( dim_in )
288 : {
289 1412 : case ( 5 ):
290 : /* k*k = 238*238 < 2^16 */
291 1412 : msize += ( ( ( ksq * ( 5 + ksq ) ) * UDIVBY3 ) << ONE );
292 1412 : break;
293 42350 : case ( 4 ):
294 42350 : msize = ( ( k * ( ksq + 2 ) ) * UDIVBY3 ) << TWO;
295 42350 : break;
296 32 : case ( 3 ):
297 32 : msize += ( ( ksq ) << ONE );
298 32 : break;
299 404 : case ( 2 ):
300 404 : msize = k << ONE;
301 404 : break;
302 : }
303 0 : }
304 :
305 44366 : return msize;
306 : }
307 :
308 :
309 : /*-------------------------------------------------------------------*
310 : * initOffsets()
311 : *
312 : * update h_mem[0.. k_val_in+1] , with starting offsets for A+U recursion
313 : *-------------------------------------------------------------------*/
314 :
315 288596 : static void initOffsets(
316 : const int16_t dim_in, /* i : Number of dimensions */
317 : uint32_t *h_mem, /* o : offsets */
318 : const int16_t k_val_in /* i : Number of pulses */
319 : )
320 : {
321 : int16_t k_val_curr, k_val_prev;
322 : int16_t k_val;
323 288596 : h_mem[0] = ZERO; /* % A(=>0,k=0) */
324 288596 : h_mem[1] = ONE_U; /* % A(*,k=1) */
325 :
326 288596 : if ( dim_in == 2 )
327 : {
328 0 : for ( k_val = TWO; k_val <= k_val_in; k_val++ )
329 : {
330 0 : h_mem[k_val] = (uint32_t) ( ( k_val << ONE ) - ONE ); /* A(2, 2 .. k ) */
331 : }
332 0 : h_mem[k_val] = (uint32_t) ( k_val_in ); /* U(2,k+1) */
333 : }
334 288596 : else if ( dim_in == 3 )
335 : {
336 288596 : k_val_prev = ONE;
337 2078791 : for ( k_val_curr = TWO; k_val_curr <= k_val_in; k_val_curr++ )
338 : {
339 1790195 : h_mem[k_val_curr] = ( ONE_U + k_val_curr * ( k_val_prev << ONE ) );
340 1790195 : k_val_prev = k_val_curr;
341 : }
342 288596 : h_mem[k_val_curr] = k_val_curr * k_val_prev;
343 : }
344 0 : else if ( dim_in == 4 )
345 : {
346 0 : for ( k_val_curr = TWO; k_val_curr <= k_val_in; k_val_curr++ )
347 : {
348 0 : h_mem[k_val_curr] = UDIVBY3 * ( ( k_val_curr << ONE ) * ( 4 + ( ( k_val_curr << ONE ) - 3 ) * k_val_curr ) - 3 );
349 : }
350 0 : h_mem[k_val_curr] = ( UDIVBY3 * ( ( k_val_curr << ONE ) * ( 4 + ( ( k_val_curr << ONE ) - 3 ) * k_val_curr ) - 3 ) ) >> 1;
351 : }
352 :
353 288596 : return;
354 : }
355 :
356 :
357 : /*-------------------------------------------------------------------*
358 : * a_fwd()
359 : *
360 : * create offsets for A(n,k) from lower A(n-1,k)
361 : *-------------------------------------------------------------------*/
362 :
363 2923872 : static void a_fwd(
364 : uint32_t *a_in, /* i/o: offsets */
365 : const int16_t n_items /* i : items, k's */
366 : )
367 : {
368 : uint32_t a_1;
369 : int16_t i, i_prev;
370 : uint32_t a_in0; /* i : start column value */
371 :
372 2923872 : a_in0 = ONE_U;
373 2923872 : i_prev = ZERO;
374 20600972 : for ( i = ONE; i <= n_items; i++ ) /*basic A fwd row recursion */
375 : {
376 17677100 : a_1 = a_in0 + a_in[i_prev] + a_in[i]; /* a_in addressed in at least two locations */
377 17677100 : a_in[i_prev] = a_in0;
378 17677100 : a_in0 = a_1;
379 17677100 : i_prev = i; /* no real need to count as it is a ptr update */
380 : }
381 2923872 : a_in[i_prev] = a_in0;
382 :
383 2923872 : return;
384 : }
385 :
386 : /*-------------------------------------------------------------------*
387 : * a_bwd()
388 : *
389 : * create offsets for A(n,k) from higher A(n+1,k)
390 : *-------------------------------------------------------------------*/
391 :
392 8044077 : static void a_bwd(
393 : uint32_t *a_in, /* i/o: offsets */
394 : const int16_t n_items /* i : n_items */
395 : )
396 : {
397 : uint32_t a_1;
398 : uint32_t a_in0;
399 : int16_t i;
400 : int16_t i_prev;
401 :
402 8044077 : a_in0 = ZERO;
403 8044077 : i_prev = ZERO;
404 48383283 : for ( i = ONE; i <= n_items; i++ ) /*basic A reverse row recursion */
405 : {
406 40339206 : a_1 = a_in[i] - a_in0 - a_in[i_prev];
407 40339206 : a_in[i_prev] = a_in0;
408 40339206 : a_in0 = a_1;
409 40339206 : i_prev = i;
410 : }
411 8044077 : a_in[i_prev] = a_in0;
412 :
413 8044077 : return;
414 : }
415 :
416 : /*-------------------------------------------------------------------*
417 : * direct_row_A2U_rec_calc()
418 : *
419 : *
420 : *-------------------------------------------------------------------*/
421 :
422 852288 : static uint32_t direct_row_A2U_rec_calc(
423 : const int16_t dim_in, /* i : Number of dimensions */
424 : const int16_t k_val_in, /* i : Number of pulses */
425 : const uint32_t a_km2, /* i : Recursion for k-2 (see Eq below) */
426 : const uint32_t a_km1 /* i : Recursion for k-1 (see Eq below) */
427 : )
428 : {
429 :
430 : /* U(n,k) = (A(n,k-2)-1)/2 + ((2*n-1)*A(n,k-1) - A(n,k-2) )/2*(k-1) */
431 : /* U(n,k) = floor(A(n,k-2)/2) + (n*A(n,k-1) - floor(A(n,k-1)/2) - floor(A(n,k-2)/2) +1 )/(k-1) */
432 : /* U(n,k) = floor(A(n,k-2)/2) + (n*A(n,k-1) - (floor(A(n,k-1)/2) + floor(A(n,k-2)/2) +1) ) /(k-1) */
433 :
434 : uint32_t km2_size, result;
435 : int16_t divisor;
436 :
437 852288 : divisor = k_val_in - ONE;
438 852288 : km2_size = ( a_km1 >> ONE ) + ( a_km2 >> ONE ) + ONE_U;
439 :
440 852288 : if ( divisor & ONE )
441 : {
442 : /* odd */
443 473550 : result = ( ( a_km2 >> ONE ) + f_odd_exact_div_opt( dim_in, a_km1, km2_size, divisor >> ONE ) );
444 : }
445 : else
446 : {
447 : /* even divisor */
448 378738 : result = ( ( a_km2 >> ONE ) + f_even_exact_div_opt( dim_in, a_km1, km2_size, divisor ) );
449 : }
450 :
451 852288 : return result;
452 : }
453 :
454 : /*-------------------------------------------------------------------*
455 : * a_u_fwd()
456 : *
457 : *
458 : *-------------------------------------------------------------------*/
459 :
460 2923872 : static void a_u_fwd(
461 : uint32_t *a_u_in, /* o : auxiliary array a_u */
462 : const int16_t k_val_in, /* i : number of pulses */
463 : const int16_t mem_size_m1 /* i : length of a_u_in */
464 : )
465 : {
466 : uint32_t u_kp1_prev;
467 : uint32_t a_k_prev;
468 :
469 : /* mem_size_m1 = 1 + k_val_in */
470 2923872 : u_kp1_prev = a_u_in[mem_size_m1]; /* previous n U (n,k+1) value*/
471 2923872 : a_k_prev = a_u_in[k_val_in]; /* previous n A(n,k) value*/
472 :
473 2923872 : a_fwd( &a_u_in[ONE], k_val_in ); /* a_u_in[k==ZERO] = zero if n>0 */
474 :
475 : /* low dynamic last offset entry mixed recursion */
476 : /* used for size calculation */
477 : /* U(n,k+1) = 1 + U(n-1,k+1) + U(n-1,k) + U(n,k) */
478 : /* U(n,k+1) = 1 + U(n-1,k+1) + (A(n-1,k)-1)/2 + (A(n,k)-1)/2 */
479 : /* Note, A(n,k) always odd for k>0, subtracted one always shifted out */
480 : /* assert(a_k_prev>0, a_k-curr>0) */
481 :
482 2923872 : a_u_in[mem_size_m1] = ONE_U + u_kp1_prev + ( a_k_prev >> ONE ) + ( a_u_in[k_val_in] >> ONE );
483 :
484 2923872 : return;
485 : }
486 :
487 : /*-------------------------------------------------------------------*
488 : * nm_h_prep_opt()
489 : *
490 : * find and return N_MPVQ(n,k) and also offsets A(n, 0 to k ) and U(n,k+1).
491 : *-------------------------------------------------------------------*/
492 :
493 : /*! r: msize for dim */
494 852288 : static uint32_t nm_h_prep_opt(
495 : const int16_t dim_in, /* i : dimension */
496 : int16_t k_val_in, /* i : nb unit pulses */
497 : uint32_t *h /* o : A/U offsets array */
498 : )
499 : {
500 : int16_t mem_size_m1, k_val;
501 : int16_t dim_tmp, d_start;
502 : uint32_t h_saveA, h_saveB; /* registers for alternating A(n,k-1), A(n,k-2)*/
503 : int16_t numDsub1; /* k_val_curr, k_val_prev*/
504 :
505 852288 : mem_size_m1 = k_val_in + ONE;
506 :
507 852288 : if ( k_val_in > TABLE_LIM_OPT )
508 : {
509 0 : if ( dim_in >= 3 )
510 : {
511 0 : d_start = 3;
512 : }
513 : else
514 : {
515 0 : d_start = 2;
516 : }
517 0 : initOffsets( d_start, h, k_val_in );
518 :
519 0 : for ( dim_tmp = d_start; dim_tmp < dim_in; dim_tmp++ )
520 : {
521 0 : a_u_fwd( h, k_val_in, mem_size_m1 );
522 : }
523 : }
524 : else
525 : {
526 852288 : h[ZERO] = ZERO;
527 852288 : h[ONE] = ONE_U;
528 852288 : numDsub1 = ( ( dim_in << ONE ) - ONE );
529 852288 : h[TWO] = numDsub1;
530 :
531 : /* interleaved odd even calls */
532 852288 : h_saveA = numDsub1;
533 852288 : h_saveB = ONE_U;
534 2939595 : for ( k_val = 3; k_val < ( mem_size_m1 ); k_val++ )
535 : {
536 : /* A(n,k) = A(n,k-2) + ((2*n-1)*A(n,k-1)-A(n,k-2)) /(k-1) */
537 : /* first odd k, even divisor */
538 2456205 : h_saveB += f_even_exact_div_opt( numDsub1, h_saveA, h_saveB, k_val - ONE );
539 2456205 : h[k_val] = h_saveB;
540 :
541 2456205 : k_val++; /* next even k, odd divisor */
542 2456205 : if ( k_val >= ( mem_size_m1 ) )
543 : {
544 368898 : break;
545 : }
546 2087307 : h_saveA += f_odd_exact_div_opt( numDsub1, h_saveB, h_saveA, ( k_val - ONE ) >> ONE );
547 2087307 : h[k_val] = h_saveA;
548 : }
549 : /* always do the last (k+1) recursion based on U(n,k+1) = func( A(n-2,k+1), A(n-1,k+1) ) */
550 852288 : h[mem_size_m1] = direct_row_A2U_rec_calc( dim_in, mem_size_m1, h[mem_size_m1 - 2], h[k_val_in] );
551 : }
552 :
553 : /* N_MPVQ(n,k) = 1 + U(n,k+1) + U(n,k) = 1 + U(n,k+1) + (A(n,k)-1)/2; */ /* A(n,k) always odd */
554 852288 : return ( ONE + h[mem_size_m1] + ( h[k_val_in] >> ONE ) );
555 : }
556 :
557 :
558 : /*-------------------------------------------------------------------*
559 : * find_amp_split_offset_func_mem()
560 : *
561 : * find first offset in range 0..k_val_in that is less than ind_in
562 : * using a tree search with direct function calls or memory iteration
563 : *-------------------------------------------------------------------*/
564 :
565 33657 : static int16_t find_amp_split_offset_func_mem(
566 : const uint32_t ind_in, /* i : input index */
567 : const int16_t k_val_in, /* i : number of pulses */
568 : H_FUNCM h_func_ptr, /* i : offset function pointer */
569 : const uint32_t *const h_mem, /* i : offsets */
570 : uint32_t *tmp_offset /* o : offset found */
571 : )
572 : {
573 : int16_t not_ready, low, high;
574 : int16_t k_test;
575 :
576 33657 : k_test = -1; /* init to eliminate compiler warning */
577 33657 : low = 0;
578 33657 : high = k_val_in;
579 : /* split over A(n,k)= h_mem(k), or use direct function */
580 33657 : not_ready = ONE;
581 236796 : while ( not_ready )
582 : {
583 203139 : k_test = ( low + high ) >> ONE; /*% split range in half */
584 :
585 203139 : if ( h_mem )
586 : {
587 0 : *tmp_offset = h_mem[k_test]; /* memory search */
588 : }
589 : else
590 : {
591 203139 : *tmp_offset = ( *h_func_ptr )( (uint32_t) k_test ); /* function search. NB only line difference to the memory search*/
592 : }
593 :
594 203139 : if ( ind_in > *tmp_offset )
595 : {
596 141831 : if ( k_test < high )
597 : {
598 108495 : low = 1 + k_test;
599 : }
600 : else
601 : {
602 33336 : not_ready = 0;
603 : }
604 : }
605 : else
606 : {
607 61308 : if ( *tmp_offset == ind_in )
608 : {
609 321 : not_ready = 0;
610 : }
611 : else
612 : {
613 60987 : high = k_test - 1;
614 : }
615 : }
616 : }
617 :
618 33657 : return k_test;
619 : }
620 :
621 : /*-------------------------------------------------------------------*
622 : * get_lead_sign()
623 : *
624 : * update index and return leading sign
625 : *-------------------------------------------------------------------*/
626 :
627 : /*! r: leading sign [-1,1] */
628 2835990 : static int16_t get_lead_sign(
629 : uint32_t *ind /* i/o: Current index */
630 : )
631 : {
632 : int16_t leading_sign;
633 :
634 2835990 : if ( ( *ind ) & ONE_U ) /* leading sign stored in LSB */
635 : {
636 1416423 : leading_sign = -1;
637 : }
638 : else
639 : {
640 1419567 : leading_sign = 1;
641 : }
642 2835990 : ( *ind ) = ( *ind ) >> ONE;
643 :
644 2835990 : return leading_sign;
645 : }
646 :
647 :
648 : /*-------------------------------------------------------------------*
649 : * mind2vec_one()
650 : *-------------------------------------------------------------------*/
651 :
652 126 : static void mind2vec_one(
653 : const int16_t k_val_in, /* i : nb unit pulses */
654 : const int16_t leading_sign, /* i : leading sign */
655 : const uint32_t ind, /* i : index */
656 : int16_t *vec_out /* o : pulse train */
657 : )
658 : {
659 :
660 126 : vec_out[ind] = ( leading_sign * k_val_in ); /* NB input k_val_in can be zero */
661 :
662 126 : return;
663 : }
664 :
665 : /*-------------------------------------------------------------------*
666 : * mind2vec_two()
667 : *-------------------------------------------------------------------*/
668 :
669 32400 : static void mind2vec_two(
670 : const int16_t k_val_in, /* i : nb unit pulses */
671 : const int16_t leading_sign, /* i : leading sign */
672 : const uint32_t ind_in, /* i : index */
673 : int16_t *vec_out /* o : pulse train */
674 : )
675 : {
676 : uint32_t ind_tmp;
677 : int16_t val1;
678 :
679 32400 : if ( k_val_in > 0 ) /* k_val_in check */
680 : {
681 32400 : if ( ind_in == 0 )
682 : {
683 2400 : vec_out[0] = ( leading_sign * k_val_in );
684 2400 : vec_out[1] = 0;
685 : }
686 30000 : else if ( ind_in == ( (uint32_t) ( k_val_in << ONE ) - ONE_U ) )
687 : {
688 1701 : vec_out[0] = 0;
689 1701 : vec_out[1] = ( leading_sign * k_val_in );
690 : }
691 : else
692 : {
693 28299 : ind_tmp = ind_in - ONE_U;
694 28299 : val1 = (int16_t) ( ONE_U + ( ind_tmp >> ONE ) );
695 28299 : vec_out[0] = leading_sign * ( k_val_in - val1 );
696 :
697 28299 : if ( ind_tmp & ONE_U )
698 : {
699 14511 : vec_out[1] = -val1;
700 : }
701 : else
702 : {
703 13788 : vec_out[1] = val1;
704 : }
705 : }
706 : }
707 :
708 32400 : return;
709 : }
710 :
711 : /*-------------------------------------------------------------------*
712 : * setval_update_sign()
713 : *
714 : *
715 : *-------------------------------------------------------------------*/
716 :
717 : /*! r: max k */
718 8109831 : static int16_t setval_update_sign(
719 : const int16_t k_delta, /* i : Delta-K */
720 : int16_t k_max_local, /* i/o: Maximum K */
721 : int16_t *leading_sign, /* o : Leading sign */
722 : uint32_t *ind_in, /* i/o: Index/index with leading sign excluded */
723 : int16_t *vec_out /* o : Output vector */
724 : )
725 : {
726 8109831 : if ( k_delta != 0 )
727 : {
728 2835990 : *vec_out = ( *leading_sign ) * k_delta;
729 2835990 : *leading_sign = get_lead_sign( ind_in );
730 2835990 : k_max_local = k_max_local - k_delta;
731 : }
732 :
733 8109831 : return k_max_local;
734 : }
735 :
736 : /*-------------------------------------------------------------------*
737 : * mind2vec_three()
738 : *-------------------------------------------------------------------*/
739 :
740 32628 : static void mind2vec_three(
741 : int16_t k_max_local, /* i : nb unit pulses */
742 : int16_t leading_sign, /* i : leading sign */
743 : uint32_t ind_in, /* i : index */
744 : int16_t *vec_out /* o : pulse train */
745 : )
746 : {
747 : int16_t k_delta;
748 : uint32_t acc_val;
749 :
750 : /*
751 : use direct calculation of first amplitude
752 : (to find amplitudes faster than using split or linear iteration)
753 : */
754 32628 : if ( ind_in == 0 )
755 : {
756 531 : vec_out[0] = leading_sign * k_max_local;
757 : }
758 : else
759 : {
760 32097 : acc_val = ( ( ONE_U + floor_sqrt_exact( ( ind_in << ONE ) - ONE_U ) ) >> ONE ); /* in BASOP use approximation + search for exact sqrt )*/
761 :
762 32097 : k_delta = k_max_local - (int16_t) acc_val;
763 32097 : ind_in -= a_three( acc_val ); /* remove amplitude offset A(n,k_acc) */
764 :
765 32097 : k_max_local = setval_update_sign( k_delta, k_max_local, &leading_sign, &ind_in, vec_out );
766 :
767 32097 : mind2vec_two( k_max_local, leading_sign, ind_in, &vec_out[1] );
768 : }
769 :
770 32628 : return;
771 : }
772 :
773 : /*-------------------------------------------------------------------*
774 : * mind2vec_direct()
775 : *
776 : * general function for direct decoding using direct functions
777 : * (no memory recursion)
778 : *-------------------------------------------------------------------*/
779 :
780 33798 : static void mind2vec_direct(
781 : int16_t k_max_local, /* i : nb unit pulses */
782 : int16_t leading_sign, /* i : leading sign */
783 : uint32_t ind, /* i : index */
784 : H_FUNCM h_func_ptr, /* i : offset function */
785 : NDIM_FUNCM nd_func_ptr, /* i : next dimension function */
786 : int16_t *vec_out /* o : pulse train */
787 : )
788 : {
789 33798 : int16_t k_delta, k_test = 0;
790 : uint32_t tmp_offset;
791 :
792 33798 : if ( ind == 0 )
793 : {
794 141 : vec_out[0] = leading_sign * k_max_local;
795 : }
796 : else
797 : {
798 33657 : k_test = find_amp_split_offset_func_mem( ind, k_max_local, h_func_ptr, NULL, &tmp_offset );
799 :
800 33657 : k_delta = k_max_local - k_test;
801 33657 : ind = ind - tmp_offset; /* % remove amplitude offset A(n,k_acc) */
802 33657 : k_max_local = setval_update_sign( k_delta, k_max_local, &leading_sign, &ind, vec_out );
803 33657 : ( *nd_func_ptr )( k_max_local, leading_sign, ind, &vec_out[1] );
804 : }
805 :
806 33798 : return;
807 : }
808 :
809 : /*-------------------------------------------------------------------*
810 : * mind2vec_four()
811 : *-------------------------------------------------------------------*/
812 :
813 32742 : static void mind2vec_four(
814 : int16_t k_val_in, /* i : nb unit pulses */
815 : int16_t leading_sign, /* i : leading sign */
816 : uint32_t ind_in, /* i : index */
817 : int16_t *vec_out /* o : pulse train */
818 : )
819 : {
820 32742 : mind2vec_direct( k_val_in, leading_sign, ind_in, a_four, mind2vec_three, vec_out );
821 :
822 32742 : return;
823 : }
824 :
825 : /*-------------------------------------------------------------------*
826 : * mind2vec_five()
827 : *-------------------------------------------------------------------*/
828 :
829 1056 : static void mind2vec_five(
830 : int16_t k_val_in, /* i : nb unit pulses */
831 : int16_t leading_sign, /* i : leading sign */
832 : uint32_t ind_in, /* i : index */
833 : int16_t *vec_out /* o : pulse train */
834 : )
835 : {
836 1056 : mind2vec_direct( k_val_in, leading_sign, ind_in, a_five, mind2vec_four, vec_out );
837 :
838 1056 : return;
839 : }
840 :
841 :
842 : /*-------------------------------------------------------------------*
843 : * mind2vec()
844 : *-------------------------------------------------------------------*/
845 :
846 852288 : static void mind2vec(
847 : int16_t dim_in, /* i : dimension */
848 : int16_t k_max_local, /* i : nb unit pulses */
849 : int16_t leading_sign, /* i : leading sign */
850 : uint32_t ind, /* i : index */
851 : int16_t *vec_out, /* o : pulse train */
852 : uint32_t *h_in /* i : offset vector A=1+2U */
853 : )
854 : {
855 : int16_t pos;
856 : int16_t k_acc, k_delta;
857 : uint32_t tmp_offset;
858 :
859 852288 : k_acc = k_max_local;
860 :
861 852288 : pos = ZERO;
862 8896365 : while ( pos < dim_in ) /* first to last position decoding */
863 : {
864 8896365 : if ( ind == 0 )
865 : {
866 852288 : vec_out[pos] = leading_sign * k_max_local;
867 852288 : break; /* "fast" recursion exit */
868 : }
869 : else
870 : {
871 : {
872 : /* linear magnitude search */
873 8044077 : k_acc = k_max_local;
874 8044077 : tmp_offset = h_in[k_acc];
875 12883296 : while ( tmp_offset > ind )
876 : {
877 4839219 : k_acc = k_acc - 1;
878 4839219 : tmp_offset = h_in[k_acc];
879 : }
880 : }
881 8044077 : k_delta = k_max_local - k_acc; /* amplitude decoding */
882 : }
883 8044077 : ind = ind - tmp_offset; /* remove amplitude index offset A(n,k_acc) */
884 :
885 8044077 : k_max_local = setval_update_sign( k_delta, k_max_local, &leading_sign, &ind, &vec_out[pos] );
886 :
887 : /* move from A(n,kmax) to A(n-1, k_max_local), */
888 8044077 : a_bwd( h_in, k_max_local + 1 ); /* [0..k_max_local], no need to calculate U(n,k_max_local+1) in index decoding */
889 8044077 : pos = pos + 1;
890 : }
891 :
892 852288 : return;
893 : }
894 :
895 :
896 : /*-------------------------------------------------------------------*
897 : * vec2mind_one()
898 : *-------------------------------------------------------------------*/
899 :
900 42 : static void vec2mind_one(
901 : const int16_t *vec_in, /* i : PVQ abs pulse train */
902 : int16_t *k_val_out_ptr, /* o : number of unit pulses */
903 : uint32_t *next_sign_ind, /* i/o: next sign ind */
904 : uint32_t *ind /* o : MPVQ index */
905 : )
906 : {
907 42 : *k_val_out_ptr = -1; /* just to avoid compiler warnings */
908 :
909 42 : *ind = ZERO;
910 : /* *k_val_out_ptr = (int16_t)abs(*vec_in); */ /* dim==1, function not called recursively */
911 42 : *next_sign_ind = (uint32_t) ( *vec_in < ZERO ); /* single sign always pushed out of MPVQ */
912 42 : return;
913 : }
914 :
915 : /*-------------------------------------------------------------------*
916 : * vec2mind_two()
917 : *-------------------------------------------------------------------*/
918 :
919 299722 : static void vec2mind_two(
920 : const int16_t *vec_in, /* i : PVQ pulse train */
921 : int16_t *k_val_out_ptr, /* o : number of unit pulses */
922 : uint32_t *next_sign_ind, /* i/o: next sign ind */
923 : uint32_t *ind /* o : MPVQ index */
924 : )
925 : {
926 : uint32_t lead_sign_ind;
927 : int16_t abs0, abs1, abs01;
928 :
929 299722 : abs0 = (int16_t) abs( vec_in[0] );
930 299722 : abs1 = (int16_t) abs( vec_in[1] );
931 :
932 299722 : abs01 = abs0 + abs1;
933 299722 : *k_val_out_ptr = abs01;
934 :
935 299722 : if ( abs01 == 0 ) /* zeroes can happen in a recursive encoding call */
936 : {
937 130749 : *next_sign_ind = SIGNBIT;
938 130749 : *ind = ZERO;
939 : }
940 : else
941 : {
942 168973 : *next_sign_ind = 0;
943 168973 : if ( abs1 == 0 )
944 : {
945 50034 : *ind = ZERO;
946 : }
947 118939 : else if ( abs0 == 0 )
948 : {
949 47624 : *ind = (uint32_t) ( abs1 << ONE ) - ONE_U;
950 47624 : *next_sign_ind = 1;
951 : }
952 : else
953 : {
954 71315 : lead_sign_ind = (uint32_t) ( vec_in[1] < 0 ); /*% sign always shifted to first pos */
955 71315 : *ind = ONE_U + ( (uint32_t) ( abs1 - 1 ) << ONE ) + lead_sign_ind;
956 : }
957 168973 : *next_sign_ind = (uint32_t) ( vec_in[*next_sign_ind] < 0 );
958 : }
959 :
960 299722 : return;
961 : }
962 :
963 :
964 : /*-------------------------------------------------------------------*
965 : * vec2mind_gen345( vec_in kval, next_dim_func, offset_func,....)
966 : * generic call saves PROM ,
967 : *-------------------------------------------------------------------*/
968 :
969 22398 : static void vec2mind_gen345(
970 : const int16_t *vec_in, /* i : PVQ abs pulse train */
971 : int16_t *k_val_out_ptr, /* o : number of unit pulses */
972 : uint32_t *next_sign_ind, /* i/o: next sign ind */
973 : uint32_t *index, /* o : MPVQ index */
974 : VEC2INDFUNCM vec2indfunc_ptr, /* i : */
975 : H_FUNCM a_func_ptr /* i : offset function */
976 : )
977 : {
978 : int16_t tmp_val;
979 :
980 22398 : tmp_val = vec_in[ZERO];
981 22398 : ( *vec2indfunc_ptr )( &vec_in[ONE], k_val_out_ptr, next_sign_ind, index );
982 :
983 22398 : if ( ( ( *next_sign_ind & SIGNBIT ) == 0 && tmp_val != 0 ) != ZERO )
984 : {
985 20263 : *index = ( *index << ONE ) + *next_sign_ind;
986 : }
987 :
988 22398 : if ( tmp_val != 0 ) /* push sign */
989 : {
990 20488 : *next_sign_ind = (uint32_t) ( tmp_val < 0 );
991 : }
992 :
993 22398 : *index += ( *a_func_ptr )( (uint32_t) *k_val_out_ptr );
994 22398 : if ( tmp_val > 0 )
995 : {
996 10266 : *k_val_out_ptr += tmp_val;
997 : }
998 : else
999 : {
1000 12132 : *k_val_out_ptr -= tmp_val;
1001 : }
1002 :
1003 22398 : return;
1004 : }
1005 :
1006 :
1007 : /*-------------------------------------------------------------------*
1008 : * vec2mind_three()
1009 : *-------------------------------------------------------------------*/
1010 :
1011 11025 : static void vec2mind_three(
1012 : const int16_t *vec_in, /* i : PVQ pulse train */
1013 : int16_t *k_val_out_ptr, /* o : number of unit pulses */
1014 : uint32_t *next_sign_ind, /* i/o: next sign ind */
1015 : uint32_t *index /* o : MPVQ index */
1016 : )
1017 : {
1018 11025 : vec2mind_gen345( vec_in, k_val_out_ptr, next_sign_ind, index, vec2mind_two, a_three );
1019 :
1020 11025 : return;
1021 : }
1022 :
1023 : /*-------------------------------------------------------------------*
1024 : * vec2mind_four()
1025 : *-------------------------------------------------------------------*/
1026 :
1027 11017 : static void vec2mind_four(
1028 : const int16_t *vec_in, /* i : PVQ pulse train */
1029 : int16_t *k_val_out_ptr, /* o : number of unit pulses */
1030 : uint32_t *next_sign_ind, /* i/o: next sign ind */
1031 : uint32_t *index /* o : MPVQ index */
1032 : )
1033 : {
1034 11017 : vec2mind_gen345( vec_in, k_val_out_ptr, next_sign_ind, index, vec2mind_three, a_four );
1035 :
1036 11017 : return;
1037 : }
1038 :
1039 : /*-------------------------------------------------------------------*
1040 : * vec2mind_five()
1041 : *-------------------------------------------------------------------*/
1042 :
1043 356 : static void vec2mind_five(
1044 : const int16_t *vec_in, /* i : PVQ abs pulse train */
1045 : int16_t *k_val_out_ptr, /* o : number of unit pulses */
1046 : uint32_t *next_sign_ind, /* i/o: next sign ind */
1047 : uint32_t *index /* o : MPVQ index */
1048 : )
1049 : {
1050 356 : vec2mind_gen345( vec_in, k_val_out_ptr, next_sign_ind, index, vec2mind_four, a_five );
1051 :
1052 356 : return;
1053 : }
1054 :
1055 :
1056 : /*-------------------------------------------------------------------*
1057 : * vec2mind()
1058 : *-------------------------------------------------------------------*/
1059 :
1060 288596 : static void vec2mind(
1061 : int16_t dim_in, /* i : dim */
1062 : int16_t k_val_in, /* i : number of unit pulses */
1063 : const int16_t *vec_in, /* i : PVQ pulse train */
1064 : uint32_t *next_sign_ind, /* o : pushed leading sign */
1065 : uint32_t *index, /* o : MPVQ index */
1066 : uint32_t *N_MPVQ_ptr, /* o : size(N_MPVQ(dim,K_val_in))*/
1067 : uint32_t *h_mem /* o : offsets */
1068 : )
1069 : {
1070 : int16_t pos, mem_size_m1;
1071 : int16_t k_val_acc;
1072 : int16_t tmp_val;
1073 :
1074 288596 : mem_size_m1 = k_val_in + ONE;
1075 :
1076 288596 : *next_sign_ind = SIGNBIT; /* % should always be 0 or 1 out, highest bit set signals no sign found yet*/
1077 :
1078 288596 : pos = dim_in - 2; /* % address 2nd last sample */
1079 288596 : vec2mind_two( &vec_in[pos], &k_val_acc, next_sign_ind, index );
1080 288596 : initOffsets( 3, h_mem, k_val_in );
1081 :
1082 3501064 : for ( pos--; pos >= 0; pos-- )
1083 : {
1084 : /*
1085 : % Check if the leading sign 'bit' is to be added
1086 : */
1087 3212468 : tmp_val = vec_in[pos];
1088 3212468 : if ( ( ( *next_sign_ind & SIGNBIT ) == 0 && ( tmp_val != 0 ) ) )
1089 : {
1090 876055 : *index = ( *index << ONE ) + ( *next_sign_ind );
1091 : }
1092 :
1093 : /* % push sign fwd, for encoding in the next non_zero position */
1094 3212468 : if ( tmp_val != 0 )
1095 : {
1096 1006579 : *next_sign_ind = (uint32_t) ( tmp_val < 0 );
1097 : }
1098 :
1099 : /*% add indexing offset up to this reverse (r_l) accumulated amplitude point */
1100 3212468 : *index += h_mem[k_val_acc]; /* % k_val_acc==0 ==>0 */
1101 :
1102 3212468 : k_val_acc += (int16_t) abs( tmp_val ); /*% now increase acc k value for next N */
1103 :
1104 3212468 : if ( pos )
1105 : {
1106 2923872 : a_u_fwd( h_mem, k_val_in, mem_size_m1 );
1107 : /*% update A(n,k=1:k_val_in) and U(n,k_val_in+1), NB here (k_val_in + 2 elements always has to be updated */
1108 : }
1109 : }
1110 :
1111 : /* size is needed for the subseqent arithmetic encoding/transmission of the index. */
1112 : /* use relation N_MPVQ(n,K) = 1 + (A(n, K)-1)/2 + U(n, 1 + K) */
1113 : /* = N_MPVQ(n,K) = 1 + (A(n, K)>>1) + U(n, 1 + K), as A(n,K) is odd) */
1114 :
1115 288596 : *N_MPVQ_ptr = ONE_U + ( h_mem[k_val_acc] >> ONE ) + h_mem[mem_size_m1]; /* total size size */
1116 :
1117 288596 : return;
1118 : }
1119 :
1120 : /*--------------------------------------------------------------------------*
1121 : * mpvq_encode_vec()
1122 : *
1123 : * returns struct with leading sign index, MPVQ-index, dim and N_MPVQ
1124 : *-------------------------------------------------------------------------*/
1125 :
1126 : /*! r: leading_sign_index, index, size, k_val */
1127 299764 : PvqEntry mpvq_encode_vec(
1128 : const int16_t *vec_in, /* i : signed pulse train */
1129 : const int16_t dim_in, /* i : dimension */
1130 : int16_t k_val_local /* i/o: nb unit pulses */
1131 : )
1132 : {
1133 : PvqEntry result;
1134 : uint32_t h_mem[1 + KMAX_NON_DIRECT + 1]; /* allocate max offset memory for dim 6 */ /* OPT: actually only 1+k_val_in+1 needed ) */
1135 : uint32_t lead_sign_ind;
1136 299764 : const VEC2INDFUNCM vec2mind_f[1 + N_OPT] = { NULL, vec2mind_one, vec2mind_two, vec2mind_three, vec2mind_four, vec2mind_five }; /* VEC2INDFUNCM can be a static global */
1137 :
1138 299764 : result.k_val = k_val_local;
1139 299764 : result.dim = dim_in;
1140 :
1141 : /* NB, k_val_local may be changed in some sub encoding routines */
1142 299764 : if ( dim_in > N_OPT ) /* use the generic dimension function */
1143 : {
1144 288596 : vec2mind( dim_in, k_val_local, vec_in, &lead_sign_ind, &result.index, &result.size, h_mem );
1145 : }
1146 : else /* if (dim_in<=N_OPT) */
1147 : {
1148 11168 : ( vec2mind_f[dim_in] )( vec_in, &k_val_local, &lead_sign_ind, &result.index );
1149 11168 : result.size = direct_msize( dim_in, k_val_local ); /* k_val_local not used for dim==1 */
1150 : }
1151 299764 : result.lead_sign_ind = (int16_t) lead_sign_ind;
1152 :
1153 299764 : return result;
1154 : }
1155 :
1156 : /*-------------------------------------------------------------------*
1157 : * get_size_mpvq_calc_offset()
1158 : *
1159 : * uint32_t h_mem[1 + KMAX +1 ];
1160 : * example using fixed size of offset vector input help variable
1161 : *-------------------------------------------------------------------*/
1162 :
1163 : /*! r: size, dim, k_val */
1164 885486 : PvqEntry get_size_mpvq_calc_offset(
1165 : const int16_t dim_in, /* i : dimension */
1166 : const int16_t k_val_in, /* i : nb unit pulses */
1167 : uint32_t *h_mem /* o : offsets */
1168 : )
1169 : {
1170 : PvqEntry entry;
1171 :
1172 885486 : entry.dim = dim_in;
1173 885486 : entry.k_val = k_val_in;
1174 885486 : entry.index = 0U; /* avoid gcc warning in struct passing */
1175 885486 : entry.lead_sign_ind = 0; /* avoid gcc warning in struct passing */
1176 885486 : if ( dim_in > N_OPT ) /* non-direct solutions, use A+U relation */
1177 : {
1178 852288 : entry.size = nm_h_prep_opt( entry.dim, entry.k_val, h_mem );
1179 : }
1180 : else
1181 : {
1182 33198 : entry.size = direct_msize( dim_in, entry.k_val ); /* ues equations, h_mem is not used */
1183 : }
1184 :
1185 :
1186 885486 : return entry;
1187 : }
1188 :
1189 : /*-------------------------------------------------------------------*
1190 : * mpvq_decode_vec()
1191 : *-------------------------------------------------------------------*/
1192 :
1193 : /*! r: void */
1194 885486 : void mpvq_decode_vec(
1195 : const PvqEntry *entry, /* i : sign_ind, index, dim, k_val */
1196 : uint32_t *h_mem, /* i : A/U offsets */
1197 : int16_t *vec_out /* o : pulse train */
1198 : )
1199 : {
1200 : int16_t i, leading_sign;
1201 885486 : const IND2VECFUNCM mind2vec_f[N_OPT + 1] = { NULL, mind2vec_one, mind2vec_two, mind2vec_three, mind2vec_four, mind2vec_five }; /*IND2VECFUNCM vector can be static global */
1202 :
1203 12213090 : for ( i = 0; i < entry->dim; i++ )
1204 : {
1205 11327604 : vec_out[i] = ZERO; /* set all of short output vector to zero */
1206 : }
1207 :
1208 885486 : leading_sign = 1;
1209 885486 : if ( entry->lead_sign_ind )
1210 : {
1211 442128 : leading_sign = -1;
1212 : }
1213 :
1214 885486 : if ( entry->k_val != 0 )
1215 : {
1216 885486 : if ( entry->dim > N_OPT ) /* N_OPT */
1217 : {
1218 : /* generic */
1219 852288 : mind2vec( entry->dim, entry->k_val, leading_sign, entry->index, vec_out, h_mem );
1220 : }
1221 : else
1222 : {
1223 : /* specialized functions */
1224 33198 : ( mind2vec_f[entry->dim] )( entry->k_val, leading_sign, entry->index, vec_out );
1225 : }
1226 : }
1227 :
1228 885486 : return;
1229 : }
1230 :
1231 : #ifdef ONE_U
1232 : #undef ZERO
1233 : #undef ONE
1234 : #undef ONE_U
1235 : #undef TWO
1236 : #undef MAXBIT
1237 : #undef MINNEG
1238 : #undef SIGNBIT
1239 : #undef UDIVBY3
1240 : #endif
1241 :
1242 : #endif
|