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_prot.h"
39 : #include "ivas_rom_com.h"
40 : #include "ivas_stat_enc.h"
41 : #include "wmc_auto.h"
42 : #include "prot.h"
43 :
44 :
45 : /*-----------------------------------------------------------------------*
46 : * Local function prototypes
47 : *-----------------------------------------------------------------------*/
48 :
49 : static float quantize_theta_phi( float *theta_cb, const int16_t no_th, const int16_t *no_phi_loc, const float abs_theta, int16_t *id_phi, int16_t *id_phi_remap, float *phi_hat, const float phi, const int16_t no_bits, int16_t *id_theta, float *phi_q, const int16_t remap, const MC_LS_SETUP mc_format );
50 :
51 : static float direction_distance_cp( float theta, float theta_hat, float theta_hat1, const float phi, const float phi_hat, const float phi_hat1, float *d1 );
52 :
53 : /*-------------------------------------------------------------------*
54 : * quantize_direction_frame()
55 : *
56 : *
57 : *----------------------------------------------------------------------*/
58 :
59 217725 : void quantize_direction_frame(
60 : IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */
61 : float azimuth_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES],
62 : float elevation_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES],
63 : const int16_t hrmasa_flag /* i : flag indicating high-rate MASA MD coding*/
64 : )
65 : {
66 : int16_t i, j;
67 : uint16_t idx;
68 :
69 : /* Quantize directions */
70 217725 : q_direction->not_in_2D = 0;
71 1301131 : for ( i = q_direction->cfg.start_band; i < q_direction->cfg.nbands; i++ )
72 : {
73 1083406 : idx = q_direction->band_data[i].energy_ratio_index_mod[0];
74 4916402 : for ( j = 0; j < q_direction->cfg.nblocks; j++ )
75 : {
76 3832996 : if ( azimuth_orig != NULL )
77 : {
78 3832996 : azimuth_orig[i][j] = q_direction->band_data[i].azimuth[j];
79 : }
80 :
81 3832996 : if ( elevation_orig != NULL )
82 : {
83 3832996 : elevation_orig[i][j] = q_direction->band_data[i].elevation[j];
84 : }
85 :
86 : /* requantize the direction */
87 7665992 : q_direction->band_data[i].spherical_index[j] = quantize_direction( q_direction->band_data[i].elevation[j],
88 3832996 : q_direction->band_data[i].azimuth[j],
89 3832996 : q_direction->band_data[i].bits_sph_idx[j],
90 3832996 : &q_direction->band_data[i].elevation[j],
91 3832996 : &q_direction->band_data[i].azimuth[j], &q_direction->band_data[i].elevation_index[j],
92 3832996 : &q_direction->band_data[i].azimuth_index[j],
93 : q_direction->cfg.mc_ls_setup );
94 :
95 3832996 : q_direction->not_in_2D += q_direction->band_data[i].elevation_index[j];
96 :
97 3832996 : if ( hrmasa_flag )
98 : {
99 158082 : if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID )
100 : {
101 0 : q_direction->band_data[i].elevation_m_alphabet[j] = no_theta_masa[bits_direction_masa[0] - 3];
102 0 : q_direction->band_data[i].azimuth_m_alphabet[j] = no_phi_masa[bits_direction_masa[0] - 1][q_direction->band_data[i].elevation_index[j]];
103 : }
104 : else
105 : {
106 158082 : q_direction->band_data[i].elevation_m_alphabet[j] = no_theta_masa[bits_direction_masa[0] - 3] * 2 - 1;
107 158082 : q_direction->band_data[i].azimuth_m_alphabet[j] = no_phi_masa[bits_direction_masa[0] - 1][( q_direction->band_data[i].elevation_index[j] + 1 ) >> 1];
108 : }
109 : }
110 : else
111 : {
112 3674914 : if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID )
113 : {
114 25889 : q_direction->band_data[i].elevation_m_alphabet[j] = no_theta_masa[bits_direction_masa[idx] - 3];
115 25889 : q_direction->band_data[i].azimuth_m_alphabet[j] = no_phi_masa[bits_direction_masa[idx] - 1][q_direction->band_data[i].elevation_index[j]];
116 : }
117 : else
118 : {
119 3649025 : q_direction->band_data[i].elevation_m_alphabet[j] = no_theta_masa[bits_direction_masa[idx] - 3] * 2 - 1;
120 3649025 : q_direction->band_data[i].azimuth_m_alphabet[j] = no_phi_masa[bits_direction_masa[idx] - 1][( q_direction->band_data[i].elevation_index[j] + 1 ) >> 1];
121 : }
122 : }
123 :
124 3832996 : if ( q_direction->band_data[i].azimuth_index[j] == MASA_NO_INDEX )
125 : {
126 3067 : q_direction->band_data[i].azimuth_index[j] = 0;
127 : }
128 :
129 3832996 : if ( q_direction->band_data[i].bits_sph_idx[j] <= 2 )
130 : {
131 0 : q_direction->band_data[i].elevation_index[j] = 0;
132 : }
133 : else
134 : {
135 3832996 : if ( q_direction->cfg.mc_ls_setup == MC_LS_SETUP_INVALID )
136 : {
137 : /*deorder elevation indexing*/
138 3807107 : if ( ( q_direction->band_data[i].elevation_index[j] & 1 ) != 0 )
139 : {
140 722999 : q_direction->band_data[i].elevation_index[j] = ( ( q_direction->band_data[i].elevation_index[j] + 1 ) >> 1 ) + ( q_direction->band_data[i].elevation_m_alphabet[j] >> 1 );
141 : }
142 : else
143 : {
144 3084108 : q_direction->band_data[i].elevation_index[j] = -( ( q_direction->band_data[i].elevation_index[j] ) >> 1 ) + ( q_direction->band_data[i].elevation_m_alphabet[j] >> 1 );
145 : }
146 : }
147 : }
148 : }
149 : }
150 :
151 217725 : if ( q_direction->not_in_2D > 0 )
152 : {
153 191512 : q_direction->not_in_2D = 1 + MASA_LIMIT_2D;
154 : }
155 :
156 217725 : return;
157 : }
158 :
159 :
160 : /*-------------------------------------------------------------------*
161 : * quantize_direction_frame2D()
162 : *
163 : *
164 : *----------------------------------------------------------------------*/
165 :
166 10150 : void quantize_direction_frame2D(
167 : IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */
168 : float azimuth_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES],
169 : float elevation_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES] )
170 : {
171 : int16_t i, j;
172 : uint16_t idx;
173 : /* Quantize directions */
174 10150 : q_direction->not_in_2D = 0;
175 54544 : for ( i = q_direction->cfg.start_band; i < q_direction->cfg.nbands; i++ )
176 : {
177 44394 : idx = q_direction->band_data[i].energy_ratio_index[0];
178 128055 : for ( j = 0; j < q_direction->cfg.nblocks; j++ )
179 : {
180 83661 : if ( azimuth_orig != NULL )
181 : {
182 83661 : azimuth_orig[i][j] = q_direction->band_data[i].azimuth[j];
183 : }
184 83661 : if ( elevation_orig != NULL )
185 : {
186 83661 : elevation_orig[i][j] = q_direction->band_data[i].elevation[j];
187 : }
188 83661 : q_direction->band_data[i].azimuth_m_alphabet[j] = no_phi_masa[bits_direction_masa[idx] - 1][0];
189 :
190 : /* requantize the direction */
191 167322 : q_direction->band_data[i].spherical_index[j] = quantize_direction2D( q_direction->band_data[i].azimuth[j],
192 83661 : q_direction->band_data[i].azimuth_m_alphabet[j],
193 83661 : &q_direction->band_data[i].azimuth[j],
194 83661 : &q_direction->band_data[i].azimuth_index[j],
195 : q_direction->cfg.mc_ls_setup );
196 :
197 83661 : q_direction->band_data[i].elevation_m_alphabet[j] = 1;
198 : }
199 : }
200 :
201 10150 : return;
202 : }
203 :
204 :
205 : /*-------------------------------------------------------------------*
206 : * small_requantize_direction_frame()
207 : *
208 : *
209 : *----------------------------------------------------------------------*/
210 :
211 7640 : void small_requantize_direction_frame(
212 : IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */
213 : float azimuth_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES],
214 : float elevation_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES],
215 : const int16_t raw_flag[MASA_MAXIMUM_CODING_SUBBANDS],
216 : int16_t bits_dir_bands[MASA_MAXIMUM_CODING_SUBBANDS],
217 : int16_t *diff )
218 : {
219 : int16_t i, j;
220 : uint16_t bits_dir[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES];
221 :
222 7640 : if ( ( *diff > 0 ) && ( q_direction->not_in_2D > 0 ) )
223 : {
224 34881 : for ( i = q_direction->cfg.start_band; i < q_direction->cfg.nbands; i++ )
225 : {
226 141445 : for ( j = 0; j < q_direction->cfg.nblocks; j++ )
227 : {
228 113156 : bits_dir[i][j] = q_direction->band_data[i].bits_sph_idx[j];
229 : }
230 : }
231 :
232 6592 : small_reduction_direction( q_direction, bits_dir, raw_flag, diff );
233 :
234 6592 : if ( *diff <= 0 )
235 : {
236 6330 : for ( i = q_direction->cfg.start_band; i < q_direction->cfg.nbands; i++ )
237 : {
238 5056 : if ( raw_flag[i] == 1 )
239 : {
240 4348 : bits_dir_bands[i] = 0;
241 21740 : for ( j = 0; j < q_direction->cfg.nblocks; j++ )
242 : {
243 17392 : bits_dir_bands[i] += bits_dir[i][j];
244 17392 : q_direction->band_data[i].bits_sph_idx[j] = bits_dir[i][j];
245 :
246 : /* requantize the direction */
247 34784 : q_direction->band_data[i].spherical_index[j] = quantize_direction(
248 17392 : elevation_orig[i][j], azimuth_orig[i][j],
249 17392 : q_direction->band_data[i].bits_sph_idx[j],
250 17392 : &q_direction->band_data[i].elevation[j], &q_direction->band_data[i].azimuth[j],
251 17392 : &q_direction->band_data[i].elevation_index[j], &q_direction->band_data[i].azimuth_index[j],
252 : q_direction->cfg.mc_ls_setup );
253 :
254 17392 : if ( q_direction->band_data[i].azimuth_index[j] == MASA_NO_INDEX )
255 : {
256 19 : q_direction->band_data[i].azimuth_index[j] = 0;
257 : }
258 : }
259 : }
260 : }
261 : }
262 : }
263 :
264 7640 : return;
265 : }
266 :
267 :
268 : /*-------------------------------------------------------------------*
269 : * quantize_direction()
270 : *
271 : *
272 : *----------------------------------------------------------------------*/
273 :
274 : /*! r: quantized spherical index */
275 3994616 : uint16_t quantize_direction(
276 : const float theta, /* i : input elevation value */
277 : float phi, /* i : input azimuth value */
278 : const int16_t no_bits, /* i : number of bits */
279 : float *theta_q, /* o : quantized elevation */
280 : float *phi_q, /* o : quantized azimuth */
281 : uint16_t *index_theta, /* o : quantized elevation index */
282 : uint16_t *index_phi, /* o : quantized azimuth index */
283 : const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */
284 : )
285 : {
286 : float abs_theta, theta_hat, phi_hat;
287 : int16_t i, sign_th;
288 : int16_t cum_n[500];
289 : int16_t id_th, id_phi;
290 : float theta_cb[MAX_NO_THETA];
291 : int16_t no_th;
292 : uint16_t idx_sph;
293 : int16_t id_phi_remap;
294 :
295 3994616 : if ( no_bits == 0 )
296 : {
297 0 : *theta_q = 0;
298 0 : *phi_q = 0;
299 0 : *index_theta = MASA_NO_INDEX;
300 0 : *index_phi = MASA_NO_INDEX;
301 0 : return 0;
302 : }
303 :
304 3994616 : if ( no_bits == 1 )
305 : {
306 0 : *theta_q = 0;
307 0 : *index_theta = MASA_NO_INDEX;
308 0 : if ( ( phi < -90 ) || ( phi > 90 ) )
309 : {
310 0 : *phi_q = -180;
311 0 : *index_phi = 1;
312 :
313 0 : return 1;
314 : }
315 : else
316 : {
317 0 : *phi_q = 0;
318 0 : *index_phi = 0;
319 :
320 0 : return 0;
321 : }
322 : }
323 :
324 3994616 : if ( no_bits == 2 )
325 : {
326 678 : *theta_q = 0;
327 678 : *index_theta = MASA_NO_INDEX;
328 678 : if ( mc_format != MC_LS_SETUP_INVALID )
329 : {
330 11 : id_phi = quantize_phi_chan_lbr( phi, &phi_hat, no_phi_masa[no_bits - 1][0] );
331 11 : phi_hat += 180;
332 11 : idx_sph = id_phi;
333 11 : *phi_q = phi_hat - 180;
334 11 : id_phi_remap = id_phi;
335 11 : *index_phi = id_phi_remap;
336 : }
337 : else
338 : {
339 667 : id_phi = quantize_phi( phi + 180, 0, &phi_hat, no_phi_masa[no_bits - 1][0] );
340 667 : idx_sph = id_phi;
341 667 : *phi_q = phi_hat - 180;
342 667 : id_phi_remap = ivas_qmetadata_reorder_generic( id_phi - ( no_phi_masa[no_bits - 1][0] >> 1 ) );
343 667 : *index_phi = id_phi_remap;
344 : }
345 :
346 678 : return idx_sph;
347 : }
348 :
349 3993938 : no_th = no_theta_masa[no_bits - 3];
350 :
351 31955114 : for ( i = 0; i < no_th; i++ )
352 : {
353 27961176 : theta_cb[i] = i * delta_theta_masa[no_bits - 3];
354 : }
355 :
356 3993938 : if ( theta_cb[i - 1] > 90 )
357 : {
358 1726395 : theta_cb[i - 1] = 90;
359 : }
360 :
361 3993938 : phi = phi + 180;
362 :
363 3993938 : if ( theta < 0 )
364 : {
365 2021317 : abs_theta = -theta;
366 2021317 : sign_th = -1;
367 : }
368 : else
369 : {
370 1972621 : abs_theta = theta;
371 1972621 : sign_th = 1;
372 : }
373 :
374 3993938 : theta_hat = quantize_theta_phi( theta_cb, no_th, no_phi_masa[no_bits - 1], abs_theta, &id_phi,
375 : &id_phi_remap, &phi_hat, phi, no_bits, &id_th, phi_q, 1, mc_format );
376 :
377 3993938 : if ( mc_format != MC_LS_SETUP_INVALID )
378 : {
379 : /* indexing only for upper hemisphere */
380 33278 : cum_n[0] = no_phi_masa[no_bits - 1][0];
381 166665 : for ( i = 1; i < no_th; i++ )
382 : {
383 133387 : cum_n[i] = cum_n[i - 1] + no_phi_masa[no_bits - 1][i];
384 : }
385 :
386 33278 : if ( id_phi < MASA_NO_INDEX )
387 : {
388 33160 : if ( id_th == 0 )
389 : {
390 4253 : idx_sph = id_phi;
391 : }
392 : else
393 : {
394 28907 : idx_sph = cum_n[id_th - 1] + id_phi;
395 : }
396 : }
397 : else
398 : {
399 118 : if ( id_th == 0 )
400 : {
401 0 : idx_sph = 0;
402 : }
403 : else
404 : {
405 118 : idx_sph = cum_n[id_th - 1];
406 : }
407 : }
408 33278 : *theta_q = theta_hat;
409 33278 : if ( theta_hat == 90 )
410 : {
411 118 : *phi_q = 0;
412 118 : id_phi = MASA_NO_INDEX;
413 : }
414 : else
415 : {
416 33160 : *phi_q = phi_hat - 180;
417 : }
418 33278 : *index_theta = id_th;
419 33278 : *index_phi = id_phi_remap;
420 : }
421 : else
422 : {
423 : /* Starting from Equator, alternating positive and negative */
424 3960660 : cum_n[0] = no_phi_masa[no_bits - 1][0];
425 27794511 : for ( i = 1; i < no_th; i++ )
426 : {
427 23833851 : cum_n[2 * i - 1] = cum_n[2 * i - 2] + no_phi_masa[no_bits - 1][i];
428 23833851 : cum_n[2 * i] = cum_n[2 * i - 1] + no_phi_masa[no_bits - 1][i];
429 : }
430 :
431 3960660 : if ( no_th > 0 )
432 : {
433 3960660 : assert( abs( cum_n[2 * ( no_th - 1 )] ) < 32768 );
434 : }
435 :
436 3960660 : if ( id_th == 0 )
437 : {
438 2097369 : if ( id_phi < MASA_NO_INDEX )
439 : {
440 2097369 : idx_sph = id_phi;
441 : }
442 : else
443 : {
444 0 : idx_sph = 0;
445 : }
446 : }
447 : else
448 : {
449 1863291 : if ( sign_th > 0 )
450 : {
451 740603 : if ( id_phi < MASA_NO_INDEX )
452 : {
453 739477 : idx_sph = cum_n[2 * id_th - 2] + id_phi;
454 : }
455 : else
456 : {
457 1126 : idx_sph = cum_n[2 * id_th - 2];
458 : }
459 :
460 740603 : id_th = 2 * id_th - 1;
461 : }
462 : else
463 : {
464 1122688 : if ( id_phi < MASA_NO_INDEX )
465 : {
466 1120584 : idx_sph = cum_n[2 * id_th - 1] + id_phi;
467 : }
468 : else
469 : {
470 2104 : idx_sph = cum_n[2 * id_th - 1];
471 : }
472 1122688 : id_th = 2 * id_th;
473 : }
474 : }
475 :
476 3960660 : *theta_q = sign_th * theta_hat;
477 3960660 : if ( theta_hat == 90 )
478 : {
479 3164 : *phi_q = 0;
480 3164 : id_phi = MASA_NO_INDEX;
481 : }
482 : else
483 : {
484 3957496 : *phi_q = phi_hat - 180;
485 : }
486 :
487 3960660 : *index_theta = id_th;
488 3960660 : *index_phi = id_phi_remap;
489 : }
490 :
491 3993938 : return idx_sph;
492 : }
493 :
494 :
495 : /*-------------------------------------------------------------------*
496 : * direction_distance_cp()
497 : *
498 : * quantization distortion calculated on the sphere
499 : *----------------------------------------------------------------------*/
500 :
501 : /*! r: distortion value */
502 2306016 : static float direction_distance_cp(
503 : float theta, /* i : elevation absolute value */
504 : float theta_hat, /* i : quantized elevation value in absolute value */
505 : float theta_hat1, /* i : quantized elevation value in absolute value */
506 : const float phi, /* i : azimuth value */
507 : const float phi_hat, /* i : quantized azimuth value */
508 : const float phi_hat1, /* i : quantized azimuth value */
509 : float *d1 )
510 : {
511 : float d, ct, st, st1, st2;
512 :
513 2306016 : theta *= PI_OVER_180;
514 2306016 : theta_hat *= PI_OVER_180;
515 2306016 : theta_hat1 *= PI_OVER_180;
516 2306016 : st = sinf( theta );
517 2306016 : ct = cosf( theta );
518 2306016 : st1 = sinf( theta_hat );
519 2306016 : st2 = sinf( theta_hat1 );
520 :
521 2306016 : d = st * st1 + ct * ( sqrtf( 1 - st1 * st1 ) ) * cosf( ( phi - phi_hat ) * PI_OVER_180 );
522 2306016 : *d1 = st * st2 + ct * ( sqrtf( 1 - st2 * st2 ) ) * cosf( ( phi - phi_hat1 ) * PI_OVER_180 );
523 :
524 2306016 : return d;
525 : }
526 :
527 :
528 : /*-------------------------------------------------------------------*
529 : * quantize_theta_phi()
530 : *
531 : * joint quantization of elevation and azimuth
532 : *----------------------------------------------------------------------*/
533 :
534 : /*! r: quantized elevation value */
535 3993938 : static float quantize_theta_phi(
536 : float *theta_cb, /* i : elevation codebook */
537 : const int16_t no_th, /* i : elevation codebook size */
538 : const int16_t *no_phi_loc, /* i : number of azimuth values for each elevation codeword*/
539 : const float abs_theta, /* i : absolute value of elevation to be quantized */
540 : int16_t *id_phi, /* o : azimuth index */
541 : int16_t *id_phi_remap, /* o : remapped azimuth index */
542 : float *phi_hat, /* o : quantized azimuth value */
543 : const float phi, /* i : input azimuth value; to be quantized */
544 : const int16_t no_bits, /* i : number of bits used for quantization */
545 : int16_t *id_theta, /* o : elevation index */
546 : float *phi_q, /* o : rotated quantized azimuth */
547 : const int16_t remap, /* i : flag for remapping */
548 : const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */
549 : )
550 : {
551 : float theta_hat, theta_hat1, phi_hat1;
552 : int16_t id_th, id_th1, id_th2, id_ph, id_ph1;
553 : float d, d1;
554 :
555 3993938 : id_th = (int16_t) ( abs_theta / delta_theta_masa[no_bits - 3] );
556 3993938 : if ( id_th >= no_th )
557 : {
558 6 : id_th = no_th - 1;
559 : }
560 3993938 : theta_hat = theta_cb[id_th];
561 3993938 : if ( id_th < no_th - 1 )
562 : {
563 3763876 : id_th += squant( abs_theta, &theta_hat, &theta_cb[id_th], 2 );
564 : }
565 :
566 3993938 : if ( no_th > 1 )
567 : {
568 3993938 : if ( ( no_th < 6 ) && mc_format == MC_LS_SETUP_INVALID )
569 : {
570 2336237 : if ( id_th == 0 )
571 : {
572 1294002 : id_th1 = 1;
573 : }
574 1042235 : else if ( id_th == no_th - 1 )
575 : {
576 570314 : id_th1 = no_th - 2;
577 : }
578 : else
579 : {
580 471921 : id_th1 = id_th - 1;
581 471921 : id_th2 = id_th + 1;
582 :
583 471921 : if ( fabsf( abs_theta - theta_cb[id_th1] ) > fabsf( abs_theta - theta_cb[id_th2] ) )
584 : {
585 167424 : id_th1 = id_th2;
586 : }
587 : }
588 : }
589 : else
590 : {
591 1657701 : id_th1 = id_th;
592 : }
593 :
594 3993938 : if ( no_phi_loc[id_th] > 1 )
595 : {
596 : /* Note: (id_th % 2 == 1) must be equal to id_th % 2 */
597 3990590 : if ( mc_format != MC_LS_SETUP_INVALID )
598 : {
599 33160 : id_ph = quantize_phi_chan_compand( phi, phi_hat, no_phi_loc[id_th], ( theta_cb[id_th] > MC_MASA_THR_ELEVATION ), mc_format );
600 33160 : *id_phi_remap = id_ph;
601 : }
602 : else
603 : {
604 3957430 : id_ph = quantize_phi( phi, ( id_th % 2 == 1 ), phi_hat, no_phi_loc[id_th] );
605 : }
606 : }
607 : else
608 : {
609 3348 : id_ph = MASA_NO_INDEX;
610 3348 : *id_phi_remap = MASA_NO_INDEX;
611 3348 : *phi_hat = 180;
612 3348 : *phi_q = 0;
613 : }
614 :
615 3993938 : if ( ( no_phi_loc[id_th1] > 1 ) && ( id_ph < MASA_NO_INDEX ) && ( no_th < 6 ) && ( mc_format == MC_LS_SETUP_INVALID ) )
616 : {
617 2306016 : theta_hat1 = theta_cb[id_th1];
618 :
619 2306016 : id_ph1 = quantize_phi( phi, ( id_th1 % 2 == 1 ), &phi_hat1, no_phi_loc[id_th1] );
620 :
621 2306016 : d = direction_distance_cp( abs_theta, theta_hat, theta_hat1, phi, *phi_hat, phi_hat1, &d1 );
622 :
623 2306016 : if ( d1 > d )
624 : {
625 238130 : *phi_hat = phi_hat1;
626 238130 : id_ph = id_ph1;
627 238130 : theta_hat = theta_cb[id_th1];
628 238130 : id_th = id_th1;
629 : }
630 : }
631 : }
632 : else
633 : {
634 0 : if ( mc_format != MC_LS_SETUP_INVALID )
635 : {
636 0 : id_ph = quantize_phi_chan_compand( phi, phi_hat, no_phi_loc[id_th], 0, mc_format );
637 0 : *id_phi_remap = id_ph;
638 : }
639 : else
640 : {
641 0 : id_ph = quantize_phi( phi, ( id_th % 2 == 1 ), phi_hat, no_phi_loc[id_th] );
642 : }
643 : }
644 :
645 3993938 : if ( remap )
646 : {
647 3993938 : if ( id_ph < MASA_NO_INDEX )
648 : {
649 3990590 : *id_phi_remap = ivas_qmetadata_reorder_generic( id_ph - ( no_phi_loc[id_th] >> 1 ) );
650 : }
651 : }
652 : else
653 : {
654 0 : *id_phi_remap = id_ph;
655 : }
656 :
657 3993938 : *id_phi = id_ph;
658 3993938 : *id_theta = id_th;
659 :
660 3993938 : return theta_hat;
661 : }
|