LCOV - code coverage report
Current view: top level - lib_isar - isar_splitRendererPre.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 0 649 0.0 %
Date: 2025-05-23 08:37:30 Functions: 0 26 0.0 %

          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             : }

Generated by: LCOV version 1.14