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 <stdint.h>
34 : #include "options.h"
35 : #include <math.h>
36 : #ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG
37 : #include <string.h>
38 : #endif
39 : #include "ivas_prot.h"
40 : #include "prot.h"
41 : #include "isar_rom_post_rend.h"
42 : #include "lib_isar_pre_rend.h"
43 : #include "isar_prot.h"
44 : #ifdef DEBUGGING
45 : #include "debug.h"
46 : #endif
47 : #include "wmc_auto.h"
48 : #ifdef DBG_WAV_WRITER
49 : #include "string.h"
50 : #endif
51 :
52 : /*---------------------------------------------------------------------*
53 : * Local function declarations
54 : *---------------------------------------------------------------------*/
55 :
56 : static void isar_SplitRenderer_GetRotMd( ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, float Cldfb_RealBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const int16_t low_res, const int16_t ro_md_flag );
57 :
58 :
59 : /*-------------------------------------------------------------------------
60 : * Local functions
61 : *
62 : *
63 : *------------------------------------------------------------------------*/
64 :
65 0 : static void isar_calc_mat_det_2by2_complex(
66 : float in_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
67 : float in_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
68 : float *det_re,
69 : float *det_im )
70 : {
71 : float re1, im1, re2, im2;
72 :
73 0 : IVAS_CMULT_FLOAT( in_re[0][0], in_im[0][0], in_re[1][1], in_im[1][1], re1, im1 );
74 0 : IVAS_CMULT_FLOAT( in_re[0][1], in_im[0][1], in_re[1][0], in_im[1][0], re2, im2 );
75 0 : *det_re = re1 - re2;
76 0 : *det_im = im1 - im2;
77 :
78 0 : return;
79 : }
80 :
81 :
82 0 : static int16_t isar_is_mat_inv_2by2_complex(
83 : float in_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
84 : float in_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
85 : {
86 0 : int16_t is_det_zero = 1;
87 : float det, det_re, det_im;
88 :
89 0 : isar_calc_mat_det_2by2_complex( in_re, in_im, &det_re, &det_im );
90 :
91 0 : det = ( ( det_re * det_re ) + ( det_im * det_im ) );
92 :
93 0 : if ( det < EPSILON )
94 : {
95 0 : is_det_zero = 0;
96 : }
97 :
98 0 : return is_det_zero;
99 : }
100 :
101 :
102 0 : static void isar_calc_mat_inv_2by2_complex(
103 : float in_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
104 : float in_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
105 : float out_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
106 : float out_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
107 : {
108 : float det_re, det_im;
109 : float re, im, det;
110 :
111 0 : isar_calc_mat_det_2by2_complex( in_re, in_im, &det_re, &det_im );
112 :
113 0 : det = ( det_re * det_re ) + ( det_im * det_im );
114 :
115 : #ifdef DEBUGGING
116 : /* assert to catch cases when input is singular matrix */
117 : assert( det > 0 );
118 : #endif
119 0 : det = 1 / det;
120 :
121 0 : IVAS_CMULT_FLOAT( det_re, -det_im, in_re[1][1], in_im[1][1], re, im );
122 0 : out_re[0][0] = re * det;
123 0 : out_im[0][0] = im * det;
124 :
125 0 : IVAS_CMULT_FLOAT( det_re, -det_im, in_re[0][1], in_im[0][1], re, im );
126 0 : out_re[0][1] = -re * det;
127 0 : out_im[0][1] = -im * det;
128 :
129 0 : IVAS_CMULT_FLOAT( det_re, -det_im, in_re[1][0], in_im[1][0], re, im );
130 0 : out_re[1][0] = -re * det;
131 0 : out_im[1][0] = -im * det;
132 :
133 0 : IVAS_CMULT_FLOAT( det_re, -det_im, in_re[0][0], in_im[0][0], re, im );
134 0 : out_re[1][1] = re * det;
135 0 : out_im[1][1] = im * det;
136 :
137 0 : return;
138 : }
139 :
140 :
141 0 : static void ComputePredMat(
142 : float cov_ii_re[][BINAURAL_CHANNELS],
143 : float cov_ii_im[][BINAURAL_CHANNELS],
144 : float cov_io_re[][BINAURAL_CHANNELS],
145 : float cov_io_im[][BINAURAL_CHANNELS],
146 : float pred_mat_re[][BINAURAL_CHANNELS],
147 : float pred_mat_im[][BINAURAL_CHANNELS],
148 : const int16_t num_chs,
149 : const int16_t real_only )
150 : {
151 : float cov_ii_local_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
152 : float cov_ii_inv_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
153 : float cov_ii_inv_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
154 : float trace_cov;
155 : int16_t i, j;
156 :
157 0 : trace_cov = 0.0f;
158 0 : for ( i = 0; i < num_chs; i++ )
159 : {
160 0 : trace_cov += cov_ii_re[i][i];
161 : }
162 :
163 0 : trace_cov = max( 0.0f, trace_cov );
164 :
165 0 : if ( trace_cov < EPSILON )
166 : {
167 0 : for ( i = 0; i < num_chs; i++ )
168 : {
169 : /* protection from cases when variance of ref channels is very small */
170 0 : set_zero( pred_mat_re[i], BINAURAL_CHANNELS );
171 0 : set_zero( pred_mat_im[i], BINAURAL_CHANNELS );
172 : }
173 0 : return;
174 : }
175 :
176 0 : for ( i = 0; i < num_chs; i++ )
177 : {
178 0 : mvr2r( cov_ii_re[i], cov_ii_local_re[i], num_chs );
179 : }
180 :
181 0 : for ( i = 0; i < num_chs; i++ )
182 : {
183 0 : cov_ii_local_re[i][i] = cov_ii_re[i][i] + ( trace_cov * 0.0001f );
184 : }
185 :
186 0 : if ( isar_is_mat_inv_2by2_complex( cov_ii_local_re, cov_ii_im ) )
187 : {
188 0 : isar_calc_mat_inv_2by2_complex( cov_ii_local_re, cov_ii_im, cov_ii_inv_re, cov_ii_inv_im );
189 0 : isar_mat_mult_2by2_complex( cov_ii_inv_re, cov_ii_inv_im, cov_io_re, cov_io_im, pred_mat_re, pred_mat_im );
190 : }
191 : else
192 : {
193 : int16_t max_var_idx;
194 0 : for ( i = 0; i < num_chs; i++ )
195 : {
196 0 : set_zero( pred_mat_re[i], BINAURAL_CHANNELS );
197 0 : set_zero( pred_mat_im[i], BINAURAL_CHANNELS );
198 : }
199 :
200 0 : max_var_idx = 0;
201 0 : if ( cov_ii_local_re[1][1] > cov_ii_local_re[0][0] )
202 : {
203 0 : max_var_idx = 1;
204 : }
205 :
206 0 : if ( cov_ii_local_re[max_var_idx][max_var_idx] > EPSILON )
207 : {
208 0 : for ( j = 0; j < num_chs; j++ )
209 : {
210 0 : pred_mat_re[max_var_idx][j] = cov_io_re[max_var_idx][j] / cov_ii_local_re[max_var_idx][max_var_idx];
211 0 : pred_mat_im[max_var_idx][j] = cov_io_im[max_var_idx][j] / cov_ii_local_re[max_var_idx][max_var_idx];
212 : }
213 : }
214 : }
215 :
216 0 : if ( real_only )
217 : {
218 0 : for ( i = 0; i < num_chs; i++ )
219 : {
220 0 : set_zero( pred_mat_im[i], BINAURAL_CHANNELS );
221 : }
222 : }
223 :
224 0 : return;
225 : }
226 :
227 :
228 0 : static void ComputePostPredCov(
229 : float cov_ii_re[][BINAURAL_CHANNELS],
230 : float cov_ii_im[][BINAURAL_CHANNELS],
231 : float pred_mat_re[][BINAURAL_CHANNELS],
232 : float pred_mat_im[][BINAURAL_CHANNELS],
233 : float postpred_cov_re[][BINAURAL_CHANNELS],
234 : const int16_t num_chs )
235 : {
236 : int16_t i, j;
237 : float dmx_mat_conj_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
238 : float dmx_mat_conj_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
239 : float temp_mat_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
240 : float temp_mat_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
241 : float postpred_cov_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
242 :
243 0 : assert( num_chs == BINAURAL_CHANNELS );
244 0 : for ( i = 0; i < num_chs; i++ )
245 : {
246 0 : for ( j = 0; j < num_chs; j++ )
247 : {
248 0 : dmx_mat_conj_re[i][j] = pred_mat_re[j][i];
249 0 : dmx_mat_conj_im[i][j] = -pred_mat_im[j][i];
250 :
251 0 : temp_mat_re[i][j] = pred_mat_re[i][j];
252 0 : temp_mat_im[i][j] = pred_mat_im[i][j];
253 : }
254 0 : set_zero( postpred_cov_re[i], BINAURAL_CHANNELS );
255 : }
256 :
257 : /* 2x2 mult */
258 0 : isar_mat_mult_2by2_complex( dmx_mat_conj_re, dmx_mat_conj_im, cov_ii_re, cov_ii_im, temp_mat_re, temp_mat_im );
259 0 : isar_mat_mult_2by2_complex( temp_mat_re, temp_mat_im, pred_mat_re, pred_mat_im, postpred_cov_re, postpred_cov_im );
260 :
261 0 : for ( i = 0; i < BINAURAL_CHANNELS; i++ )
262 : {
263 0 : for ( j = 0; j < i; j++ )
264 : {
265 0 : postpred_cov_re[i][j] = postpred_cov_re[j][i];
266 : }
267 : }
268 :
269 0 : return;
270 : }
271 :
272 :
273 0 : static void ComputeBandedCrossCov(
274 : float Cldfb_RealBuffer1[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
275 : float Cldfb_ImagBuffer1[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
276 : const int16_t ch_start_idx1,
277 : float Cldfb_RealBuffer2[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
278 : float Cldfb_ImagBuffer2[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
279 : const int16_t ch_start_idx2,
280 : float out_cov_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
281 : float out_cov_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
282 : const int16_t num_chs,
283 : const int16_t *pBand_grouping,
284 : const int16_t num_slots,
285 : const int16_t start_slot_idx,
286 : const int16_t md_band_idx,
287 : const int16_t real_only )
288 : {
289 : int16_t sf, cldfb_band_idx, ch_idx1, ch_idx2;
290 : int16_t brange[2];
291 :
292 0 : for ( ch_idx1 = 0; ch_idx1 < num_chs; ch_idx1++ )
293 : {
294 0 : set_f( out_cov_re[ch_idx1], 0.0f, num_chs );
295 0 : set_f( out_cov_im[ch_idx1], 0.0f, num_chs );
296 : }
297 :
298 0 : brange[0] = pBand_grouping[md_band_idx];
299 0 : brange[1] = pBand_grouping[md_band_idx + 1];
300 :
301 0 : for ( ch_idx1 = 0; ch_idx1 < num_chs; ch_idx1++ )
302 : {
303 0 : for ( ch_idx2 = 0; ch_idx2 < num_chs; ch_idx2++ )
304 : {
305 0 : if ( real_only == 0 )
306 : {
307 0 : for ( sf = start_slot_idx; sf < start_slot_idx + num_slots; sf++ )
308 : {
309 0 : for ( cldfb_band_idx = brange[0]; cldfb_band_idx < brange[1]; cldfb_band_idx++ )
310 : {
311 0 : out_cov_re[ch_idx1][ch_idx2] +=
312 0 : Cldfb_RealBuffer1[ch_start_idx1 + ch_idx1][sf][cldfb_band_idx] * Cldfb_RealBuffer2[ch_start_idx2 + ch_idx2][sf][cldfb_band_idx] +
313 0 : Cldfb_ImagBuffer1[ch_start_idx1 + ch_idx1][sf][cldfb_band_idx] * Cldfb_ImagBuffer2[ch_start_idx2 + ch_idx2][sf][cldfb_band_idx];
314 :
315 0 : out_cov_im[ch_idx1][ch_idx2] +=
316 0 : Cldfb_RealBuffer1[ch_start_idx1 + ch_idx1][sf][cldfb_band_idx] * Cldfb_ImagBuffer2[ch_start_idx2 + ch_idx2][sf][cldfb_band_idx] -
317 0 : Cldfb_ImagBuffer1[ch_start_idx1 + ch_idx1][sf][cldfb_band_idx] * Cldfb_RealBuffer2[ch_start_idx2 + ch_idx2][sf][cldfb_band_idx];
318 : }
319 : }
320 : }
321 : else
322 : {
323 0 : for ( sf = start_slot_idx; sf < start_slot_idx + num_slots; sf++ )
324 : {
325 0 : for ( cldfb_band_idx = brange[0]; cldfb_band_idx < brange[1]; cldfb_band_idx++ )
326 : {
327 0 : out_cov_re[ch_idx1][ch_idx2] +=
328 0 : Cldfb_RealBuffer1[ch_start_idx1 + ch_idx1][sf][cldfb_band_idx] * Cldfb_RealBuffer2[ch_start_idx2 + ch_idx2][sf][cldfb_band_idx] +
329 0 : Cldfb_ImagBuffer1[ch_start_idx1 + ch_idx1][sf][cldfb_band_idx] * Cldfb_ImagBuffer2[ch_start_idx2 + ch_idx2][sf][cldfb_band_idx];
330 :
331 0 : out_cov_im[ch_idx1][ch_idx2] = 0.0f;
332 : }
333 : }
334 : }
335 : }
336 : }
337 :
338 0 : return;
339 : }
340 :
341 :
342 0 : static void ComputeBandedCov(
343 : float Cldfb_RealBuffer[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
344 : float Cldfb_ImagBuffer[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
345 : const int16_t ch_start_idx,
346 : float out_cov_re[][BINAURAL_CHANNELS],
347 : float out_cov_im[][BINAURAL_CHANNELS],
348 : const int16_t num_chs,
349 : const int16_t *pBand_grouping,
350 : const int16_t num_slots,
351 : const int16_t start_slot_idx,
352 : const int16_t md_band_idx,
353 : const int16_t real_only )
354 : {
355 : int16_t sf, cldfb_band_idx, ch_idx1, ch_idx2;
356 : int16_t brange[2];
357 :
358 0 : for ( ch_idx1 = 0; ch_idx1 < num_chs; ch_idx1++ )
359 : {
360 0 : set_f( out_cov_re[ch_idx1], 0.0f, num_chs );
361 0 : set_f( out_cov_im[ch_idx1], 0.0f, num_chs );
362 : }
363 :
364 0 : brange[0] = pBand_grouping[md_band_idx];
365 0 : brange[1] = pBand_grouping[md_band_idx + 1];
366 :
367 0 : for ( ch_idx1 = 0; ch_idx1 < num_chs; ch_idx1++ )
368 : {
369 0 : for ( ch_idx2 = 0; ch_idx2 <= ch_idx1; ch_idx2++ )
370 : {
371 0 : if ( ( ch_idx2 != ch_idx1 ) && ( real_only == 0 ) )
372 : {
373 0 : for ( sf = start_slot_idx; sf < start_slot_idx + num_slots; sf++ )
374 : {
375 0 : for ( cldfb_band_idx = brange[0]; cldfb_band_idx < brange[1]; cldfb_band_idx++ )
376 : {
377 0 : out_cov_re[ch_idx1][ch_idx2] +=
378 0 : Cldfb_RealBuffer[ch_start_idx + ch_idx1][sf][cldfb_band_idx] * Cldfb_RealBuffer[ch_start_idx + ch_idx2][sf][cldfb_band_idx] +
379 0 : Cldfb_ImagBuffer[ch_start_idx + ch_idx1][sf][cldfb_band_idx] * Cldfb_ImagBuffer[ch_start_idx + ch_idx2][sf][cldfb_band_idx];
380 :
381 0 : out_cov_im[ch_idx1][ch_idx2] +=
382 0 : Cldfb_RealBuffer[ch_start_idx + ch_idx1][sf][cldfb_band_idx] * Cldfb_ImagBuffer[ch_start_idx + ch_idx2][sf][cldfb_band_idx] -
383 0 : Cldfb_ImagBuffer[ch_start_idx + ch_idx1][sf][cldfb_band_idx] * Cldfb_RealBuffer[ch_start_idx + ch_idx2][sf][cldfb_band_idx];
384 : }
385 : }
386 : }
387 : else
388 : {
389 0 : for ( sf = start_slot_idx; sf < start_slot_idx + num_slots; sf++ )
390 : {
391 0 : for ( cldfb_band_idx = brange[0]; cldfb_band_idx < brange[1]; cldfb_band_idx++ )
392 : {
393 0 : out_cov_re[ch_idx1][ch_idx2] +=
394 0 : Cldfb_RealBuffer[ch_start_idx + ch_idx1][sf][cldfb_band_idx] * Cldfb_RealBuffer[ch_start_idx + ch_idx2][sf][cldfb_band_idx] +
395 0 : Cldfb_ImagBuffer[ch_start_idx + ch_idx1][sf][cldfb_band_idx] * Cldfb_ImagBuffer[ch_start_idx + ch_idx2][sf][cldfb_band_idx];
396 :
397 0 : out_cov_im[ch_idx1][ch_idx2] = 0.0f;
398 : }
399 : }
400 : }
401 : }
402 : }
403 :
404 0 : for ( ch_idx1 = 0; ch_idx1 < num_chs; ch_idx1++ )
405 : {
406 0 : for ( ch_idx2 = ch_idx1 + 1; ch_idx2 < num_chs; ch_idx2++ )
407 : {
408 0 : out_cov_re[ch_idx1][ch_idx2] = out_cov_re[ch_idx2][ch_idx1];
409 0 : out_cov_im[ch_idx1][ch_idx2] = -out_cov_im[ch_idx2][ch_idx1];
410 : }
411 : }
412 :
413 0 : return;
414 : }
415 :
416 :
417 0 : static float GetNormFact(
418 : float cov_ii_re[][BINAURAL_CHANNELS],
419 : float cov_ii_im[][BINAURAL_CHANNELS],
420 : float cov_io_re[][BINAURAL_CHANNELS],
421 : float cov_io_im[][BINAURAL_CHANNELS],
422 : float cov_oo_re[][BINAURAL_CHANNELS] )
423 : {
424 : int16_t i, j;
425 : float norm_fact, abs_val;
426 :
427 0 : norm_fact = 0.0f;
428 0 : for ( i = 0; i < BINAURAL_CHANNELS; i++ )
429 : {
430 0 : for ( j = 0; j < BINAURAL_CHANNELS; j++ )
431 : {
432 0 : IVAS_CALCULATE_ABS( cov_ii_re[i][j], cov_ii_im[i][j], abs_val );
433 0 : norm_fact = max( norm_fact, abs_val );
434 :
435 0 : IVAS_CALCULATE_ABS( cov_io_re[i][j], cov_io_im[i][j], abs_val );
436 0 : norm_fact = max( norm_fact, abs_val );
437 :
438 0 : IVAS_CALCULATE_RABS( cov_oo_re[i][j], abs_val );
439 0 : norm_fact = max( norm_fact, abs_val );
440 : }
441 : }
442 :
443 0 : norm_fact = ( norm_fact > EPSILON ) ? norm_fact : 1.0f;
444 :
445 0 : norm_fact = PCM16_TO_FLT_FAC / norm_fact;
446 :
447 0 : return norm_fact;
448 : }
449 :
450 :
451 0 : static void isar_split_rend_huffman_encode(
452 : isar_split_rend_huffman_cfg_t *huff_cfg,
453 : const int16_t in,
454 : int32_t *hcode,
455 : int32_t *hlen )
456 : {
457 : int32_t min_sym_val;
458 : const int32_t *codebook;
459 :
460 0 : min_sym_val = huff_cfg->codebook[0];
461 :
462 0 : codebook = &huff_cfg->codebook[3 * ( in - min_sym_val )];
463 0 : *hlen = codebook[1];
464 0 : *hcode = codebook[2];
465 :
466 0 : return;
467 : }
468 :
469 :
470 0 : static void isar_split_rend_quant_md(
471 : ISAR_BIN_HR_SPLIT_REND_MD_HANDLE hMd,
472 : const ISAR_SPLIT_REND_POSE_TYPE pose_type,
473 : const int16_t real_only,
474 : float fix_pos_rot_mat[][BINAURAL_CHANNELS],
475 : const float pred_1byquantstep )
476 : {
477 : int16_t ch1, ch2;
478 : int16_t gd_idx_min;
479 : float quant_val;
480 :
481 0 : if ( pose_type == PRED_ONLY || pose_type == PRED_ROLL_ONLY )
482 0 : {
483 : float onebyquantstep;
484 :
485 0 : onebyquantstep = pred_1byquantstep;
486 0 : if ( real_only == 1 )
487 : {
488 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
489 : {
490 0 : hMd->pred_mat_re[ch1][ch1] = hMd->pred_mat_re2[ch1];
491 : }
492 :
493 0 : hMd->pred_mat_re[1][0] = 0.0f;
494 0 : hMd->pred_mat_re[0][1] = 0.0f;
495 :
496 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
497 : {
498 0 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
499 : {
500 0 : quant_val = hMd->pred_mat_re[ch1][ch2] - ( ( ch1 == ch2 ) ? 1.0f : 0.0f );
501 0 : quant_val = min( ISAR_SPLIT_REND_PRED_MAX_VAL, max( quant_val, ISAR_SPLIT_REND_PRED_MIN_VAL ) );
502 0 : hMd->pred_mat_re_idx[ch1][ch2] = (int16_t) roundf( onebyquantstep * quant_val );
503 : }
504 : }
505 : }
506 : else
507 : {
508 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
509 : {
510 0 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
511 : {
512 0 : quant_val = hMd->pred_mat_re[ch1][ch2] - fix_pos_rot_mat[ch1][ch2];
513 0 : quant_val = min( ISAR_SPLIT_REND_PRED_MAX_VAL, max( quant_val, ISAR_SPLIT_REND_PRED_MIN_VAL ) );
514 0 : hMd->pred_mat_re_idx[ch1][ch2] = (int16_t) roundf( onebyquantstep * quant_val );
515 : }
516 : }
517 : }
518 :
519 0 : if ( real_only == 0 )
520 : {
521 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
522 : {
523 0 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
524 : {
525 0 : quant_val = min( ISAR_SPLIT_REND_PRED_MAX_VAL, max( hMd->pred_mat_im[ch1][ch2], ISAR_SPLIT_REND_PRED_MIN_VAL ) );
526 0 : hMd->pred_mat_im_idx[ch1][ch2] = (int16_t) roundf( onebyquantstep * quant_val );
527 : }
528 : }
529 : }
530 : }
531 0 : else if ( pose_type == COM_GAIN_ONLY )
532 : {
533 0 : quant_val = min( ISAR_SPLIT_REND_D_MAX_VAL, max( hMd->gd, ISAR_SPLIT_REND_D_MIN_VAL ) );
534 0 : gd_idx_min = (int16_t) roundf( ISAR_SPLIT_REND_D_1BYQ_STEP * ISAR_SPLIT_REND_D_MIN_VAL );
535 0 : hMd->gd_idx = (int16_t) roundf( ISAR_SPLIT_REND_D_1BYQ_STEP * quant_val );
536 0 : hMd->gd = hMd->gd_idx * ISAR_SPLIT_REND_D_Q_STEP;
537 0 : hMd->gd_idx = hMd->gd_idx - gd_idx_min;
538 : }
539 0 : else if ( pose_type == LR_GAIN_ONLY )
540 : {
541 0 : quant_val = min( ISAR_SPLIT_REND_PITCH_G_MAX_VAL, max( hMd->gd, ISAR_SPLIT_REND_PITCH_G_MIN_VAL ) );
542 0 : gd_idx_min = (int16_t) roundf( ISAR_SPLIT_REND_PITCH_G_1BYQ_STEP * ISAR_SPLIT_REND_PITCH_G_MIN_VAL );
543 0 : hMd->gd_idx = (int16_t) roundf( ISAR_SPLIT_REND_PITCH_G_1BYQ_STEP * quant_val );
544 0 : hMd->gd_idx = hMd->gd_idx - gd_idx_min;
545 :
546 0 : quant_val = min( ISAR_SPLIT_REND_PITCH_G_MAX_VAL, max( hMd->gd2, ISAR_SPLIT_REND_PITCH_G_MIN_VAL ) );
547 0 : hMd->gd2_idx = (int16_t) roundf( ISAR_SPLIT_REND_PITCH_G_1BYQ_STEP * quant_val );
548 0 : hMd->gd2_idx = hMd->gd2_idx - gd_idx_min;
549 : }
550 :
551 0 : return;
552 : }
553 :
554 :
555 0 : static void get_lr_gains(
556 : float cov_in[][BINAURAL_CHANNELS],
557 : float cov_out[][BINAURAL_CHANNELS],
558 : float gains[BINAURAL_CHANNELS] )
559 : {
560 : int16_t i;
561 :
562 0 : for ( i = 0; i < BINAURAL_CHANNELS; i++ )
563 : {
564 0 : gains[i] = cov_in[i][i];
565 0 : if ( gains[i] < EPSILON )
566 : {
567 0 : gains[i] = 1.0f;
568 : }
569 : else
570 : {
571 0 : gains[i] = ( cov_out[i][i] ) / gains[i];
572 0 : gains[i] = sqrtf( gains[i] );
573 : }
574 : }
575 :
576 0 : return;
577 : }
578 :
579 :
580 0 : static void ComputeCoeffs(
581 : float cov_ii_re[][BINAURAL_CHANNELS],
582 : float cov_ii_im[][BINAURAL_CHANNELS],
583 : float cov_io_re[][BINAURAL_CHANNELS],
584 : float cov_io_im[][BINAURAL_CHANNELS],
585 : float cov_oo_re[][BINAURAL_CHANNELS],
586 : ISAR_BIN_HR_SPLIT_REND_MD_HANDLE hMd,
587 : const ISAR_SPLIT_REND_POSE_TYPE pose_type,
588 : const int16_t real_only )
589 : {
590 : float postpred_cov_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
591 : float cov_ii_norm_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
592 : float cov_ii_norm_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
593 : float cov_io_norm_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
594 : float cov_io_norm_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
595 : float cov_oo_norm_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
596 : float sigma_d, gd, gd2, gl2, gr2, cov_norm_fact;
597 : int16_t i, j;
598 :
599 0 : if ( pose_type == PITCH_ONLY )
600 : {
601 : float gd_tmp[BINAURAL_CHANNELS];
602 :
603 0 : get_lr_gains( cov_ii_re, cov_oo_re, gd_tmp );
604 :
605 0 : hMd->gd = gd_tmp[0];
606 0 : hMd->gd2 = gd_tmp[1];
607 : }
608 : else
609 : {
610 0 : if ( real_only )
611 : {
612 : float gd_tmp[BINAURAL_CHANNELS];
613 :
614 0 : get_lr_gains( cov_ii_re, cov_oo_re, gd_tmp );
615 :
616 0 : for ( i = 0; i < BINAURAL_CHANNELS; i++ )
617 : {
618 0 : hMd->pred_mat_re[i][i] = gd_tmp[i];
619 0 : hMd->pred_mat_re2[i] = gd_tmp[i];
620 0 : set_zero( hMd->pred_mat_im[i], BINAURAL_CHANNELS );
621 : }
622 :
623 0 : hMd->pred_mat_re[1][0] = 0.0f;
624 0 : hMd->pred_mat_re[0][1] = 0.0f;
625 : }
626 : else
627 : {
628 0 : get_lr_gains( cov_ii_re, cov_oo_re, hMd->pred_mat_re2 );
629 :
630 0 : cov_norm_fact = GetNormFact( cov_ii_re, cov_ii_im, cov_io_re, cov_io_im, cov_oo_re );
631 :
632 : /* normalize the covariance */
633 0 : for ( i = 0; i < BINAURAL_CHANNELS; i++ )
634 : {
635 0 : for ( j = 0; j < BINAURAL_CHANNELS; j++ )
636 : {
637 0 : cov_ii_norm_re[i][j] = cov_ii_re[i][j] * cov_norm_fact;
638 0 : cov_ii_norm_im[i][j] = cov_ii_im[i][j] * cov_norm_fact;
639 0 : cov_io_norm_re[i][j] = cov_io_re[i][j] * cov_norm_fact;
640 0 : cov_io_norm_im[i][j] = cov_io_im[i][j] * cov_norm_fact;
641 0 : cov_oo_norm_re[i][j] = cov_oo_re[i][j] * cov_norm_fact;
642 : }
643 : }
644 :
645 0 : ComputePredMat( cov_ii_norm_re, cov_ii_norm_im, cov_io_norm_re, cov_io_norm_im, hMd->pred_mat_re, hMd->pred_mat_im, BINAURAL_CHANNELS, real_only );
646 :
647 0 : ComputePostPredCov( cov_ii_norm_re, cov_ii_norm_im, hMd->pred_mat_re, hMd->pred_mat_im, postpred_cov_re, BINAURAL_CHANNELS );
648 :
649 : /* normalize everything to +-1 range */
650 0 : gd = 1.0f / ( PCM16_TO_FLT_FAC );
651 0 : for ( i = 0; i < BINAURAL_CHANNELS; i++ )
652 : {
653 0 : for ( j = 0; j < BINAURAL_CHANNELS; j++ )
654 : {
655 0 : postpred_cov_re[i][j] *= gd;
656 0 : cov_ii_norm_re[i][j] = cov_ii_norm_re[i][j] * gd;
657 0 : cov_oo_norm_re[i][j] = cov_oo_norm_re[i][j] * gd;
658 : }
659 : }
660 :
661 0 : gd2 = 0.0f;
662 0 : sigma_d = 0.0f;
663 0 : hMd->gd = 0.0f;
664 :
665 0 : if ( postpred_cov_re[0][0] > EPSILON )
666 : {
667 0 : gl2 = ( cov_oo_norm_re[0][0] - ( gd2 * sigma_d ) ) / max( EPSILON, postpred_cov_re[0][0] );
668 0 : gl2 = max( gl2, 1.0f );
669 0 : gl2 = sqrtf( gl2 );
670 : }
671 : else
672 : {
673 0 : gl2 = 1.0f;
674 : }
675 :
676 0 : if ( postpred_cov_re[1][1] > EPSILON )
677 : {
678 0 : gr2 = ( cov_oo_norm_re[1][1] - ( gd2 * sigma_d ) ) / max( EPSILON, postpred_cov_re[1][1] );
679 0 : gr2 = max( gr2, 1.0f );
680 0 : gr2 = sqrtf( gr2 );
681 : }
682 : else
683 : {
684 0 : gr2 = 1.0f;
685 : }
686 :
687 0 : for ( i = 0; i < BINAURAL_CHANNELS; i++ )
688 : {
689 0 : hMd->pred_mat_re[i][0] *= gl2;
690 0 : hMd->pred_mat_re[i][1] *= gr2;
691 : }
692 :
693 0 : if ( real_only == 0 )
694 : {
695 0 : for ( i = 0; i < BINAURAL_CHANNELS; i++ )
696 : {
697 0 : hMd->pred_mat_im[i][0] *= gl2;
698 0 : hMd->pred_mat_im[i][1] *= gr2;
699 : }
700 : }
701 : }
702 : }
703 :
704 0 : return;
705 : }
706 :
707 :
708 0 : static void get_base2_bits(
709 : const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, /* i : binaural pre-renderer handle */
710 : MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */
711 : const int16_t num_subframes,
712 : const int16_t num_quant_strats,
713 : const int16_t pred_real_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
714 : const int16_t pred_imag_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
715 : int16_t pred_quant_pnts_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
716 : const int16_t d_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
717 : const int16_t bands_pitch[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
718 : const int16_t pred_real_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
719 : const int16_t pred_imag_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
720 : int32_t base2bits[ISAR_SPLIT_REND_NUM_QUANT_STRATS] )
721 : {
722 : int16_t pred_roll_bits;
723 : int16_t d_gain_bits, pitch_gain_bits, pose_idx, q;
724 : int16_t pred_yaw_bits[ISAR_SPLIT_REND_NUM_QUANT_STRATS];
725 :
726 : ISAR_SPLIT_REND_POSE_TYPE pose_type;
727 :
728 0 : for ( q = 0; q < num_quant_strats; q++ )
729 : {
730 0 : pred_yaw_bits[q] = (int16_t) ceilf( log2f( pred_quant_pnts_yaw[q] ) );
731 : }
732 0 : pred_roll_bits = (int16_t) ceilf( log2f( ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS ) );
733 :
734 0 : d_gain_bits = (int16_t) ceilf( log2f( ISAR_SPLIT_REND_D_QUANT_PNTS ) );
735 0 : pitch_gain_bits = d_gain_bits;
736 :
737 0 : for ( q = 0; q < num_quant_strats; q++ )
738 : {
739 0 : base2bits[q] = 0;
740 : }
741 :
742 0 : for ( q = 0; q < num_quant_strats; q++ )
743 : {
744 0 : for ( pose_idx = 0; pose_idx < pMultiBinPoseData->num_poses - 1; pose_idx++ )
745 : {
746 0 : pose_type = hBinHrSplitPreRend->pose_type[pose_idx];
747 0 : if ( pose_type == ANY_YAW )
748 : {
749 0 : base2bits[q] += pred_yaw_bits[q] * pred_real_bands_yaw[q] * num_subframes * BINAURAL_CHANNELS;
750 0 : base2bits[q] += pred_yaw_bits[q] * pred_imag_bands_yaw[q] * num_subframes * BINAURAL_CHANNELS;
751 0 : base2bits[q] += pred_yaw_bits[q] * pred_imag_bands_yaw[q] * num_subframes * BINAURAL_CHANNELS * BINAURAL_CHANNELS;
752 0 : base2bits[q] += d_gain_bits * d_bands_yaw[q] * num_subframes;
753 : }
754 0 : else if ( pose_type == PITCH_ONLY )
755 : {
756 0 : base2bits[q] += pitch_gain_bits * bands_pitch[q] * num_subframes;
757 0 : base2bits[q] += pitch_gain_bits * bands_pitch[q] * num_subframes;
758 : }
759 : else
760 : {
761 0 : base2bits[q] += pred_roll_bits * pred_real_bands_roll[q] * num_subframes * BINAURAL_CHANNELS;
762 0 : base2bits[q] += pred_roll_bits * pred_imag_bands_roll[q] * num_subframes * BINAURAL_CHANNELS;
763 0 : base2bits[q] += pred_roll_bits * pred_imag_bands_roll[q] * num_subframes * BINAURAL_CHANNELS * BINAURAL_CHANNELS;
764 : }
765 : }
766 : }
767 :
768 0 : return;
769 : }
770 :
771 :
772 0 : static void isar_SplitRenderer_code_md_base2(
773 : const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, /* i : binaural pre-renderer handle */
774 : MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */
775 : const int16_t num_subframes,
776 : const int16_t pred_real_bands_yaw,
777 : const int16_t pred_imag_bands_yaw,
778 : const int16_t pred_quant_pnts_yaw,
779 : const int16_t d_bands_yaw,
780 : const int16_t bands_pitch,
781 : const int16_t pred_real_bands_roll,
782 : const int16_t pred_imag_bands_roll,
783 : ISAR_SPLIT_REND_BITS_HANDLE pBits /* i/o: ISAR bits handle */
784 : )
785 : {
786 : int16_t pos_idx, b, ch1, ch2, sf_idx;
787 : int16_t min_pred_idx, min_gd_idx, min_p_gd_idx, pred_code_len, gd_code_len, p_gd_code_len, num_poses;
788 : int16_t min_pred_roll_idx, pred_roll_code_len;
789 : int16_t pred_cb_idx;
790 : int32_t code;
791 : ISAR_BIN_HR_SPLIT_REND_MD_HANDLE hMd;
792 : ISAR_BIN_HR_SPLIT_REND_HUFF_HANDLE pHuff_cfg;
793 :
794 0 : pHuff_cfg = &hBinHrSplitPreRend->huff_cfg;
795 0 : if ( pred_quant_pnts_yaw == ISAR_SPLIT_REND_PRED_63QUANT_PNTS )
796 : {
797 0 : pred_cb_idx = 1;
798 : }
799 : else
800 : {
801 0 : pred_cb_idx = 0;
802 : }
803 0 : min_pred_idx = (int16_t) pHuff_cfg->pred[pred_cb_idx].codebook[0];
804 0 : min_pred_roll_idx = (int16_t) pHuff_cfg->pred_roll.codebook[0];
805 0 : min_gd_idx = (int16_t) pHuff_cfg->gd.codebook[0];
806 0 : min_p_gd_idx = (int16_t) pHuff_cfg->p_gd.codebook[0];
807 :
808 0 : pred_code_len = pHuff_cfg->pred_base2_code_len[pred_cb_idx];
809 0 : pred_roll_code_len = pHuff_cfg->pred_roll_base2_code_len;
810 0 : gd_code_len = pHuff_cfg->gd_base2_code_len;
811 0 : p_gd_code_len = pHuff_cfg->p_gd_base2_code_len;
812 :
813 0 : num_poses = pMultiBinPoseData->num_poses;
814 :
815 0 : for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ )
816 : {
817 0 : for ( pos_idx = 0; pos_idx < num_poses - 1; pos_idx++ )
818 : {
819 0 : if ( hBinHrSplitPreRend->pose_type[pos_idx] == ANY_YAW )
820 : {
821 0 : for ( b = 0; b < pred_imag_bands_yaw; b++ )
822 : {
823 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
824 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
825 : {
826 0 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
827 : {
828 0 : code = hMd->pred_mat_re_idx[ch1][ch2] - min_pred_idx;
829 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_code_len );
830 : }
831 : }
832 :
833 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
834 : {
835 0 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
836 : {
837 0 : code = hMd->pred_mat_im_idx[ch1][ch2] - min_pred_idx;
838 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_code_len );
839 : }
840 : }
841 : }
842 :
843 0 : for ( ; b < pred_real_bands_yaw; b++ )
844 : {
845 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
846 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
847 : {
848 0 : code = hMd->pred_mat_re_idx[ch1][ch1] - min_pred_idx;
849 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_code_len );
850 : }
851 : }
852 :
853 0 : for ( b = 0; b < d_bands_yaw; b++ )
854 : {
855 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
856 0 : code = hMd->gd_idx - min_gd_idx;
857 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, gd_code_len );
858 : }
859 : }
860 0 : else if ( hBinHrSplitPreRend->pose_type[pos_idx] == PITCH_ONLY )
861 : {
862 0 : for ( b = 0; b < bands_pitch; b++ )
863 : {
864 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
865 0 : code = hMd->gd_idx - min_p_gd_idx;
866 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, p_gd_code_len );
867 :
868 0 : code = hMd->gd2_idx - min_p_gd_idx;
869 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, p_gd_code_len );
870 : }
871 : }
872 : else
873 : {
874 0 : for ( b = 0; b < pred_imag_bands_roll; b++ )
875 : {
876 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
877 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
878 : {
879 0 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
880 : {
881 0 : code = hMd->pred_mat_re_idx[ch1][ch2] - min_pred_roll_idx;
882 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_roll_code_len );
883 : }
884 : }
885 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
886 : {
887 0 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
888 : {
889 0 : code = hMd->pred_mat_im_idx[ch1][ch2] - min_pred_roll_idx;
890 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_roll_code_len );
891 : }
892 : }
893 : }
894 :
895 0 : for ( ; b < pred_real_bands_roll; b++ )
896 : {
897 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
898 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
899 : {
900 0 : code = hMd->pred_mat_re_idx[ch1][ch1] - min_pred_roll_idx;
901 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_roll_code_len );
902 : }
903 : }
904 : }
905 : }
906 : }
907 :
908 : #ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG
909 : {
910 : static int16_t num_bits = 0;
911 : static int16_t cntr = 0;
912 : float fnum_bits;
913 :
914 : cntr++;
915 :
916 : num_bits += pBits->bits_written;
917 : /* collect bits for every second */
918 : if ( cntr == 50 )
919 : {
920 : cntr = 0;
921 : fnum_bits = (float) num_bits / 1000.0f;
922 : dbgwrite_txt( &fnum_bits, 1, "split_rend_MD_bitrate.txt", "MD bitrate (kbps)" );
923 : num_bits = 0;
924 : }
925 : }
926 : #endif
927 0 : return;
928 : }
929 :
930 :
931 0 : static void isar_SplitRenderer_code_md_huff(
932 : const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, /* i : binaural pre-renderer handle */
933 : MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */
934 : const int16_t num_subframes,
935 : const int16_t pred_real_bands_yaw,
936 : const int16_t pred_imag_bands_yaw,
937 : const int16_t pred_quant_pnts_yaw,
938 : const int16_t d_bands_yaw,
939 : const int16_t bands_pitch,
940 : const int16_t pred_real_bands_roll,
941 : const int16_t pred_imag_bands_roll,
942 : ISAR_SPLIT_REND_BITS_HANDLE pBits /* i/o: ISAR bits handle */
943 : )
944 : {
945 : int16_t pos_idx, b, ch1, ch2, sf_idx, num_poses;
946 : int16_t sym_adj_idx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
947 : int16_t min_pred_idx, max_pred_idx;
948 : int16_t min_pred_roll_idx, max_pred_roll_idx, pred_cb_idx;
949 : int32_t code, len;
950 : ISAR_BIN_HR_SPLIT_REND_MD_HANDLE hMd;
951 : ISAR_BIN_HR_SPLIT_REND_HUFF_HANDLE pHuff_cfg;
952 :
953 0 : pHuff_cfg = &hBinHrSplitPreRend->huff_cfg;
954 :
955 0 : if ( pred_quant_pnts_yaw == ISAR_SPLIT_REND_PRED_63QUANT_PNTS )
956 : {
957 0 : pred_cb_idx = 1;
958 : }
959 : else
960 : {
961 0 : pred_cb_idx = 0;
962 : }
963 :
964 0 : min_pred_idx = (int16_t) pHuff_cfg->pred[pred_cb_idx].codebook[0];
965 0 : max_pred_idx = (int16_t) pHuff_cfg->pred[pred_cb_idx].codebook[( pred_quant_pnts_yaw - 1 ) * 3];
966 0 : min_pred_roll_idx = (int16_t) pHuff_cfg->pred_roll.codebook[0];
967 0 : max_pred_roll_idx = (int16_t) pHuff_cfg->pred_roll.codebook[( ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS - 1 ) * 3];
968 :
969 0 : num_poses = pMultiBinPoseData->num_poses;
970 :
971 0 : for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ )
972 : {
973 0 : for ( pos_idx = 0; pos_idx < num_poses - 1; pos_idx++ )
974 : {
975 0 : if ( hBinHrSplitPreRend->pose_type[pos_idx] == ANY_YAW )
976 : {
977 0 : for ( b = 0; b < pred_imag_bands_yaw; b++ )
978 : {
979 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
980 0 : isar_SplitRenderer_getdiagdiff( hMd->pred_mat_re_idx, sym_adj_idx, -1, min_pred_idx, max_pred_idx );
981 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
982 : {
983 0 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
984 : {
985 0 : isar_split_rend_huffman_encode( &pHuff_cfg->pred[pred_cb_idx], sym_adj_idx[ch1][ch2], &code, &len );
986 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len );
987 : }
988 : }
989 :
990 0 : isar_SplitRenderer_getdiagdiff( hMd->pred_mat_im_idx, sym_adj_idx, 1, min_pred_idx, max_pred_idx );
991 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
992 : {
993 0 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
994 : {
995 0 : isar_split_rend_huffman_encode( &pHuff_cfg->pred[pred_cb_idx], sym_adj_idx[ch1][ch2], &code, &len );
996 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len );
997 : }
998 : }
999 : }
1000 :
1001 0 : for ( ; b < pred_real_bands_yaw; b++ )
1002 : {
1003 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
1004 0 : isar_SplitRenderer_getdiagdiff( hMd->pred_mat_re_idx, sym_adj_idx, 1, min_pred_idx, max_pred_idx );
1005 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
1006 : {
1007 0 : isar_split_rend_huffman_encode( &pHuff_cfg->pred[pred_cb_idx], sym_adj_idx[ch1][ch1], &code, &len );
1008 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len );
1009 : }
1010 : }
1011 0 : for ( b = 0; b < d_bands_yaw; b++ )
1012 : {
1013 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
1014 0 : isar_split_rend_huffman_encode( &pHuff_cfg->gd, hMd->gd_idx, &code, &len );
1015 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len );
1016 : }
1017 : }
1018 0 : else if ( hBinHrSplitPreRend->pose_type[pos_idx] == PITCH_ONLY )
1019 : {
1020 0 : for ( b = 0; b < bands_pitch; b++ )
1021 : {
1022 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
1023 0 : isar_split_rend_huffman_encode( &pHuff_cfg->p_gd, hMd->gd_idx, &code, &len );
1024 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len );
1025 :
1026 0 : isar_split_rend_huffman_encode( &pHuff_cfg->p_gd, hMd->gd2_idx, &code, &len );
1027 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len );
1028 : }
1029 : }
1030 : else
1031 : {
1032 0 : for ( b = 0; b < pred_imag_bands_roll; b++ )
1033 : {
1034 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
1035 0 : isar_SplitRenderer_getdiagdiff( hMd->pred_mat_re_idx, sym_adj_idx, -1, min_pred_roll_idx, max_pred_roll_idx );
1036 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
1037 : {
1038 0 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
1039 : {
1040 0 : isar_split_rend_huffman_encode( &pHuff_cfg->pred_roll, sym_adj_idx[ch1][ch2], &code, &len );
1041 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len );
1042 : }
1043 : }
1044 :
1045 0 : isar_SplitRenderer_getdiagdiff( hMd->pred_mat_im_idx, sym_adj_idx, 1, min_pred_roll_idx, max_pred_roll_idx );
1046 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
1047 : {
1048 0 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
1049 : {
1050 0 : isar_split_rend_huffman_encode( &pHuff_cfg->pred_roll, sym_adj_idx[ch1][ch2], &code, &len );
1051 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len );
1052 : }
1053 : }
1054 : }
1055 :
1056 0 : for ( ; b < pred_real_bands_roll; b++ )
1057 : {
1058 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
1059 0 : isar_SplitRenderer_getdiagdiff( hMd->pred_mat_re_idx, sym_adj_idx, 1, min_pred_roll_idx, max_pred_roll_idx );
1060 0 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
1061 : {
1062 0 : isar_split_rend_huffman_encode( &pHuff_cfg->pred_roll, sym_adj_idx[ch1][ch1], &code, &len );
1063 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len );
1064 : }
1065 : }
1066 : }
1067 : }
1068 : }
1069 :
1070 : #ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG
1071 : {
1072 : static int16_t num_bits = 0;
1073 : static int16_t cntr = 0;
1074 : float fnum_bits;
1075 :
1076 : cntr++;
1077 : num_bits += pBits->bits_written;
1078 : /* collect bits for every second */
1079 : if ( cntr == 50 )
1080 : {
1081 : cntr = 0;
1082 : fnum_bits = (float) num_bits / 1000.0f;
1083 : dbgwrite_txt( &fnum_bits, 1, "split_rend_MD_bitrate.txt", "MD bitrate (kbps)" );
1084 : num_bits = 0;
1085 : }
1086 : }
1087 : #endif
1088 0 : return;
1089 : }
1090 :
1091 :
1092 0 : static void isar_SplitRenderer_quant_code(
1093 : const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, /* i : binaural pre-renderer handle */
1094 : const IVAS_QUATERNION headPosition, /* i : head rotation QUATERNION */
1095 : MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */
1096 : ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */
1097 : const int16_t low_res_pre_rend_rot, /* i : low time resolution pre-renderer flag */
1098 : const int16_t ro_md_flag, /* i : real only metadata for yaw flag */
1099 : const int32_t target_md_bits /* i : ISAR MD bitrate */
1100 : )
1101 : {
1102 : int16_t q, num_subframes, sf_idx, pos_idx, b, num_quant_strats;
1103 : int32_t overhead_bits, quant_strat_bits, huff_bits, start_bit;
1104 : int16_t pred_real_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], pred_real_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS];
1105 : int16_t pred_imag_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], pred_imag_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS];
1106 : int16_t d_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], bands_pitch[ISAR_SPLIT_REND_NUM_QUANT_STRATS];
1107 : int32_t base2bits[ISAR_SPLIT_REND_NUM_QUANT_STRATS];
1108 : int16_t pred_quant_pnts_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS];
1109 : float pred_1byquantstep_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS];
1110 : float pred_quantstep_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS];
1111 : ISAR_BIN_HR_SPLIT_REND_MD_HANDLE hMd;
1112 : int16_t rot_axis_code, num_bits;
1113 :
1114 0 : if ( low_res_pre_rend_rot )
1115 : {
1116 0 : num_subframes = 1;
1117 : }
1118 : else
1119 : {
1120 0 : num_subframes = MAX_PARAM_SPATIAL_SUBFRAMES;
1121 : }
1122 :
1123 0 : overhead_bits = pBits->bits_written;
1124 :
1125 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, pMultiBinPoseData->dof, ISAR_SPLIT_REND_DOF_BITS );
1126 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, pMultiBinPoseData->hq_mode, ISAR_SPLIT_REND_HQ_MODE_BITS );
1127 :
1128 0 : rot_axis_code = isar_renderSplitGetCodeFromRot_axis( pMultiBinPoseData->dof, pMultiBinPoseData->rot_axis, &num_bits );
1129 0 : if ( num_bits > 0 )
1130 : {
1131 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, (int32_t) rot_axis_code, num_bits );
1132 : }
1133 :
1134 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, (int32_t) ro_md_flag, ISAR_SPLIT_REND_RO_FLAG_BITS );
1135 :
1136 : /* code ref pose*/
1137 0 : for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ )
1138 : {
1139 : int16_t angle;
1140 : IVAS_QUATERNION head_pos_euler;
1141 :
1142 0 : Quat2EulerDegree( headPosition, &head_pos_euler.z, &head_pos_euler.y, &head_pos_euler.x );
1143 0 : angle = (int16_t) roundf( head_pos_euler.x );
1144 0 : angle += 180;
1145 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, angle, ISAR_SPLIT_REND_HEAD_POSE_BITS );
1146 :
1147 0 : angle = (int16_t) roundf( head_pos_euler.y );
1148 0 : angle += 180;
1149 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, angle, ISAR_SPLIT_REND_HEAD_POSE_BITS );
1150 :
1151 0 : angle = (int16_t) roundf( head_pos_euler.z );
1152 0 : angle += 180;
1153 :
1154 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, angle, ISAR_SPLIT_REND_HEAD_POSE_BITS );
1155 : }
1156 :
1157 0 : isar_split_rend_get_quant_params( MAX_SPLIT_REND_MD_BANDS, pred_real_bands_yaw, pred_imag_bands_yaw,
1158 : pred_quant_pnts_yaw, pred_quantstep_yaw, pred_1byquantstep_yaw,
1159 : d_bands_yaw, bands_pitch, pred_real_bands_roll, pred_imag_bands_roll, ro_md_flag, &num_quant_strats );
1160 :
1161 0 : quant_strat_bits = (int32_t) ceilf( log2f( num_quant_strats ) );
1162 :
1163 0 : overhead_bits = pBits->bits_written - overhead_bits + quant_strat_bits + 1; /* 1 for base2 vs huff */
1164 :
1165 0 : get_base2_bits( hBinHrSplitPreRend, pMultiBinPoseData, num_subframes, num_quant_strats, pred_real_bands_yaw, pred_imag_bands_yaw,
1166 : pred_quant_pnts_yaw, d_bands_yaw, bands_pitch, pred_real_bands_roll, pred_imag_bands_roll, base2bits );
1167 :
1168 0 : for ( q = 0; q < num_quant_strats; q++ )
1169 : {
1170 0 : for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ )
1171 : {
1172 0 : for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ )
1173 : {
1174 0 : if ( hBinHrSplitPreRend->pose_type[pos_idx] == ANY_YAW )
1175 : {
1176 0 : for ( b = 0; b < pred_imag_bands_yaw[q]; b++ )
1177 : {
1178 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
1179 :
1180 0 : isar_split_rend_quant_md( hMd, PRED_ONLY, 0, hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx], pred_1byquantstep_yaw[q] );
1181 : }
1182 0 : for ( ; b < pred_real_bands_yaw[q]; b++ )
1183 : {
1184 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
1185 :
1186 0 : isar_split_rend_quant_md( hMd, PRED_ONLY, 1, hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx], pred_1byquantstep_yaw[q] );
1187 : }
1188 :
1189 0 : for ( b = 0; b < d_bands_yaw[q]; b++ )
1190 : {
1191 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
1192 :
1193 0 : isar_split_rend_quant_md( hMd, COM_GAIN_ONLY, 1, hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx], 0 );
1194 : }
1195 : }
1196 0 : else if ( hBinHrSplitPreRend->pose_type[pos_idx] == PITCH_ONLY )
1197 : {
1198 0 : for ( b = 0; b < bands_pitch[q]; b++ )
1199 : {
1200 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
1201 0 : isar_split_rend_quant_md( hMd, LR_GAIN_ONLY, 1, hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx], 0 );
1202 : }
1203 : }
1204 : else
1205 : {
1206 0 : for ( b = 0; b < pred_imag_bands_roll[q]; b++ )
1207 : {
1208 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
1209 0 : isar_split_rend_quant_md( hMd, PRED_ROLL_ONLY, 0, hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx], ISAR_SPLIT_REND_PRED_ROLL_1BYQ_STEP );
1210 : }
1211 0 : for ( ; b < pred_real_bands_roll[q]; b++ )
1212 : {
1213 0 : hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
1214 0 : isar_split_rend_quant_md( hMd, PRED_ROLL_ONLY, 1, hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx], ISAR_SPLIT_REND_PRED_ROLL_1BYQ_STEP );
1215 : }
1216 : }
1217 : }
1218 : }
1219 :
1220 : /*get base2 bits and check if its within target. if yes then code with base2 to save complexity on post renderer*/
1221 0 : start_bit = pBits->bits_written;
1222 :
1223 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, 1, 1 );
1224 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, q, quant_strat_bits );
1225 :
1226 0 : huff_bits = pBits->bits_written;
1227 0 : isar_SplitRenderer_code_md_huff(
1228 : hBinHrSplitPreRend,
1229 : pMultiBinPoseData,
1230 : num_subframes,
1231 0 : pred_real_bands_yaw[q],
1232 0 : pred_imag_bands_yaw[q],
1233 0 : pred_quant_pnts_yaw[q],
1234 0 : d_bands_yaw[q],
1235 0 : bands_pitch[q],
1236 0 : pred_real_bands_roll[q],
1237 0 : pred_imag_bands_roll[q],
1238 : pBits );
1239 :
1240 0 : huff_bits = pBits->bits_written - huff_bits;
1241 :
1242 0 : if ( ( target_md_bits >= ( base2bits[q] + overhead_bits ) ) || ( target_md_bits >= ( huff_bits + overhead_bits ) ) || ( q == ( num_quant_strats - 1 ) ) )
1243 : {
1244 0 : if ( huff_bits > base2bits[q] )
1245 : {
1246 0 : pBits->bits_written = start_bit;
1247 :
1248 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0, 1 );
1249 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, q, quant_strat_bits );
1250 :
1251 0 : isar_SplitRenderer_code_md_base2( hBinHrSplitPreRend, pMultiBinPoseData, num_subframes, pred_real_bands_yaw[q], pred_imag_bands_yaw[q],
1252 0 : pred_quant_pnts_yaw[q], d_bands_yaw[q], bands_pitch[q], pred_real_bands_roll[q], pred_imag_bands_roll[q], pBits );
1253 : }
1254 0 : break;
1255 : }
1256 :
1257 0 : pBits->bits_written = start_bit;
1258 : }
1259 :
1260 : #ifdef SPLIT_MD_CODING_DEBUG
1261 : for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ )
1262 : {
1263 : int16_t val, quant_strat, ch1, ch2;
1264 : char filename[200] = "split_md_debug_indices.bin";
1265 : quant_strat = q;
1266 : for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ )
1267 : {
1268 : if ( hBinHrSplitPreRend->pose_type[pos_idx] == ANY_YAW )
1269 : {
1270 : for ( b = 0; b < pred_real_bands_yaw[quant_strat]; b++ )
1271 : {
1272 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
1273 : {
1274 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
1275 : {
1276 : val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re_idx[ch1][ch2];
1277 : dbgwrite( &val, sizeof( int16_t ), 1, 1, filename );
1278 : }
1279 : }
1280 : }
1281 : for ( b = 0; b < pred_imag_bands_yaw[quant_strat]; b++ )
1282 : {
1283 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
1284 : {
1285 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
1286 : {
1287 : val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im_idx[ch1][ch2];
1288 : dbgwrite( &val, sizeof( int16_t ), 1, 1, filename );
1289 : }
1290 : }
1291 : }
1292 : for ( b = 0; b < d_bands_yaw[quant_strat]; b++ )
1293 : {
1294 : val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd_idx;
1295 : dbgwrite( &val, sizeof( int16_t ), 1, 1, filename );
1296 : }
1297 : }
1298 : else if ( hBinHrSplitPreRend->pose_type[pos_idx] == PITCH_ONLY )
1299 : {
1300 : for ( b = 0; b < bands_pitch[quant_strat]; b++ )
1301 : {
1302 : val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd_idx;
1303 : dbgwrite( &val, sizeof( int16_t ), 1, 1, filename );
1304 : val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd2_idx;
1305 : dbgwrite( &val, sizeof( int16_t ), 1, 1, filename );
1306 : }
1307 : }
1308 : else
1309 : {
1310 : for ( b = 0; b < pred_real_bands_roll[quant_strat]; b++ )
1311 : {
1312 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
1313 : {
1314 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
1315 : {
1316 : val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re_idx[ch1][ch2];
1317 : dbgwrite( &val, sizeof( int16_t ), 1, 1, filename );
1318 : }
1319 : }
1320 : }
1321 : for ( b = 0; b < pred_imag_bands_roll[quant_strat]; b++ )
1322 : {
1323 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
1324 : {
1325 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
1326 : {
1327 : val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im_idx[ch1][ch2];
1328 : dbgwrite( &val, sizeof( int16_t ), 1, 1, filename );
1329 : }
1330 : }
1331 : }
1332 : }
1333 : }
1334 : }
1335 :
1336 : #endif
1337 0 : return;
1338 : }
1339 :
1340 :
1341 : /*-------------------------------------------------------------------------
1342 : * Function isar_SplitRenderer_GetRotMd()
1343 : *
1344 : *
1345 : *------------------------------------------------------------------------*/
1346 :
1347 0 : static void isar_SplitRenderer_GetRotMd(
1348 : ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, /* i/o: binaural renderer handle */
1349 : MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */
1350 : float Cldfb_RealBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Reference Binaural signals */
1351 : float Cldfb_ImagBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Reference Binaural signals */
1352 : const int16_t low_res,
1353 : const int16_t ro_md_flag /* i : Flag to indicate real only metadata for yaw */
1354 : )
1355 : {
1356 : float cov_ii_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
1357 : float cov_oo_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
1358 : float cov_io_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
1359 : float cov_ii_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
1360 : float cov_oo_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
1361 : float cov_io_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
1362 0 : int16_t real_only = 0;
1363 : int16_t pos_idx, b, sf_idx, start_slot_idx, num_slots, num_subframes, ch_s_idx1, ch_s_idx2;
1364 : int16_t num_md_bands, num_poses;
1365 0 : const int16_t *pBand_grouping = isar_split_rend_band_grouping;
1366 :
1367 0 : push_wmops( "isar_SplitRenderer_GetRotMd" );
1368 :
1369 0 : num_md_bands = MAX_SPLIT_REND_MD_BANDS;
1370 0 : num_poses = pMultiBinPoseData->num_poses;
1371 :
1372 0 : if ( low_res )
1373 : {
1374 0 : num_slots = CLDFB_NO_COL_MAX;
1375 0 : num_subframes = 1;
1376 : }
1377 : else
1378 : {
1379 0 : num_slots = MAX_PARAM_SPATIAL_SUBFRAMES;
1380 0 : num_subframes = MAX_PARAM_SPATIAL_SUBFRAMES;
1381 : }
1382 :
1383 : /* compute reference signal covariance */
1384 0 : for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ )
1385 : {
1386 0 : start_slot_idx = sf_idx * num_slots;
1387 0 : for ( b = 0; b < num_md_bands; b++ )
1388 : {
1389 0 : if ( ( b < SPLIT_REND_RO_MD_BAND_THRESH ) || ( !ro_md_flag && b < COMPLEX_MD_BAND_THRESH ) )
1390 : {
1391 0 : real_only = 0;
1392 : }
1393 : else
1394 : {
1395 0 : real_only = 1;
1396 : }
1397 :
1398 0 : ch_s_idx1 = 0;
1399 0 : ComputeBandedCov( Cldfb_RealBuffer_Ref_Binaural, Cldfb_ImagBuffer_Ref_Binaural, ch_s_idx1, cov_ii_re, cov_ii_im, BINAURAL_CHANNELS, pBand_grouping, num_slots, start_slot_idx, b, real_only );
1400 :
1401 : /* compute rotated signal covariance */
1402 0 : for ( pos_idx = 0; pos_idx < num_poses - 1; pos_idx++ )
1403 : {
1404 0 : if ( hBinHrSplitPreRend->pose_type[pos_idx] == ANY_ROLL )
1405 : {
1406 0 : if ( b >= SPLIT_REND_RO_MD_BAND_THRESH )
1407 : {
1408 0 : real_only = 1;
1409 : }
1410 : }
1411 0 : ch_s_idx2 = ( pos_idx + 1 ) * BINAURAL_CHANNELS;
1412 0 : ComputeBandedCrossCov( Cldfb_RealBuffer_Ref_Binaural, Cldfb_ImagBuffer_Ref_Binaural, ch_s_idx1, Cldfb_RealBuffer_Ref_Binaural, Cldfb_ImagBuffer_Ref_Binaural, ch_s_idx2, cov_io_re, cov_io_im, BINAURAL_CHANNELS, pBand_grouping, num_slots, start_slot_idx, b, real_only );
1413 :
1414 0 : ComputeBandedCov( Cldfb_RealBuffer_Ref_Binaural, Cldfb_ImagBuffer_Ref_Binaural, ch_s_idx2, cov_oo_re, cov_oo_im, BINAURAL_CHANNELS, pBand_grouping, num_slots, start_slot_idx, b, real_only );
1415 :
1416 0 : ComputeCoeffs( cov_ii_re, cov_ii_im, cov_io_re, cov_io_im, cov_oo_re, &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b], hBinHrSplitPreRend->pose_type[pos_idx], real_only );
1417 : }
1418 : }
1419 : }
1420 :
1421 0 : pop_wmops();
1422 0 : return;
1423 : }
1424 :
1425 :
1426 : /*-------------------------------------------------------------------------
1427 : * Function isar_rend_CldfbSplitPreRendProcess()
1428 : *
1429 : *
1430 : *------------------------------------------------------------------------*/
1431 :
1432 0 : void isar_rend_CldfbSplitPreRendProcess(
1433 : const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, /* i : binaural pre-renderer handle */
1434 : const IVAS_QUATERNION headPosition, /* i : head rotation QUATERNION */
1435 : MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */
1436 : float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Binaural signals, real part */
1437 : float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Binaural signals, imag. part */
1438 : ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */
1439 : const int32_t target_md_bits, /* i : ISAR MD bitrate */
1440 : const int16_t low_res_pre_rend_rot, /* i : low time resolution pre-renderer flag */
1441 : const int16_t ro_md_flag /* i : real only metadata for yaw flag */
1442 : )
1443 : {
1444 0 : push_wmops( "isar_rend_CldfbSplitPreRendProcess" );
1445 :
1446 0 : isar_SplitRenderer_GetRotMd( hBinHrSplitPreRend, pMultiBinPoseData, Cldfb_In_BinReal, Cldfb_In_BinImag, low_res_pre_rend_rot, ro_md_flag );
1447 :
1448 0 : isar_SplitRenderer_quant_code( hBinHrSplitPreRend, headPosition, pMultiBinPoseData, pBits, low_res_pre_rend_rot, ro_md_flag, target_md_bits );
1449 :
1450 : #ifdef SPLIT_POSE_CORRECTION_DEBUG
1451 : float tmpCrendBuffer[2][L_FRAME48k], quant_val, step, minv, maxv;
1452 : IVAS_QUATERNION QuaternionsPost[MAX_PARAM_SPATIAL_SUBFRAMES], head_pos_euler;
1453 : float Cldfb_RealBuffer_Binaural_5ms[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX];
1454 : float Cldfb_ImagBuffer_Binaural_5ms[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX];
1455 : int16_t sf_idx, pos_idx, b, ch1, ch2;
1456 : int32_t read_off, write_off;
1457 : for ( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ )
1458 : {
1459 : QuaternionsPost[sf_idx].w = -3.0f;
1460 : QuaternionsPost[sf_idx].x = 0.0f;
1461 : QuaternionsPost[sf_idx].y = 0.0f;
1462 : QuaternionsPost[sf_idx].z = 0.0f;
1463 : }
1464 :
1465 : hBinHrSplitPreRend->hBinHrSplitPostRend->low_Res = 1;
1466 : set_fix_rotation_mat( hBinHrSplitPreRend->hBinHrSplitPostRend->fix_pos_rot_mat, pMultiBinPoseData );
1467 : set_pose_types( hBinHrSplitPreRend->hBinHrSplitPostRend->pose_type, pMultiBinPoseData );
1468 : for ( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ )
1469 : {
1470 : Quat2EulerDegree( headPosition, &head_pos_euler.z, &head_pos_euler.y, &head_pos_euler.x );
1471 : hBinHrSplitPreRend->hBinHrSplitPostRend->QuaternionsPre[sf_idx].w = -3.0f;
1472 : hBinHrSplitPreRend->hBinHrSplitPostRend->QuaternionsPre[sf_idx].x = roundf( head_pos_euler.x );
1473 : hBinHrSplitPreRend->hBinHrSplitPostRend->QuaternionsPre[sf_idx].y = roundf( head_pos_euler.y );
1474 : hBinHrSplitPreRend->hBinHrSplitPostRend->QuaternionsPre[sf_idx].z = roundf( head_pos_euler.z );
1475 : }
1476 : for ( sf_idx = 0; sf_idx < 1; sf_idx++ )
1477 : {
1478 : for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ )
1479 : {
1480 : for ( b = 0; b < MAX_SPLIT_REND_MD_BANDS; b++ )
1481 : {
1482 : hBinHrSplitPreRend->hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b] = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b];
1483 : BIN_HR_SPLIT_REND_MD_HANDLE hMd;
1484 : hMd = &hBinHrSplitPreRend->hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b];
1485 : minv = -1.4f;
1486 : maxv = 1.4f;
1487 : step = ( maxv - minv ) / 62.0f;
1488 : if ( b >= 20 )
1489 : {
1490 : float sign;
1491 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
1492 : {
1493 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
1494 : {
1495 : sign = ( hMd->pred_mat_re[ch1][ch2] >= 0.0f ) ? 1.0f : -1.0f;
1496 : IVAS_CALCULATE_ABS( hMd->pred_mat_re[ch1][ch2], hMd->pred_mat_im[ch1][ch2], hMd->pred_mat_re[ch1][ch2] );
1497 : hMd->pred_mat_re[ch1][ch2] *= sign;
1498 : hMd->pred_mat_im[ch1][ch2] = 0.0f;
1499 : }
1500 : }
1501 : }
1502 :
1503 : for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ )
1504 : {
1505 : for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ )
1506 : {
1507 : quant_val = hMd->pred_mat_re[ch1][ch2] - hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx][ch1][ch2];
1508 : quant_val = min( maxv, max( quant_val, minv ) );
1509 : quant_val = (int16_t) roundf( quant_val / step );
1510 : hMd->pred_mat_re[ch1][ch2] = quant_val * step;
1511 : hMd->pred_mat_re[ch1][ch2] += hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx][ch1][ch2];
1512 :
1513 : quant_val = hMd->pred_mat_im[ch1][ch2];
1514 : quant_val = min( maxv, max( quant_val, minv ) );
1515 : quant_val = (int16_t) roundf( quant_val / step );
1516 : hMd->pred_mat_im[ch1][ch2] = quant_val * step;
1517 : }
1518 : }
1519 : }
1520 : }
1521 : }
1522 :
1523 : for ( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ )
1524 : {
1525 : mvr2r( (float *) Cldfb_In_BinReal[0][sf_idx * MAX_PARAM_SPATIAL_SUBFRAMES], (float *) Cldfb_RealBuffer_Binaural_5ms[0], MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX );
1526 : mvr2r( (float *) Cldfb_In_BinReal[1][sf_idx * MAX_PARAM_SPATIAL_SUBFRAMES], (float *) Cldfb_RealBuffer_Binaural_5ms[1], MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX );
1527 : mvr2r( (float *) Cldfb_In_BinImag[0][sf_idx * MAX_PARAM_SPATIAL_SUBFRAMES], (float *) Cldfb_ImagBuffer_Binaural_5ms[0], MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX );
1528 : mvr2r( (float *) Cldfb_In_BinImag[1][sf_idx * MAX_PARAM_SPATIAL_SUBFRAMES], (float *) Cldfb_ImagBuffer_Binaural_5ms[1], MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX );
1529 : isar_rend_CldfbSplitPostRendProcess( hBinHrSplitPreRend->hBinHrSplitPostRend, pMultiBinPoseData, QuaternionsPost[0], Cldfb_RealBuffer_Binaural_5ms, Cldfb_ImagBuffer_Binaural_5ms, tmpCrendBuffer, 1 );
1530 :
1531 : {
1532 : float *pOut[2];
1533 : char fname[200] = "ref_act_pos.wav";
1534 : pOut[0] = tmpCrendBuffer[0];
1535 : pOut[1] = tmpCrendBuffer[1];
1536 : dbgwrite_wav( pOut, CLDFB_NO_COL_MAX * hBinHrSplitPreRend->hBinHrSplitPostRend->cldfbSyn[0]->no_channels, fname, 48000, 2 );
1537 : }
1538 : }
1539 : #endif
1540 :
1541 0 : pop_wmops();
1542 0 : return;
1543 : }
1544 :
1545 :
1546 : /*-------------------------------------------------------------------------
1547 : * Function isar_splitBinPreRendOpen()
1548 : *
1549 : *
1550 : *------------------------------------------------------------------------*/
1551 :
1552 0 : ivas_error isar_splitBinPreRendOpen(
1553 : ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend, /* i/o: binaural pre-renderer handle */
1554 : MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData /* o : pose correction data handle */
1555 : #ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG
1556 : ,
1557 : const int32_t output_Fs
1558 : #endif
1559 : )
1560 : {
1561 : ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinRend;
1562 : #ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG
1563 : ivas_error error;
1564 : int16_t ch;
1565 : #endif
1566 : int16_t pos_idx, sf_idx, bandIdx;
1567 :
1568 0 : if ( ( hBinRend = (ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE) malloc( sizeof( ISAR_BIN_HR_SPLIT_PRE_REND ) ) ) == NULL )
1569 : {
1570 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for bin split pre renderer Module \n" ) );
1571 : }
1572 :
1573 : #ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG
1574 : for ( int16_t i = 0; i < MAX_HEAD_ROT_POSES + 1; i++ )
1575 : {
1576 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1577 : {
1578 : hBinRend->cldfbSynRotBinDec[i][ch] = NULL;
1579 : }
1580 : }
1581 :
1582 : for ( int16_t i = 0; i < MAX_HEAD_ROT_POSES + 1; i++ )
1583 : {
1584 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1585 : {
1586 : if ( ( error = openCldfb( &( hBinRend->cldfbSynRotBinDec[i][ch] ), CLDFB_SYNTHESIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK )
1587 : {
1588 : return error;
1589 : }
1590 : }
1591 : }
1592 :
1593 : #endif
1594 0 : for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ )
1595 : {
1596 0 : for ( sf_idx = 0; sf_idx < MAX_SPLIT_MD_SUBFRAMES; sf_idx++ )
1597 : {
1598 0 : for ( bandIdx = 0; bandIdx < MAX_SPLIT_REND_MD_BANDS; bandIdx++ )
1599 : {
1600 0 : hBinRend->rot_md[pos_idx][sf_idx][bandIdx].gd = 0.0f;
1601 : }
1602 : }
1603 : }
1604 :
1605 0 : set_fix_rotation_mat( hBinRend->fix_pos_rot_mat, pMultiBinPoseData );
1606 :
1607 0 : set_pose_types( hBinRend->pose_type, pMultiBinPoseData );
1608 :
1609 0 : isar_split_rend_init_huff_cfg( &hBinRend->huff_cfg );
1610 :
1611 : #ifdef SPLIT_POSE_CORRECTION_DEBUG
1612 : ivas_error error;
1613 : if ( ( error = isar_splitBinPostRendOpen( &hBinRend->hBinHrSplitPostRend, pMultiBinPoseData, 48000 ) ) != IVAS_ERR_OK )
1614 : {
1615 : return error;
1616 : }
1617 :
1618 : #endif
1619 0 : *hBinHrSplitPreRend = hBinRend;
1620 :
1621 0 : return IVAS_ERR_OK;
1622 : }
1623 :
1624 :
1625 : /*-------------------------------------------------------------------------
1626 : * Function isar_splitBinPreRendClose()
1627 : *
1628 : *
1629 : *------------------------------------------------------------------------*/
1630 :
1631 0 : void isar_splitBinPreRendClose(
1632 : ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend /* i/o: binaural pre-renderer handle */
1633 : )
1634 : {
1635 0 : if ( ( *hBinHrSplitPreRend ) != NULL )
1636 : {
1637 : #ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG
1638 : {
1639 : int16_t i, n;
1640 : for ( i = 0; i < MAX_HEAD_ROT_POSES + 1; i++ )
1641 : {
1642 : for ( n = 0; n < BINAURAL_CHANNELS; n++ )
1643 : {
1644 : if ( ( *hBinHrSplitPreRend )->cldfbSynRotBinDec[i][n] != NULL )
1645 : {
1646 : deleteCldfb( &( ( *hBinHrSplitPreRend )->cldfbSynRotBinDec[i][n] ) );
1647 : ( *hBinHrSplitPreRend )->cldfbSynRotBinDec[i][n] = NULL;
1648 : }
1649 : }
1650 : }
1651 : }
1652 : #endif
1653 : #ifdef SPLIT_POSE_CORRECTION_DEBUG
1654 : isar_splitBinPostRendClose( &( *hBinHrSplitPreRend )->hBinHrSplitPostRend );
1655 : #endif
1656 :
1657 0 : free( ( *hBinHrSplitPreRend ) );
1658 0 : ( *hBinHrSplitPreRend ) = NULL;
1659 : }
1660 :
1661 0 : return;
1662 : }
1663 :
1664 :
1665 : /*-------------------------------------------------------------------------*
1666 : * isar_set_split_rend_ht_setup()
1667 : *
1668 : *
1669 : *-------------------------------------------------------------------------*/
1670 :
1671 0 : void isar_set_split_rend_ht_setup(
1672 : SPLIT_REND_WRAPPER *hSplitrend, /* i/o: Split renderer pre-renderer handle */
1673 : IVAS_QUATERNION Quaternions[MAX_PARAM_SPATIAL_SUBFRAMES], /* i/o: External orientation in quaternions */
1674 : float Rmat[MAX_PARAM_SPATIAL_SUBFRAMES][3][3] /* o : real-space rotation matrix */
1675 : )
1676 : {
1677 : int16_t sf, i, j;
1678 :
1679 0 : if ( hSplitrend->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB )
1680 : {
1681 0 : for ( sf = 1; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1682 : {
1683 0 : Quaternions[sf] = Quaternions[0];
1684 :
1685 0 : for ( i = 0; i < 3; i++ )
1686 : {
1687 0 : for ( j = 0; j < 3; j++ )
1688 : {
1689 0 : Rmat[sf][i][j] = Rmat[0][i][j];
1690 : }
1691 : }
1692 : }
1693 : }
1694 :
1695 0 : return;
1696 : }
1697 :
1698 :
1699 : /*-------------------------------------------------------------------------
1700 : * Function isar_init_split_rend_handles()
1701 : *
1702 : *
1703 : *------------------------------------------------------------------------*/
1704 :
1705 0 : void isar_init_split_rend_handles(
1706 : SPLIT_REND_WRAPPER *hSplitRendWrapper /* i/o: Split renderer pre-renderer handle */
1707 : )
1708 : {
1709 : int16_t i;
1710 :
1711 0 : hSplitRendWrapper->hBinHrSplitPreRend = NULL;
1712 0 : hSplitRendWrapper->hCldfbHandles = NULL;
1713 0 : hSplitRendWrapper->hSplitBinLCLDEnc = NULL;
1714 0 : hSplitRendWrapper->hLc3plusEnc = NULL;
1715 :
1716 0 : for ( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; ++i )
1717 : {
1718 0 : hSplitRendWrapper->lc3plusDelayBuffers[i] = NULL;
1719 : }
1720 0 : hSplitRendWrapper->lc3plusDelaySamples = 0;
1721 :
1722 0 : isar_init_multi_bin_pose_data( &hSplitRendWrapper->multiBinPoseData );
1723 :
1724 0 : return;
1725 : }
1726 :
1727 :
1728 : /*-------------------------------------------------------------------------
1729 : * Function split_renderer_open_lc3plus()
1730 : *
1731 : *
1732 : *------------------------------------------------------------------------*/
1733 :
1734 0 : ivas_error split_renderer_open_lc3plus(
1735 : SPLIT_REND_WRAPPER *hSplitRendWrapper, /* i/o: Split renderer pre-renderer handle */
1736 : const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, /* i : Split renderer pre-renderer config */
1737 : const int32_t output_Fs, /* i : output sampling rate */
1738 : const IVAS_RENDER_FRAMESIZE isar_frame_size /* i : IVAS frame size */
1739 : )
1740 : {
1741 : ivas_error error;
1742 : int16_t i, delayBufferLength;
1743 : LC3PLUS_CONFIG config;
1744 : int16_t isar_frame_size_ms;
1745 :
1746 0 : if ( ( error = isar_framesize_to_ms( isar_frame_size, &isar_frame_size_ms ) ) != IVAS_ERR_OK )
1747 : {
1748 0 : return error;
1749 : }
1750 :
1751 : /* Check configuration validity */
1752 0 : if ( isar_frame_size_ms < pSplitRendConfig->codec_frame_size_ms )
1753 : {
1754 0 : return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "SR codec frame doesn't fit in one output frame" );
1755 : }
1756 :
1757 0 : config.lc3plus_frame_duration_us = pSplitRendConfig->codec_frame_size_ms * 1000;
1758 0 : config.samplerate = output_Fs;
1759 :
1760 0 : config.isar_frame_duration_us = isar_frame_size_ms * 1000;
1761 :
1762 0 : config.high_res_mode_enabled = ( pSplitRendConfig->lc3plus_highres != 0 );
1763 0 : config.channels = BINAURAL_CHANNELS;
1764 :
1765 0 : if ( ( error = ISAR_LC3PLUS_ENC_Open( config, isar_get_lc3plus_bitrate( pSplitRendConfig->splitRendBitRate, pSplitRendConfig->poseCorrectionMode, config.channels, config.lc3plus_frame_duration_us ), &hSplitRendWrapper->hLc3plusEnc ) ) != IVAS_ERR_OK )
1766 : {
1767 0 : return error;
1768 : }
1769 :
1770 : /* This returns delay of entire LC3plus chain (enc + dec) */
1771 0 : if ( ( error = ISAR_LC3PLUS_ENC_GetDelay( hSplitRendWrapper->hLc3plusEnc, &hSplitRendWrapper->lc3plusDelaySamples ) ) != IVAS_ERR_OK )
1772 : {
1773 0 : return error;
1774 : }
1775 :
1776 : /* Alocate buffers for delay compensation */
1777 0 : if ( pSplitRendConfig->codec == ISAR_SPLIT_REND_CODEC_LC3PLUS )
1778 : {
1779 0 : delayBufferLength = (int16_t) ( output_Fs / (int32_t) FRAMES_PER_SEC + hSplitRendWrapper->lc3plusDelaySamples );
1780 0 : for ( i = 0; i < hSplitRendWrapper->multiBinPoseData.num_poses * BINAURAL_CHANNELS; ++i )
1781 : {
1782 0 : if ( ( hSplitRendWrapper->lc3plusDelayBuffers[i] = malloc( delayBufferLength * sizeof( float ) ) ) == NULL )
1783 : {
1784 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for multiBinPoseData handle\n" ) );
1785 : }
1786 :
1787 0 : set_zero( hSplitRendWrapper->lc3plusDelayBuffers[i], delayBufferLength );
1788 : }
1789 : }
1790 : else
1791 : {
1792 : /* Delay is always expected to be exactly 2 CLDFB columns */
1793 0 : assert( hSplitRendWrapper->lc3plusDelaySamples % ( output_Fs / FRAMES_PER_SEC / CLDFB_NO_COL_MAX ) == 0 );
1794 0 : assert( hSplitRendWrapper->lc3plusDelaySamples / ( output_Fs / FRAMES_PER_SEC / CLDFB_NO_COL_MAX ) == 2 );
1795 :
1796 0 : delayBufferLength = 2 /* Columns */ * 2 /* real and imag */ * CLDFB_NO_CHANNELS_MAX;
1797 0 : for ( i = 0; i < hSplitRendWrapper->multiBinPoseData.num_poses * BINAURAL_CHANNELS; ++i )
1798 : {
1799 0 : if ( ( hSplitRendWrapper->lc3plusDelayBuffers[i] = malloc( delayBufferLength * sizeof( float ) ) ) == NULL )
1800 : {
1801 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for multiBinPoseData handle\n" ) );
1802 : }
1803 :
1804 0 : set_zero( hSplitRendWrapper->lc3plusDelayBuffers[i], delayBufferLength );
1805 : }
1806 : }
1807 :
1808 0 : return IVAS_ERR_OK;
1809 : }
1810 :
1811 :
1812 : /*-------------------------------------------------------------------------
1813 : * Function splitRendLc3plusEncodeAndWrite()
1814 : *
1815 : *
1816 : *------------------------------------------------------------------------*/
1817 :
1818 0 : ivas_error splitRendLc3plusEncodeAndWrite(
1819 : SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renderer handle */
1820 : ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */
1821 : const int32_t available_bits, /* i : available bit-budget */
1822 : float *in[] /* i/o: PCM in/out buffer */
1823 : )
1824 : {
1825 : ivas_error error;
1826 : int16_t i;
1827 : int32_t lc3plusBitstreamSize;
1828 : float *channel_ptrs[MAX_HEAD_ROT_POSES * 2];
1829 0 : assert( hSplitBin->hLc3plusEnc != NULL );
1830 :
1831 : /* Find next byte boundary and zero-pad to it */
1832 0 : while ( pBits->bits_written % 8 != 0 )
1833 : {
1834 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0L, 1 );
1835 : }
1836 :
1837 0 : for ( i = 0; i < BINAURAL_CHANNELS * hSplitBin->multiBinPoseData.num_poses; ++i )
1838 : {
1839 0 : channel_ptrs[i] = in[i];
1840 : }
1841 :
1842 0 : if ( ( error = IVAS_LC3PLUS_ENC_SetBitrate( hSplitBin->hLc3plusEnc, available_bits * FRAMES_PER_SEC ) ) != IVAS_ERR_OK )
1843 : {
1844 0 : return error;
1845 : }
1846 :
1847 0 : if ( ( error = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( hSplitBin->hLc3plusEnc, &lc3plusBitstreamSize ) ) != IVAS_ERR_OK )
1848 : {
1849 0 : return error;
1850 : }
1851 :
1852 : /* Write bitstream */
1853 0 : if ( ( error = ISAR_LC3PLUS_ENC_Encode( hSplitBin->hLc3plusEnc, channel_ptrs, &pBits->bits_buf[pBits->bits_written / 8], lc3plusBitstreamSize ) ) != IVAS_ERR_OK )
1854 : {
1855 0 : return error;
1856 : }
1857 :
1858 0 : pBits->bits_written += 8 * lc3plusBitstreamSize;
1859 0 : pBits->codec = ISAR_SPLIT_REND_CODEC_LC3PLUS;
1860 0 : pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode;
1861 0 : pBits->codec_frame_size_ms = (int16_t) ( hSplitBin->hLc3plusEnc->config.lc3plus_frame_duration_us / 1000 );
1862 0 : pBits->isar_frame_size_ms = (int16_t) ( hSplitBin->hLc3plusEnc->config.isar_frame_duration_us / 1000 );
1863 :
1864 0 : return IVAS_ERR_OK;
1865 : }
1866 :
1867 :
1868 : /*-------------------------------------------------------------------------
1869 : * Function isar_renderMultiTDBinToSplitBinaural()
1870 : *
1871 : *
1872 : *------------------------------------------------------------------------*/
1873 :
1874 0 : ivas_error isar_renderMultiTDBinToSplitBinaural(
1875 : SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renderer handle */
1876 : const IVAS_QUATERNION headPosition, /* i : head rotation QUATERNION */
1877 : const int32_t SplitRendBitRate, /* i : ISAR bitrate */
1878 : const int16_t isar_frame_size_ms, /* i : ISAR bit stream frame size in ms */
1879 : const int16_t codec_frame_size_ms, /* i : ISAR frame length in ms */
1880 : ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */
1881 : const int16_t max_bands, /* i : CLDFB bands */
1882 : float *in[], /* i/o: PCM in/out buffer */
1883 : const int16_t low_res_pre_rend_rot, /* i : low time resolution pre-renderer flag */
1884 : const int16_t pcm_out_flag, /* i : flag to indicate PCM output */
1885 : const int16_t ro_md_flag /* i : real only metadata for yaw flag */
1886 : )
1887 : {
1888 : ivas_error error;
1889 : int32_t bit_len, available_bits, target_md_bits;
1890 : int16_t num_cldfb_bands, ch, slot_idx, pos_idx, num_poses;
1891 : float Cldfb_In_BinReal[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
1892 : float Cldfb_In_BinImag[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
1893 : uint8_t useLc3plus;
1894 : float *in_delayed[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS];
1895 : int16_t i;
1896 : int32_t num_slots;
1897 :
1898 0 : push_wmops( "isar_renderMultiTDBinToSplitBinaural" );
1899 :
1900 0 : error = IVAS_ERR_OK;
1901 0 : num_poses = hSplitBin->multiBinPoseData.num_poses;
1902 :
1903 0 : useLc3plus = hSplitBin->hLc3plusEnc != NULL;
1904 :
1905 0 : if ( useLc3plus )
1906 : {
1907 : /*this should always have the time resolution of pose correction MD. Note that this does not change frame size of LC3plus*/
1908 0 : int16_t frame_size = (int16_t) ( hSplitBin->hLc3plusEnc->config.samplerate / (int32_t) FRAMES_PER_SEC );
1909 :
1910 0 : for ( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i )
1911 : {
1912 : /* Artificially delay input to head pose correction analysis by LC3plus coding delay, so that audio and metadata are in sync after decoding */
1913 0 : mvr2r( hSplitBin->lc3plusDelayBuffers[i] + frame_size, hSplitBin->lc3plusDelayBuffers[i], (int16_t) hSplitBin->lc3plusDelaySamples );
1914 0 : in_delayed[i] = hSplitBin->lc3plusDelayBuffers[i];
1915 0 : mvr2r( in[i], hSplitBin->lc3plusDelayBuffers[i] + hSplitBin->lc3plusDelaySamples, frame_size );
1916 : }
1917 : }
1918 : else
1919 : {
1920 0 : for ( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i )
1921 : {
1922 0 : in_delayed[i] = in[i];
1923 : }
1924 : }
1925 :
1926 0 : if ( ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) || ( !useLc3plus && !pcm_out_flag ) )
1927 : {
1928 0 : num_slots = ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ? CLDFB_NO_COL_MAX : ( hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations );
1929 0 : num_cldfb_bands = hSplitBin->hCldfbHandles->cldfbAna[0]->no_channels;
1930 :
1931 : /* CLDFB Analysis*/
1932 0 : for ( pos_idx = 0; pos_idx < num_poses; pos_idx++ )
1933 : {
1934 : #ifdef SPLIT_POSE_CORRECTION_DEBUG
1935 : {
1936 : float *pOut[2];
1937 : char fname[200] = "ref_out_pos";
1938 : char tag[2];
1939 : tag[0] = (char) ( '0' + pos_idx );
1940 : tag[1] = '\0';
1941 : strcat( fname, tag );
1942 : strcat( fname, ".wav" );
1943 :
1944 : pOut[0] = in_delayed[2 * pos_idx];
1945 : pOut[1] = in_delayed[2 * pos_idx + 1];
1946 : dbgwrite_wav( pOut, CLDFB_NO_COL_MAX * max_bands, fname, 48000, 2 );
1947 : }
1948 :
1949 : #endif
1950 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1951 : {
1952 0 : for ( slot_idx = 0; slot_idx < num_slots; slot_idx++ )
1953 : {
1954 0 : cldfbAnalysis_ts( &( in_delayed[pos_idx * BINAURAL_CHANNELS + ch][num_cldfb_bands * slot_idx] ),
1955 0 : Cldfb_In_BinReal[pos_idx * BINAURAL_CHANNELS + ch][slot_idx], Cldfb_In_BinImag[pos_idx * BINAURAL_CHANNELS + ch][slot_idx],
1956 0 : max_bands, hSplitBin->hCldfbHandles->cldfbAna[pos_idx * BINAURAL_CHANNELS + ch] );
1957 : }
1958 : }
1959 : }
1960 : }
1961 :
1962 0 : if ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB )
1963 : {
1964 0 : target_md_bits = isar_get_split_rend_md_target_brate( SplitRendBitRate, pcm_out_flag ) * L_FRAME48k / 48000;
1965 :
1966 0 : isar_rend_CldfbSplitPreRendProcess( hSplitBin->hBinHrSplitPreRend, headPosition, &hSplitBin->multiBinPoseData, Cldfb_In_BinReal, Cldfb_In_BinImag, pBits, target_md_bits, low_res_pre_rend_rot, ro_md_flag );
1967 : }
1968 :
1969 0 : if ( pcm_out_flag == 0 )
1970 : {
1971 0 : pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode;
1972 0 : pBits->codec = useLc3plus ? ISAR_SPLIT_REND_CODEC_LC3PLUS : ISAR_SPLIT_REND_CODEC_LCLD;
1973 :
1974 0 : if ( !useLc3plus )
1975 : {
1976 0 : available_bits = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC );
1977 0 : available_bits -= pBits->bits_written;
1978 0 : pBits->codec_frame_size_ms = codec_frame_size_ms;
1979 0 : pBits->isar_frame_size_ms = isar_frame_size_ms;
1980 :
1981 0 : isar_splitBinLCLDEncProcess( hSplitBin->hSplitBinLCLDEnc, Cldfb_In_BinReal, Cldfb_In_BinImag, available_bits, pBits );
1982 : }
1983 : else
1984 : {
1985 0 : if ( pBits->pose_correction == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE )
1986 : {
1987 0 : available_bits = isar_get_lc3plus_bitrate( SplitRendBitRate, hSplitBin->multiBinPoseData.poseCorrectionMode, hSplitBin->hLc3plusEnc->config.channels, hSplitBin->hLc3plusEnc->config.lc3plus_frame_duration_us ) / FRAMES_PER_SEC;
1988 : }
1989 : else
1990 : {
1991 0 : available_bits = ( SplitRendBitRate / FRAMES_PER_SEC ) - pBits->bits_written;
1992 : }
1993 :
1994 0 : if ( ( error = splitRendLc3plusEncodeAndWrite( hSplitBin, pBits, available_bits, in ) ) != IVAS_ERR_OK )
1995 : {
1996 0 : return error;
1997 : }
1998 : }
1999 : }
2000 : else
2001 : {
2002 0 : pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode;
2003 0 : pBits->codec = ISAR_SPLIT_REND_CODEC_NONE;
2004 : }
2005 :
2006 : /*zero pad*/
2007 0 : if ( pcm_out_flag )
2008 : {
2009 0 : bit_len = SplitRendBitRate / FRAMES_PER_SEC;
2010 : }
2011 : else
2012 : {
2013 0 : if ( !useLc3plus )
2014 : {
2015 0 : bit_len = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC );
2016 : }
2017 : else
2018 : {
2019 0 : bit_len = hSplitBin->hLc3plusEnc->config.isar_frame_duration_us / 1000;
2020 0 : bit_len = SplitRendBitRate * bit_len / 1000;
2021 : }
2022 : }
2023 :
2024 0 : while ( pBits->bits_written < bit_len )
2025 : {
2026 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0L, 1 );
2027 : }
2028 :
2029 0 : pop_wmops();
2030 :
2031 0 : return error;
2032 : }
2033 :
2034 :
2035 : /*-------------------------------------------------------------------------
2036 : * Function lc3plusTimeAlignCldfbPoseCorr()
2037 : *
2038 : *
2039 : *------------------------------------------------------------------------*/
2040 :
2041 0 : void lc3plusTimeAlignCldfbPoseCorr(
2042 : SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renderer handle */
2043 : float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: Binaural signals, real part */
2044 : float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* ii/: Binaural signals, imag. part */
2045 : )
2046 : {
2047 : float Cldfb_In_BinReal_tmp[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][2][CLDFB_NO_CHANNELS_MAX];
2048 : float Cldfb_In_BinImag_tmp[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][2][CLDFB_NO_CHANNELS_MAX];
2049 : int16_t pose, ch, slot_idx;
2050 : float *bufRead, *bufWrite;
2051 :
2052 0 : for ( pose = 0; pose < hSplitBin->multiBinPoseData.num_poses; ++pose )
2053 : {
2054 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ++ch )
2055 : {
2056 0 : bufRead = hSplitBin->lc3plusDelayBuffers[pose * BINAURAL_CHANNELS + ch];
2057 0 : bufWrite = bufRead;
2058 :
2059 : /* Save last 2 columns for next frame */
2060 0 : for ( slot_idx = 0; slot_idx < 2; ++slot_idx )
2061 : {
2062 0 : mvr2r( Cldfb_In_BinReal[pose * BINAURAL_CHANNELS + ch][CLDFB_NO_COL_MAX - 2 + slot_idx], Cldfb_In_BinReal_tmp[pose][ch][slot_idx], CLDFB_NO_CHANNELS_MAX );
2063 0 : mvr2r( Cldfb_In_BinImag[pose * BINAURAL_CHANNELS + ch][CLDFB_NO_COL_MAX - 2 + slot_idx], Cldfb_In_BinImag_tmp[pose][ch][slot_idx], CLDFB_NO_CHANNELS_MAX );
2064 : }
2065 :
2066 : /* Delay existing columns by 2 slots */
2067 0 : for ( slot_idx = CLDFB_NO_COL_MAX - 2 - 1; slot_idx >= 0; --slot_idx )
2068 : {
2069 0 : mvr2r( Cldfb_In_BinReal[pose * BINAURAL_CHANNELS + ch][slot_idx], Cldfb_In_BinReal[pose * BINAURAL_CHANNELS + ch][slot_idx + 2], CLDFB_NO_CHANNELS_MAX );
2070 0 : mvr2r( Cldfb_In_BinImag[pose * BINAURAL_CHANNELS + ch][slot_idx], Cldfb_In_BinImag[pose * BINAURAL_CHANNELS + ch][slot_idx + 2], CLDFB_NO_CHANNELS_MAX );
2071 : }
2072 :
2073 : /* Fill 2 first columns from buffer */
2074 0 : for ( slot_idx = 0; slot_idx < 2; ++slot_idx )
2075 : {
2076 0 : mvr2r( bufRead, Cldfb_In_BinReal[pose * BINAURAL_CHANNELS + ch][slot_idx], CLDFB_NO_CHANNELS_MAX );
2077 0 : bufRead += CLDFB_NO_CHANNELS_MAX;
2078 0 : mvr2r( bufRead, Cldfb_In_BinImag[pose * BINAURAL_CHANNELS + ch][slot_idx], CLDFB_NO_CHANNELS_MAX );
2079 0 : bufRead += CLDFB_NO_CHANNELS_MAX;
2080 : }
2081 :
2082 : /* Copy last 2 columns to buffer */
2083 0 : for ( slot_idx = 0; slot_idx < 2; ++slot_idx )
2084 : {
2085 0 : mvr2r( Cldfb_In_BinReal_tmp[pose][ch][slot_idx], bufWrite, CLDFB_NO_CHANNELS_MAX );
2086 0 : bufWrite += CLDFB_NO_CHANNELS_MAX;
2087 0 : mvr2r( Cldfb_In_BinImag_tmp[pose][ch][slot_idx], bufWrite, CLDFB_NO_CHANNELS_MAX );
2088 0 : bufWrite += CLDFB_NO_CHANNELS_MAX;
2089 : }
2090 : }
2091 : }
2092 :
2093 0 : return;
2094 : }
|