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 : #include <assert.h>
34 : #include <stdint.h>
35 : #include "options.h"
36 : #include <math.h>
37 : #include "ivas_cnst.h"
38 : #include "ivas_rom_com.h"
39 : #include "prot_fx.h"
40 : #include "cnst.h"
41 : #include "wmc_auto.h"
42 : #include "ivas_prot_fx.h"
43 : #include "ivas_rom_com_fx.h"
44 :
45 :
46 : /*-------------------------------------------------------------------------
47 : * ivas_qmetadata_reorder_generic()
48 : *
49 : *------------------------------------------------------------------------*/
50 22273839 : UWord16 ivas_qmetadata_reorder_generic_fx(
51 : const Word16 signed_value )
52 : {
53 : UWord16 unsigned_value;
54 :
55 22273839 : IF( signed_value < 0 )
56 : {
57 : // unsigned_value = ( ( UWord16 ) - ( signed_value + 1 ) << 1 ) + 1;
58 9215387 : unsigned_value = (UWord16) L_add( L_shl( negate( add( signed_value, 1 ) ), 1 ), 1 );
59 : }
60 : ELSE
61 : {
62 13058452 : unsigned_value = (UWord16) L_shl( signed_value, 1 );
63 : }
64 :
65 22273839 : return unsigned_value;
66 : }
67 :
68 :
69 : /*-------------------------------------------------------------------------
70 : * ivas_qmetadata_dereorder_generic()
71 : *
72 : * Returns the original value of the array "folded" by ReorderGeneric
73 : *------------------------------------------------------------------------*/
74 :
75 : /*! r: "Unfolded" value, positive or negative depending on the value of the input */
76 13479400 : Word16 ivas_qmetadata_dereorder_generic_fx(
77 : const UWord16 uns_value /* i : unsigned value result of ReorderGeneric */
78 : )
79 : {
80 13479400 : IF( L_and( uns_value, 1 ) != 0 )
81 : {
82 5832127 : return sub( negate( extract_l( L_shr( uns_value, 1 ) ) ), 1 );
83 : }
84 : ELSE
85 : {
86 7647273 : return extract_l( L_shr( uns_value, 1 ) );
87 : }
88 : }
89 :
90 :
91 : /*-------------------------------------------------------------------------
92 : * ivas_dirac_project_elevation_index()
93 : *
94 : *
95 : *------------------------------------------------------------------------*/
96 :
97 : /*! r: projected elevation index */
98 8958124 : Word16 ivas_dirac_project_elevation_index_fx(
99 : const Word16 el_idx, /* i : elevation index */
100 : const Word16 el_alph, /* i : number of elevation symbols */
101 : const Word16 el_alph_proj /* i : size of projected alphabet */
102 : )
103 : {
104 : Word16 el_idx_proj;
105 :
106 : /* evaluate floor((el_idx / (el_alph - 1)) * (el_alph_proj - 1) + 0.5) using only integer */
107 8958124 : el_idx_proj = idiv1616( add( imult1616( imult1616( 2, el_idx ), sub( el_alph_proj, 1 ) ), sub( el_alph, 1 ) ), imult1616( 2, sub( el_alph, 1 ) ) );
108 :
109 8958124 : return el_idx_proj;
110 : }
111 :
112 :
113 : /*-------------------------------------------------------------------------
114 : * ivas_chan_project_elevation_index()
115 : *
116 : *
117 : *------------------------------------------------------------------------*/
118 :
119 : /*! r: projected index in channel mode */
120 84795 : Word16 ivas_chan_project_elevation_index_fx(
121 : const Word16 el_idx, /* i : elevation index */
122 : const Word16 el_alph, /* i : number of elevation symbols */
123 : const Word16 el_alph_proj /* i : size of projected alphabet */
124 : )
125 : {
126 : Word16 el_idx_proj;
127 :
128 : /* evaluate floor((el_idx / (el_alph - 1)) * (el_alph_proj - 1) + 0.5) using only integer */
129 84795 : IF( EQ_16( el_idx, sub( el_alph, 1 ) ) )
130 : {
131 9106 : el_idx_proj = sub( el_alph_proj, 1 );
132 : }
133 : ELSE
134 : {
135 75689 : el_idx_proj = idiv1616( add( imult1616( imult1616( 2, el_idx ), el_alph_proj ), el_alph ), imult1616( 2, el_alph ) );
136 : }
137 :
138 84795 : return el_idx_proj;
139 : }
140 :
141 :
142 : /*-------------------------------------------------------------------------
143 : * ivas_dirac_project_azimuth_index()
144 : *
145 : *
146 : *------------------------------------------------------------------------*/
147 :
148 : /*! r: projected azimuth index */
149 10386410 : Word16 ivas_dirac_project_azimuth_index_fx(
150 : const Word16 az_idx, /* i : azimuth index */
151 : const Word16 az_alph, /* i : number of azimuth symbols */
152 : const Word16 az_alph_proj /* i : size of projected alphabet */
153 : )
154 : {
155 : Word16 az_idx_proj;
156 :
157 10386410 : IF( EQ_16( az_alph_proj, 1 ) )
158 : {
159 5125 : return 0;
160 : }
161 :
162 : /* evaluate floor((az_idx / az_alph) * az_alph_proj + 0.5) using only integer */
163 10381285 : az_idx_proj = idiv1616( add( imult1616( imult1616( 2, az_idx ), az_alph_proj ), az_alph ), imult1616( 2, az_alph ) );
164 :
165 10381285 : if ( EQ_16( az_idx_proj, az_alph_proj ) )
166 : {
167 242243 : az_idx_proj = 0;
168 242243 : move16();
169 : }
170 :
171 10381285 : return az_idx_proj;
172 : }
173 :
174 :
175 : /*-------------------------------------------------------------------------
176 : * small_reduction_direction()
177 : *
178 : * Compute the allocated bit reduction in spherical indexing for bit budget
179 : * is exceeded by diff. bits
180 : *------------------------------------------------------------------------*/
181 :
182 8368 : void small_reduction_direction_fx(
183 : IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */
184 : UWord16 bits_dir[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES],
185 : const Word16 raw_flag[MASA_MAXIMUM_CODING_SUBBANDS],
186 : Word16 *diff )
187 : {
188 : Word16 i, j, k;
189 :
190 8368 : test();
191 22512 : FOR( k = 0; ( k < 2 ) && ( *diff > 0 ); k++ )
192 : {
193 14144 : test();
194 14144 : test();
195 70132 : FOR( i = q_direction->cfg.start_band; ( i < q_direction->cfg.nbands ) && ( *diff > 0 ); i++ )
196 : {
197 55988 : test();
198 55988 : IF( EQ_16( raw_flag[i], 1 ) )
199 : {
200 26650 : test();
201 130063 : FOR( j = 0; ( j < q_direction->cfg.nblocks ) && ( *diff > 0 ); j++ )
202 : {
203 103413 : test();
204 103413 : IF( GT_32( bits_dir[i][j], MASA_MIN_BITS_TF ) )
205 : {
206 65797 : bits_dir[i][j] = (UWord16) L_sub( bits_dir[i][j], 1 );
207 65797 : move16();
208 65797 : ( *diff )--;
209 : }
210 : }
211 : }
212 : }
213 : }
214 :
215 8368 : return;
216 : }
217 :
218 :
219 : /*-----------------------------------------------------------------------*
220 : * quantize_phi()
221 : *
222 : * Quantize azimuth.
223 : * Input phi expected to be an angle in degree between 0 and 360.
224 : *-----------------------------------------------------------------------*/
225 : /*! r: index azimuth */
226 :
227 8376 : Word16 quantize_phi_fx(
228 : Word32 phi, /* i : azimuth value, Q22 */
229 : const Word16 flag_delta, /* i : flag indicating if the azimuth codebook is translated or not */
230 : Word32 *phi_hat, /* o : quantized azimuth, Q22 */
231 : const Word16 n /* i : azimuth codebook size */
232 : )
233 : {
234 : Word16 id_phi;
235 : Word32 dd_fx;
236 : Word32 delta_phi_fx;
237 : Word32 inv_delta_phi_fx;
238 : Word32 temp_res;
239 :
240 8376 : delta_phi_fx = delta_phi_val[n]; // Q22
241 8376 : move32();
242 8376 : inv_delta_phi_fx = inv_delta_phi_val[n]; // Q31
243 8376 : move32();
244 8376 : IF( EQ_16( n, 1 ) )
245 : {
246 0 : *phi_hat = 0;
247 0 : move32();
248 :
249 0 : return 0;
250 : }
251 :
252 8376 : test();
253 8376 : IF( EQ_16( flag_delta, 1 ) && GT_16( n, 2 ) )
254 : {
255 0 : dd_fx = dd_val[n];
256 0 : move32();
257 : }
258 : ELSE
259 : {
260 8376 : dd_fx = 0;
261 8376 : move32();
262 : }
263 :
264 8376 : temp_res = Mpy_32_32( L_sub( L_sub( phi, DEGREE_180_Q_22 ), dd_fx ), inv_delta_phi_fx ); // Q22 + Q31 - Q31 -> Q22
265 8376 : id_phi = round_fx( L_shr( temp_res, Q22 - Q16 ) ); // Q0
266 :
267 8376 : assert( L_sub( L_abs( temp_res ), abs( id_phi ) * ONE_IN_Q22 ) <= ONE_IN_Q21 );
268 :
269 :
270 8376 : IF( add( id_phi, shr( n, 1 ) ) < 0 )
271 : {
272 0 : id_phi = add( id_phi, 1 );
273 : }
274 :
275 8376 : IF( sub( id_phi, shr( n, 1 ) ) >= 0 )
276 : {
277 4 : id_phi = negate( shr( n, 1 ) );
278 : }
279 :
280 8376 : IF( EQ_16( id_phi, negate( add( shr( n, 1 ), ( n % 2 ) ) ) ) )
281 : {
282 7 : id_phi = add( id_phi, ( n % 2 ) );
283 : }
284 : ELSE{
285 8369 : IF( EQ_16( id_phi, add( shr( n, 1 ), ( n % 2 ) ) ) ){
286 0 : IF( n % 2 ){
287 0 : id_phi = sub( id_phi, 1 );
288 : }
289 : ELSE
290 : {
291 0 : id_phi = negate( id_phi );
292 : }
293 : }
294 : }
295 :
296 8376 : *phi_hat = L_add_sat( L_add_sat( imult3216( delta_phi_fx, id_phi ), dd_fx ), DEGREE_180_Q_22 ); // Q22
297 8376 : move32();
298 8376 : id_phi = add( id_phi, shr( n, 1 ) );
299 :
300 8376 : return id_phi;
301 : }
302 :
303 6591116 : Word16 quantize_phi_enc_fx(
304 : Word32 phi, /* i : azimuth value, Q22 */
305 : const Word16 flag_delta, /* i : flag indicating if the azimuth codebook is translated or not */
306 : Word32 *phi_hat, /* o : quantized azimuth, Q22 */
307 : const Word16 n /* i : azimuth codebook size */
308 : )
309 : {
310 : Word16 id_phi;
311 : Word32 dd_fx;
312 : Word32 delta_phi_fx;
313 : Word32 inv_delta_phi_fx;
314 : Word32 temp_res;
315 : Word16 temp_e;
316 :
317 6591116 : delta_phi_fx = BASOP_Util_Divide3232_Scale_newton( 360, n, &temp_e );
318 6591116 : delta_phi_fx = L_shl( delta_phi_fx, sub( temp_e, 9 ) );
319 6591116 : inv_delta_phi_fx = BASOP_Util_Divide3232_Scale_newton( n, 360, &temp_e );
320 :
321 6591116 : IF( EQ_16( n, 1 ) )
322 : {
323 0 : *phi_hat = 0;
324 0 : move32();
325 :
326 0 : return 0;
327 : }
328 :
329 6591116 : test();
330 6591116 : IF( EQ_16( flag_delta, 1 ) && GT_16( n, 2 ) )
331 : {
332 1598880 : dd_fx = dd_val[n];
333 1598880 : move32();
334 : }
335 : ELSE
336 : {
337 4992236 : dd_fx = 0;
338 4992236 : move32();
339 : }
340 :
341 6591116 : temp_res = Mpy_32_32( L_sub( L_sub( phi, DEGREE_180_Q_22 ), dd_fx ), inv_delta_phi_fx );
342 6591116 : temp_res = L_shl( temp_res, temp_e );
343 6591116 : id_phi = round_fx( L_shr( temp_res, Q22 - Q16 ) );
344 :
345 6591116 : assert( L_sub( L_abs( temp_res ), abs( id_phi ) * ONE_IN_Q22 ) <= ONE_IN_Q21 );
346 :
347 :
348 6591116 : IF( add( id_phi, shr( n, 1 ) ) < 0 )
349 : {
350 25217 : id_phi = add( id_phi, 1 );
351 : }
352 :
353 6591116 : IF( sub( id_phi, shr( n, 1 ) ) >= 0 )
354 : {
355 473579 : id_phi = negate( shr( n, 1 ) );
356 : }
357 :
358 6591116 : IF( EQ_16( id_phi, negate( add( shr( n, 1 ), ( n % 2 ) ) ) ) )
359 : {
360 809096 : id_phi = add( id_phi, ( n % 2 ) );
361 : }
362 : ELSE{
363 5782020 : IF( EQ_16( id_phi, add( shr( n, 1 ), ( n % 2 ) ) ) ){
364 0 : IF( n % 2 ){
365 0 : id_phi = sub( id_phi, 1 );
366 : }
367 : ELSE
368 : {
369 0 : id_phi = negate( id_phi );
370 : }
371 : }
372 : }
373 :
374 6591116 : *phi_hat = L_add_sat( L_add_sat( ( imult3216( delta_phi_fx, id_phi ) ), dd_fx ), DEGREE_180_Q_22 );
375 6591116 : move32();
376 6591116 : id_phi = add( id_phi, shr( n, 1 ) );
377 :
378 6591116 : return id_phi;
379 : }
380 : /*-----------------------------------------------------------------------*
381 : * companding_azimuth()
382 : *
383 : * Compand azimuth based on the format
384 : *-----------------------------------------------------------------------*/
385 :
386 314031 : Word32 companding_azimuth_fx(
387 : const Word32 azi_fx, /* i : input azimuth value, Q22 */
388 : const MC_LS_SETUP mc_format, /* i : input channel format */
389 : const Word16 theta_flag, /* i : zero/non zero elevation flag */
390 : const Word16 direction /* i : direction of companding (direct or inverse)*/
391 : )
392 : {
393 314031 : const Word16 pointsA[] = { 0, 60, 110, 150, 180, 0, 50, 90, 150, 180, 0, 30, 80, 150, 180 }; // Q0
394 314031 : const Word16 pointsB[] = { 0, 90, 110, 170, 180, 0, 90, 110, 170, 180, 0, 10, 100, 170, 180 }; // Q0
395 : const Word16 *pA;
396 314031 : const Word32 pointsA_fx[] = { 0, 251658240, 461373440, 629145600, 754974720, 0, 209715200, 377487360, 629145600, 754974720, 0, 125829120, 335544320, 629145600, 754974720 }; // q=22
397 314031 : const Word32 pointsB_fx[] = { 0, 377487360, 461373440, 713031680, 754974720, 0, 377487360, 461373440, 713031680, 754974720, 0, 41943040, 419430400, 713031680, 754974720 }; // q=22
398 : const Word32 *pA_fx, *pB_fx;
399 : Word16 no_points;
400 : Word32 comp_azi_fx;
401 : Word16 i, not_done, start;
402 : Word32 abs_azi_fx;
403 314031 : move16();
404 314031 : move16();
405 314031 : move16();
406 314031 : move16();
407 314031 : move16();
408 314031 : move16();
409 314031 : move16();
410 314031 : move16();
411 314031 : move16();
412 314031 : move16();
413 314031 : move16();
414 314031 : move16();
415 314031 : move16();
416 314031 : move16();
417 314031 : move16();
418 314031 : move16();
419 314031 : move16();
420 314031 : move16();
421 314031 : move16();
422 314031 : move16();
423 314031 : move16();
424 314031 : move16();
425 314031 : move16();
426 314031 : move16();
427 314031 : move16();
428 314031 : move16();
429 314031 : move16();
430 314031 : move16();
431 314031 : move16();
432 314031 : move16();
433 314031 : move32();
434 314031 : move32();
435 314031 : move32();
436 314031 : move32();
437 314031 : move32();
438 314031 : move32();
439 314031 : move32();
440 314031 : move32();
441 314031 : move32();
442 314031 : move32();
443 314031 : move32();
444 314031 : move32();
445 314031 : move32();
446 314031 : move32();
447 314031 : move32();
448 314031 : move32();
449 314031 : move32();
450 314031 : move32();
451 314031 : move32();
452 314031 : move32();
453 314031 : move32();
454 314031 : move32();
455 314031 : move32();
456 314031 : move32();
457 314031 : move32();
458 314031 : move32();
459 314031 : move32();
460 314031 : move32();
461 314031 : move32();
462 314031 : move32();
463 :
464 314031 : test();
465 314031 : test();
466 314031 : IF( EQ_32( mc_format, MC_LS_SETUP_5_1 ) || EQ_32( mc_format, MC_LS_SETUP_5_1_2 ) || EQ_32( mc_format, MC_LS_SETUP_5_1_4 ) ) /* 5.1, 5.1+2 or 5.1+4*/
467 : {
468 250833 : start = 5;
469 250833 : move16();
470 : }
471 : ELSE
472 : {
473 63198 : start = 0;
474 63198 : move16();
475 : }
476 :
477 : /* theta flag 1 is for non zero, larger than a threshold elevation */
478 314031 : test();
479 314031 : test();
480 314031 : test();
481 314031 : IF( ( EQ_16( theta_flag, 1 ) ) && ( ( EQ_32( mc_format, MC_LS_SETUP_5_1_2 ) ) || ( EQ_32( mc_format, MC_LS_SETUP_5_1_4 ) ) || ( EQ_32( mc_format, MC_LS_SETUP_7_1_4 ) ) ) ) /* 5.1+2, 5.1+4 or 7.1+4*/
482 : {
483 28186 : start = 10;
484 28186 : move16();
485 : }
486 314031 : no_points = 5;
487 314031 : move16();
488 :
489 314031 : pA_fx = &pointsA_fx[start];
490 314031 : pB_fx = &pointsB_fx[start];
491 314031 : pA = &pointsA[start];
492 :
493 314031 : IF( EQ_16( direction, -1 ) ) /* inverse companding */
494 : {
495 196953 : pA_fx = &pointsB_fx[start];
496 196953 : pB_fx = &pointsA_fx[start];
497 196953 : pA = &pointsB[start];
498 : }
499 : ELSE
500 : {
501 117078 : IF( NE_16( direction, 1 ) )
502 : {
503 0 : printf( "Wrong direction in companding" );
504 : }
505 : }
506 :
507 314031 : not_done = 1;
508 314031 : move16();
509 314031 : abs_azi_fx = L_abs( azi_fx );
510 :
511 314031 : comp_azi_fx = azi_fx;
512 314031 : move32();
513 314031 : i = 0;
514 314031 : move16();
515 695083 : WHILE( not_done && ( LT_16( i, sub( no_points, 1 ) ) ) )
516 : {
517 381052 : test();
518 381052 : IF( LE_32( abs_azi_fx, pA_fx[i + 1] ) )
519 : {
520 314031 : not_done = 0;
521 314031 : move16();
522 : /* calculate companding */
523 314031 : comp_azi_fx = Mpy_32_32( L_sub( pB_fx[i + 1], pB_fx[i] ), L_sub( abs_azi_fx, pA_fx[i] ) ); // ( Q22 + Q22 - Q31 ) -> Q13
524 314031 : SWITCH( sub( pA[i + 1], pA[i] ) )
525 : {
526 9604 : case 10:
527 : // Q13 + Q31 - Q31 -> Q13
528 9604 : comp_azi_fx = Mpy_32_32( comp_azi_fx, 214748364 ); // 1 / 10 in 2 ^ 31
529 9604 : BREAK;
530 11668 : case 20:
531 : // Q13 + Q31 - Q31 -> Q13
532 11668 : comp_azi_fx = Mpy_32_32( comp_azi_fx, 107374182 ); // 1 / 20 in 2 ^ 31
533 11668 : BREAK;
534 3447 : case 30:
535 : // Q13 + Q31 - Q31 -> Q13
536 3447 : comp_azi_fx = Mpy_32_32( comp_azi_fx, 71582788 ); // 1 / 30 in 2 ^ 31
537 3447 : BREAK;
538 8661 : case 40:
539 : // Q13 + Q31 - Q31 -> Q13
540 8661 : comp_azi_fx = Mpy_32_32( comp_azi_fx, 53687091 ); // 1 / 40 in 2 ^ 31
541 8661 : BREAK;
542 88822 : case 50:
543 : // Q13 + Q31 - Q31 -> Q13
544 88822 : comp_azi_fx = Mpy_32_32( comp_azi_fx, 42949672 ); // 1 / 50 in 2 ^ 31
545 88822 : BREAK;
546 18710 : case 60:
547 : // Q13 + Q31 - Q31 -> Q13
548 18710 : comp_azi_fx = Mpy_32_32( comp_azi_fx, 35791394 ); // 1 / 60 in 2 ^ 31
549 18710 : BREAK;
550 7111 : case 70:
551 : // Q13 + Q31 - Q31 -> Q13
552 7111 : comp_azi_fx = Mpy_32_32( comp_azi_fx, 30678337 ); // 1 / 70 in 2 ^ 31
553 7111 : BREAK;
554 166008 : case 90:
555 : // Q13 + Q31 - Q31 -> Q13
556 166008 : comp_azi_fx = Mpy_32_32( comp_azi_fx, 23860929 ); // 1 / 90 in 2 ^ 31
557 166008 : BREAK;
558 0 : default:
559 0 : assert( 0 );
560 : BREAK;
561 : }
562 314031 : comp_azi_fx = L_add( pB_fx[i], L_shl( comp_azi_fx, Q22 - Q13 ) ); // Q22
563 : // comp_azi = pB[i] + ( pB[i + 1] - pB[i] ) / ( pA[i + 1] - pA[i] ) * ( abs_azi - pA[i] );
564 : }
565 : ELSE
566 : {
567 67021 : i = add( i, 1 );
568 : }
569 : }
570 :
571 314031 : IF( azi_fx < 0 )
572 : {
573 150249 : comp_azi_fx = L_negate( comp_azi_fx ); // Q22
574 : }
575 :
576 314031 : IF( EQ_16( not_done, 1 ) )
577 : {
578 0 : comp_azi_fx = azi_fx; // Q22
579 0 : move32();
580 : }
581 :
582 314031 : return comp_azi_fx; // Q22
583 : }
584 :
585 : /*-----------------------------------------------------------------------*
586 : * quantize_phi_chan_lbr()
587 : *
588 : * Quantize azimuth in low-bitrate channel mode.
589 : * Input phi expected to be an angle in degree between 0 and 360.
590 : *-----------------------------------------------------------------------*/
591 :
592 : /*! r: index azimuth */
593 2325 : Word16 quantize_phi_chan_lbr_fx(
594 : const Word32 phi, /* i : azimuth value, Q22 */
595 : Word32 *phi_hat, /* o : quantized azimuth, Q22 */
596 : const Word16 n /* i : azimuth codebook size */
597 : )
598 : {
599 : Word16 id_phi, phi_hat_16;
600 :
601 :
602 2325 : IF( LE_16( n, 1 ) )
603 : {
604 0 : *phi_hat = 0;
605 0 : move32();
606 :
607 0 : return 0;
608 : }
609 :
610 2325 : id_phi = squant_fx( round_fx( L_abs( phi ) ) /* Q6 */, &phi_hat_16 /* Q6 */, cb_azi_chan_16fx, shr( n, 1 ) );
611 2325 : *phi_hat = L_deposit_h( phi_hat_16 ); // Q6 -> Q22
612 2325 : move32();
613 :
614 2325 : test();
615 2325 : IF( phi < 0 && id_phi > 0 )
616 : {
617 920 : id_phi = sub( shl( id_phi, 1 ), 1 );
618 920 : *phi_hat = L_negate( *phi_hat ); // Q22
619 920 : move32();
620 : }
621 : ELSE
622 : {
623 : // id_phi *= 2;
624 1405 : id_phi = shl( id_phi, 1 );
625 : }
626 :
627 2325 : return id_phi;
628 : }
629 :
630 :
631 : /*-----------------------------------------------------------------------*
632 : * quantize_phi_chan_compand()
633 : *
634 : * Quantize azimuth.
635 : * Input phi expected to be an angle in degree between 0 and 360.
636 : *-----------------------------------------------------------------------*/
637 :
638 :
639 : /*! r: index azimuth */
640 117078 : Word16 quantize_phi_chan_compand_fx(
641 : Word32 phi, /* i : azimuth value Q22 */
642 : Word32 *phi_hat, /* o : quantized azimuth Q22 */
643 : const Word16 n, /* i : azimuth codebook size */
644 : const Word16 theta_flag, /* i : flag signaling high elevation */
645 : const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */
646 : )
647 : {
648 : Word16 id_phi;
649 : Word32 delta_phi; // Q22
650 : Word16 tmp_e;
651 :
652 117078 : IF( LE_16( n, 1 ) )
653 : {
654 0 : *phi_hat = 0;
655 0 : move32();
656 :
657 0 : return 0;
658 : }
659 :
660 117078 : phi = companding_azimuth_fx( L_sub( phi, 180 << Q22 ), mc_format, theta_flag, 1 );
661 :
662 : /* quantize companded value */
663 : // delta_phi = 360.0f / (float) n;
664 117078 : delta_phi = BASOP_Util_Divide3232_Scale_newton( 360, n, &tmp_e );
665 117078 : delta_phi = L_shr( delta_phi, sub( 9, tmp_e ) ); // Q22
666 : // id_phi = (int16_t) round_f( ( phi / (float) delta_phi ) );
667 117078 : id_phi = BASOP_Util_Divide3232_Scale( phi, delta_phi, &tmp_e ); // Q15
668 117078 : id_phi = round_fx( L_shl( id_phi, add( tmp_e, 1 ) ) ); // Q0
669 :
670 117078 : IF( add( id_phi, shr( n, 1 ) ) < 0 )
671 : {
672 0 : id_phi = add( id_phi, 1 );
673 : }
674 117078 : IF( sub( id_phi, shr( n, 1 ) ) >= 0 )
675 : {
676 811 : id_phi = negate( shr( n, 1 ) );
677 : }
678 :
679 117078 : IF( EQ_16( id_phi, negate( add( shr( n, 1 ), ( n % 2 ) ) ) ) )
680 : {
681 933 : id_phi = add( id_phi, ( n % 2 ) );
682 : }
683 : ELSE{
684 116145 : IF( EQ_16( id_phi, add( shr( n, 1 ), ( n % 2 ) ) ) ){
685 0 : IF( n % 2 ){
686 0 : id_phi = sub( id_phi, 1 );
687 : }
688 : ELSE
689 : {
690 0 : id_phi = negate( id_phi );
691 : }
692 : }
693 : }
694 : //*phi_hat = id_phi * delta_phi;
695 117078 : *phi_hat = imult3216( delta_phi, id_phi ); // Q22
696 117078 : move32();
697 :
698 : // id_phi += ( n >> 1 );
699 117078 : id_phi = add( id_phi, shr( n, 1 ) );
700 :
701 :
702 117078 : *phi_hat = L_add( companding_azimuth_fx( *phi_hat, mc_format, theta_flag, -1 ), DEGREE_180_Q_22 ); // Q22
703 117078 : move32();
704 :
705 117078 : return id_phi;
706 : }
|