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