LCOV - code coverage report
Current view: top level - lib_dec - ivas_objectRenderer_internal_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ da9cc8ead0679b4682d329fdff98cf1616159273 Lines: 131 198 66.2 %
Date: 2025-10-13 22:24:20 Functions: 2 3 66.7 %

          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 "prot_fx.h"
      36             : #include "ivas_prot_rend_fx.h"
      37             : #include <math.h>
      38             : #include "ivas_rom_com.h"
      39             : #include "wmc_auto.h"
      40             : #include "ivas_prot_fx.h"
      41             : #include "debug.h"
      42             : 
      43             : 
      44             : /*---------------------------------------------------------------------*
      45             :  * ivas_td_binaural_open()
      46             :  *
      47             :  * Open and initialize TD Object binaural renderer
      48             :  *---------------------------------------------------------------------*/
      49             : 
      50         202 : ivas_error ivas_td_binaural_open_fx(
      51             :     Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure  */
      52             :     Word16 *SrcInd,          /*Temporarily used to store the updated value of SrcInd*/
      53             :     Word16 *num_src )
      54             : {
      55         202 :     *num_src = st_ivas->nchan_transport;
      56         202 :     move16();
      57             : 
      58         202 :     test();
      59         202 :     if ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) )
      60             :     {
      61         170 :         *num_src = st_ivas->nchan_ism;
      62         170 :         move16();
      63             :     }
      64             : 
      65             : #ifdef FIX_HRTF_LOAD
      66         202 :     if ( st_ivas->hHrtfTD == NULL && st_ivas->hDecoderConfig->Opt_HRTF_binary &&
      67           0 :          ( st_ivas->ivas_format != SBA_ISM_FORMAT ) // ToDo: temporary hack to avoid ASAN errors -> see issue #1202
      68             :     )
      69             :     {
      70           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "HRTF binary file present but not used in TD renderer" );
      71             :     }
      72             : 
      73             : #endif
      74         202 :     return ivas_td_binaural_open_unwrap_fx( &st_ivas->hHrtfTD, st_ivas->hDecoderConfig->output_Fs, *num_src, st_ivas->ivas_format, st_ivas->transport_config, st_ivas->hRenderConfig->directivity_fx, st_ivas->hRenderConfig->distAtt_fx, st_ivas->hTransSetup, &st_ivas->hBinRendererTd, &st_ivas->binaural_latency_ns, SrcInd );
      75             : }
      76             : 
      77             : 
      78             : /*---------------------------------------------------------------------*
      79             :  * ivas_td_binaural_renderer_sf()
      80             :  *
      81             :  * Receives the current frames for the object streams, updates metadata
      82             :  * and renders the current frame.
      83             :  *---------------------------------------------------------------------*/
      84             : 
      85       41994 : ivas_error ivas_td_binaural_renderer_sf_fx(
      86             :     Decoder_Struct *st_ivas,           /* i/o: IVAS decoder structure              */
      87             :     Word32 *output_fx[],               /* i/o: SCE channels / Binaural synthesis   Q11*/
      88             :     const Word16 n_samples_granularity /* i  : granularity of the renderer/buffer  */
      89             : )
      90             : {
      91             :     Word16 first_sf, last_sf, subframe_idx;
      92             :     Word32 *output_fx_local[BINAURAL_CHANNELS];
      93             :     Word32 reverb_signal_fx[BINAURAL_CHANNELS][L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES];
      94             :     Word32 *p_reverb_signal_fx[BINAURAL_CHANNELS];
      95             :     Word32 *tc_local_fx[MAX_TRANSPORT_CHANNELS];
      96             :     Word16 ch, slot_size, slots_to_render, output_frame, tmp;
      97             :     ivas_error error;
      98             : 
      99             :     Word16 ism_md_subframe_update_jbm;
     100             :     Word16 c_indx, nS, i;
     101             :     Word16 nchan_ism_internal, nchan_ism, ch_offset;
     102             : 
     103             :     IVAS_QUATERNION *tmp_Quaternion_fx;
     104             :     IVAS_VECTOR3 *tmp_vector_fx;
     105             :     Word16 enableCombinedOrientation;
     106             : 
     107             :     /* Set the number of ISMs */
     108       41994 :     test();
     109       41994 :     test();
     110       41994 :     IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) || ( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && GT_16( st_ivas->nchan_ism, 0 ) ) )
     111             :     {
     112         126 :         nchan_ism_internal = st_ivas->nchan_ism;
     113         126 :         move16();
     114         126 :         nchan_ism = st_ivas->nchan_ism;
     115         126 :         move16();
     116         126 :         ch_offset = 2;
     117         126 :         move16();
     118             :     }
     119       41868 :     ELSE IF( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) )
     120             :     {
     121        9250 :         nchan_ism_internal = st_ivas->nchan_ism;
     122        9250 :         move16();
     123        9250 :         nchan_ism = st_ivas->nchan_ism;
     124        9250 :         move16();
     125        9250 :         ch_offset = 0;
     126        9250 :         move16();
     127             :     }
     128             :     ELSE
     129             :     {
     130       32618 :         nchan_ism_internal = st_ivas->hTcBuffer->nchan_transport_internal;
     131       32618 :         move16();
     132       32618 :         nchan_ism = st_ivas->nchan_transport;
     133       32618 :         move16();
     134       32618 :         ch_offset = 0;
     135       32618 :         move16();
     136             :     }
     137             : 
     138             :     /* Number of subframes to delay metadata to sync with audio */
     139       41994 :     IF( st_ivas->hDecoderConfig->Opt_delay_comp )
     140             :     {
     141       41104 :         ism_md_subframe_update_jbm = s_max( 0, sub( st_ivas->hTcBuffer->nb_subframes, 3 ) );
     142             :     }
     143             :     ELSE
     144             :     {
     145         890 :         ism_md_subframe_update_jbm = sub( st_ivas->hTcBuffer->nb_subframes, 2 );
     146             :     }
     147             : 
     148       41994 :     IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
     149             :     {
     150         126 :         ism_md_subframe_update_jbm = s_max( 0, sub( st_ivas->hTcBuffer->nb_subframes, 2 ) );
     151             :     }
     152             : 
     153      125982 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
     154             :     {
     155       83988 :         p_reverb_signal_fx[ch] = reverb_signal_fx[ch];
     156             :     }
     157      172746 :     FOR( ch = 0; ch < nchan_ism_internal; ch++ )
     158             :     {
     159      130752 :         tc_local_fx[ch] = st_ivas->hTcBuffer->tc_fx[ch + ch_offset] + st_ivas->hTcBuffer->n_samples_rendered;
     160             :     }
     161             : 
     162      125982 :     FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ )
     163             :     {
     164       83988 :         output_fx_local[ch] = output_fx[ch]; // Q11
     165             :     }
     166             : 
     167       41994 :     slot_size = st_ivas->hTcBuffer->n_samples_granularity;
     168       41994 :     move16();
     169             : 
     170             :     /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */
     171       41994 :     tmp = 0;
     172       41994 :     move16();
     173       41994 :     IF( n_samples_granularity != 0 )
     174             :     {
     175       41994 :         tmp = idiv1616( n_samples_granularity, slot_size );
     176             :     }
     177       41994 :     slots_to_render = s_min( sub( st_ivas->hTcBuffer->num_slots, st_ivas->hTcBuffer->slots_rendered ), tmp );
     178       41994 :     first_sf = st_ivas->hTcBuffer->subframes_rendered;
     179       41994 :     move16();
     180       41994 :     last_sf = first_sf;
     181       41994 :     move16();
     182       41994 :     st_ivas->hTcBuffer->slots_rendered = add( st_ivas->hTcBuffer->slots_rendered, slots_to_render );
     183       41994 :     move16();
     184             : 
     185      208696 :     WHILE( slots_to_render > 0 )
     186             :     {
     187      166702 :         slots_to_render = sub( slots_to_render, st_ivas->hTcBuffer->subframe_nbslots[last_sf] );
     188      166702 :         last_sf = add( last_sf, 1 );
     189             :     }
     190             : 
     191      208696 :     FOR( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
     192             :     {
     193      166702 :         output_frame = i_mult( st_ivas->hTcBuffer->subframe_nbslots[subframe_idx], st_ivas->hTcBuffer->n_samples_granularity );
     194             : 
     195             :         /* Update object position(s) */
     196      166702 :         c_indx = 0;
     197      166702 :         move16();
     198             : 
     199      686456 :         FOR( nS = 0; nS < nchan_ism; nS++ )
     200             :         {
     201      519754 :             test();
     202      519754 :             IF( !( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_16( nS, LFE_CHANNEL ) ) ) /* Skip LFE for MC */
     203             :             {
     204      507261 :                 st_ivas->hBinRendererTd->Sources[c_indx]->InputFrame_p_fx = tc_local_fx[nS]; /* Q11 */
     205      507261 :                 st_ivas->hBinRendererTd->Sources[c_indx]->SrcRend_p->InputAvailable = TRUE;
     206      507261 :                 move16();
     207      507261 :                 c_indx = add( c_indx, 1 );
     208             :             }
     209             :         }
     210             : 
     211      166702 :         IF( EQ_16( subframe_idx, ism_md_subframe_update_jbm ) )
     212             :         {
     213             : #ifdef OBJ_EDITING_API
     214       41585 :             test();
     215       41585 :             IF( EQ_16( st_ivas->ivas_format, ISM_FORMAT ) || EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) )
     216       38350 :             {
     217             :                 ISM_METADATA_FRAME ismMetaData[MAX_NUM_OBJECTS];
     218             :                 ISM_METADATA_HANDLE hIsmMetaData[MAX_NUM_OBJECTS];
     219      148680 :                 FOR( nS = 0; nS < nchan_ism; nS++ )
     220             :                 {
     221      110330 :                     ismMetaData[nS].azimuth_fx = st_ivas->hIsmMetaData[nS]->edited_azimuth_fx;
     222      110330 :                     move32();
     223      110330 :                     ismMetaData[nS].elevation_fx = st_ivas->hIsmMetaData[nS]->edited_elevation_fx;
     224      110330 :                     move32();
     225      110330 :                     ismMetaData[nS].radius_fx = st_ivas->hIsmMetaData[nS]->edited_radius_fx;
     226      110330 :                     move16();
     227      110330 :                     ismMetaData[nS].yaw_fx = st_ivas->hIsmMetaData[nS]->edited_yaw_fx;
     228      110330 :                     move32();
     229      110330 :                     ismMetaData[nS].pitch_fx = st_ivas->hIsmMetaData[nS]->edited_pitch_fx;
     230      110330 :                     move32();
     231      110330 :                     ismMetaData[nS].non_diegetic_flag = st_ivas->hIsmMetaData[nS]->non_diegetic_flag;
     232      110330 :                     move16();
     233      110330 :                     ismMetaData[nS].gain_fx = st_ivas->hIsmMetaData[nS]->edited_gain_fx;
     234      110330 :                     move32();
     235      110330 :                     hIsmMetaData[nS] = &ismMetaData[nS];
     236             :                 }
     237             : 
     238       38350 :                 IF( NE_16( ( error = TDREND_Update_object_positions_fx( st_ivas->hBinRendererTd, nchan_ism, st_ivas->ivas_format, hIsmMetaData ) ), IVAS_ERR_OK ) )
     239             :                 {
     240           0 :                     return error;
     241             :                 }
     242             :             }
     243             :             else
     244             : #endif
     245             :             {
     246        3235 :                 IF( NE_16( error = TDREND_Update_object_positions_fx( st_ivas->hBinRendererTd, nchan_ism, st_ivas->ivas_format, st_ivas->hIsmMetaData ), IVAS_ERR_OK ) )
     247             :                 {
     248           0 :                     return error;
     249             :                 }
     250             :             }
     251             :         }
     252             : 
     253             :         /* Update the listener's location/orientation */
     254      166702 :         IF( st_ivas->hCombinedOrientationData != NULL )
     255             :         {
     256       85693 :             tmp_Quaternion_fx = &st_ivas->hCombinedOrientationData->Quaternions[st_ivas->hCombinedOrientationData->subframe_idx];
     257       85693 :             tmp_vector_fx = &st_ivas->hCombinedOrientationData->listenerPos[st_ivas->hCombinedOrientationData->subframe_idx];
     258       85693 :             enableCombinedOrientation = st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx];
     259       85693 :             move16();
     260             : 
     261             :             /* Shifting x_fx, y_fx, z_fx to the same Q-factor as Listener_p->Pos_q (usually Q25) */
     262       85693 :             Word16 pos_q = st_ivas->hBinRendererTd->Listener_p->Pos_q;
     263       85693 :             move16();
     264       85693 :             tmp_vector_fx->x_fx = L_shr( tmp_vector_fx->x_fx, sub( tmp_vector_fx->q_fact, pos_q ) );
     265       85693 :             tmp_vector_fx->y_fx = L_shr( tmp_vector_fx->y_fx, sub( tmp_vector_fx->q_fact, pos_q ) );
     266       85693 :             tmp_vector_fx->z_fx = L_shr( tmp_vector_fx->z_fx, sub( tmp_vector_fx->q_fact, pos_q ) );
     267       85693 :             tmp_vector_fx->q_fact = pos_q;
     268       85693 :             move16();
     269             :         }
     270             :         ELSE
     271             :         {
     272       81009 :             tmp_Quaternion_fx = NULL;
     273       81009 :             tmp_vector_fx = NULL;
     274       81009 :             enableCombinedOrientation = 0;
     275       81009 :             move16();
     276             :         }
     277             : 
     278      166702 :         IF( NE_32( ( error = TDREND_Update_listener_orientation_fx( st_ivas->hBinRendererTd, enableCombinedOrientation, tmp_Quaternion_fx, tmp_vector_fx ) ), IVAS_ERR_OK ) )
     279             :         {
     280           0 :             return error;
     281             :         }
     282             : 
     283      166702 :         test();
     284      166702 :         IF( st_ivas->hRenderConfig != NULL && EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
     285             :         {
     286      122347 :             FOR( i = 0; i < nchan_ism_internal; ++i )
     287             :             {
     288       98604 :                 scale_sig32( tc_local_fx[i], st_ivas->hReverb->full_block_size, -4 ); // Q11 - 4 = Q7
     289             :             }
     290             : 
     291       23743 :             IF( NE_32( ( error = ivas_reverb_process_fx( st_ivas->hReverb, st_ivas->transport_config, 0, tc_local_fx, p_reverb_signal_fx, 0 ) ), IVAS_ERR_OK ) ) // Q(p_reverb_signal_fx) = 11
     292             :             {
     293           0 :                 return error;
     294             :             }
     295             : 
     296      122347 :             FOR( i = 0; i < nchan_ism_internal; ++i )
     297             :             {
     298       98604 :                 scale_sig32( tc_local_fx[i], st_ivas->hReverb->full_block_size, 4 ); // Q7 + 4 = Q11
     299             :             }
     300             : 
     301       71229 :             FOR( i = 0; i < BINAURAL_CHANNELS; ++i )
     302             :             {
     303       47486 :                 scale_sig32( p_reverb_signal_fx[i], st_ivas->hReverb->full_block_size, 2 + 4 ); // Q5 + 6 = Q11
     304             :             }
     305             :         }
     306             : 
     307             :         /* Render subframe */
     308             :         /* ism_md_subframe_update_jbm != subframe_idx: trigger update only for ism_md_subframe_update_jbm == subframe_idx,
     309             :            where then the two TDREND_GetMix()-arguments subframe_idx and ism_md_subframe_update are equal, and we want to enforce the update inside TDREND_GetMix to use subframe_idx == 0 */
     310      166702 :         IF( NE_32( ( error = TDREND_GetMix_fx( st_ivas->hBinRendererTd, output_fx_local, output_frame, 0 ) ), IVAS_ERR_OK ) )
     311             :         {
     312           0 :             return error;
     313             :         }
     314             : 
     315      166702 :         test();
     316      166702 :         IF( st_ivas->hRenderConfig != NULL && EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
     317             :         {
     318             :             /* add reverb to rendered signals */
     319       23743 :             v_add_32( reverb_signal_fx[0], output_fx_local[0], output_fx_local[0], output_frame ); // Q11
     320       23743 :             v_add_32( reverb_signal_fx[1], output_fx_local[1], output_fx_local[1], output_frame );
     321             :         }
     322             : 
     323      686468 :         FOR( ch = 0; ch < nchan_ism_internal; ch++ )
     324             :         {
     325      519766 :             tc_local_fx[ch] += output_frame;
     326             :         }
     327             : 
     328      500106 :         FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ )
     329             :         {
     330      333404 :             output_fx_local[ch] += output_frame;
     331             :         }
     332             : 
     333             :         /* update combined orientation access index */
     334      166702 :         ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, output_frame );
     335             :     }
     336             : 
     337       41994 :     st_ivas->hTcBuffer->subframes_rendered = last_sf;
     338       41994 :     move16();
     339             : 
     340       41994 :     return IVAS_ERR_OK;
     341             : }
     342             : 
     343             : /*---------------------------------------------------------------------*
     344             :  * ivas_td_binaural_renderer_sf_splitBinaural()
     345             :  *
     346             :  * Render to multiple binaural pairs based on relative head positions for split rendering.
     347             :  *---------------------------------------------------------------------*/
     348             : 
     349           0 : ivas_error ivas_td_binaural_renderer_sf_splitBinaural(
     350             :     Decoder_Struct *st_ivas,      /* i/o: IVAS decoder structure                    */
     351             :     Word32 *output[],             /* i/o: SCE channels / Binaural synthesis         */
     352             :     const Word16 nSamplesRendered /* i  : number of samples to render               */
     353             : )
     354             : {
     355             :     Word16 i;
     356             :     Word16 pos_idx;
     357             :     IVAS_QUATERNION originalHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES];
     358             :     MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
     359             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE origTdRendHandle;
     360             :     ivas_error error;
     361             :     Word16 original_subframes_rendered;
     362             :     Word16 original_slots_rendered;
     363             :     Word32 *p_bin_output[BINAURAL_CHANNELS];
     364             :     Word32 output_local[MAX_OUTPUT_CHANNELS][L_FRAME48k];
     365             :     Word16 q_fact_orig[MAX_PARAM_SPATIAL_SUBFRAMES];
     366             : 
     367             :     Word16 SrcInd[MAX_NUM_TDREND_CHANNELS];
     368             : 
     369           0 :     pMultiBinPoseData = &st_ivas->hSplitBinRend->splitrend.multiBinPoseData;
     370           0 :     move32();
     371             : 
     372             :     /* If not yet allocated, open additional instances of TD renderer */
     373           0 :     FOR( i = 0; i < pMultiBinPoseData->num_poses - 1; ++i )
     374             :     {
     375           0 :         IF( st_ivas->hTdRendHandles[i] != NULL )
     376             :         {
     377           0 :             continue;
     378             :         }
     379           0 :         IF( ( error = ivas_td_binaural_open_unwrap_fx( &st_ivas->hHrtfTD,
     380             :                                                        st_ivas->hDecoderConfig->output_Fs,
     381             :                                                        st_ivas->nchan_transport,
     382             :                                                        st_ivas->ivas_format,
     383             :                                                        st_ivas->transport_config,
     384             :                                                        st_ivas->hRenderConfig->directivity_fx,
     385             :                                                        st_ivas->hRenderConfig->distAtt_fx,
     386             :                                                        st_ivas->hTransSetup,
     387             :                                                        &st_ivas->hTdRendHandles[i],
     388             :                                                        &st_ivas->binaural_latency_ns,
     389             :                                                        SrcInd ) ) != IVAS_ERR_OK )
     390             :         {
     391           0 :             return error;
     392             :         }
     393             :     }
     394             : 
     395             :     /* Save current head positions */
     396           0 :     FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i )
     397             :     {
     398           0 :         originalHeadRot[i] = st_ivas->hCombinedOrientationData->Quaternions[i];
     399           0 :         q_fact_orig[i] = originalHeadRot[i].q_fact;
     400             :     }
     401             : 
     402           0 :     original_subframes_rendered = st_ivas->hTcBuffer->subframes_rendered;
     403           0 :     move16();
     404           0 :     original_slots_rendered = st_ivas->hTcBuffer->slots_rendered;
     405           0 :     move16();
     406           0 :     origTdRendHandle = st_ivas->hBinRendererTd;
     407           0 :     move32();
     408             : 
     409           0 :     FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i )
     410             :     {
     411           0 :         modify_Quat_q_fx( &originalHeadRot[i], &originalHeadRot[i], Q22 );
     412             :     }
     413             : 
     414           0 :     FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
     415             :     {
     416             :         /* Update head positions */
     417           0 :         IF( NE_16( pos_idx, 0 ) )
     418             :         {
     419           0 :             COMBINED_ORIENTATION_HANDLE pCombinedOrientationData = st_ivas->hCombinedOrientationData;
     420           0 :             FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i )
     421             :             {
     422           0 :                 pCombinedOrientationData->Quaternions[i].w_fx = L_negate( 12582912 ); // Q22
     423             :                 /*euler*/
     424           0 :                 Quat2EulerDegree_fx( originalHeadRot[i],
     425           0 :                                      &pCombinedOrientationData->Quaternions[i].z_fx,
     426           0 :                                      &pCombinedOrientationData->Quaternions[i].y_fx,
     427           0 :                                      &pCombinedOrientationData->Quaternions[i].x_fx );
     428           0 :                 pCombinedOrientationData->Quaternions[i].x_fx = L_add( pCombinedOrientationData->Quaternions[i].x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] );
     429           0 :                 pCombinedOrientationData->Quaternions[i].y_fx = L_add( pCombinedOrientationData->Quaternions[i].y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] );
     430           0 :                 pCombinedOrientationData->Quaternions[i].z_fx = L_add( pCombinedOrientationData->Quaternions[i].z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] );
     431             : 
     432           0 :                 Euler2Quat_fx( deg2rad_fx( pCombinedOrientationData->Quaternions[i].x_fx ),
     433             :                                deg2rad_fx( pCombinedOrientationData->Quaternions[i].y_fx ),
     434           0 :                                deg2rad_fx( pCombinedOrientationData->Quaternions[i].z_fx ), &pCombinedOrientationData->Quaternions[i] );
     435             : 
     436           0 :                 modify_Quat_q_fx( &pCombinedOrientationData->Quaternions[i], &pCombinedOrientationData->Quaternions[i], q_fact_orig[i] );
     437             :             }
     438             :         }
     439             : 
     440             :         /* set output channels */
     441           0 :         FOR( i = 0; i < BINAURAL_CHANNELS; i++ )
     442             :         {
     443           0 :             p_bin_output[i] = output_local[add( i_mult( pos_idx, BINAURAL_CHANNELS ), i )];
     444           0 :             move32();
     445             :         }
     446           0 :         st_ivas->hTcBuffer->subframes_rendered = original_subframes_rendered;
     447           0 :         move16();
     448           0 :         st_ivas->hTcBuffer->slots_rendered = original_slots_rendered;
     449           0 :         move16();
     450             : 
     451             :         /* update combined orientation access index */
     452           0 :         ivas_combined_orientation_set_to_start_index( st_ivas->hCombinedOrientationData );
     453             : 
     454             :         /* Render */
     455           0 :         IF( NE_16( pos_idx, 0 ) )
     456             :         {
     457           0 :             st_ivas->hBinRendererTd = st_ivas->hTdRendHandles[sub( pos_idx, 1 )];
     458           0 :             move32();
     459             :         }
     460             : 
     461           0 :         IF( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_bin_output, nSamplesRendered ) ) != IVAS_ERR_OK )
     462             :         {
     463           0 :             return error;
     464             :         }
     465             : 
     466           0 :         IF( EQ_16( st_ivas->ivas_format, MC_FORMAT ) )
     467             :         {
     468             :             Word32 *p_tc[MAX_TRANSPORT_CHANNELS];
     469           0 :             FOR( i = 0; i < st_ivas->nchan_transport; i++ )
     470             :             {
     471           0 :                 p_tc[i] = st_ivas->hTcBuffer->tc_fx[i] + st_ivas->hTcBuffer->n_samples_rendered;
     472             :             }
     473           0 :             ivas_binaural_add_LFE_fx( st_ivas, nSamplesRendered, p_tc, p_bin_output );
     474             :         }
     475             :     }
     476             : 
     477           0 :     FOR( i = 0; i < i_mult( pMultiBinPoseData->num_poses, BINAURAL_CHANNELS ); i++ )
     478             :     {
     479           0 :         Copy32( output_local[i], output[i], nSamplesRendered );
     480             :     }
     481             : 
     482             :     /* Restore original head rotation */
     483           0 :     FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i )
     484             :     {
     485           0 :         modify_Quat_q_fx( &originalHeadRot[i], &originalHeadRot[i], q_fact_orig[i] );
     486           0 :         st_ivas->hCombinedOrientationData->Quaternions[i] = originalHeadRot[i];
     487           0 :         move32();
     488             :     }
     489             : 
     490             :     /* restore original td renderer handle */
     491           0 :     st_ivas->hBinRendererTd = origTdRendHandle;
     492           0 :     move32();
     493             : 
     494           0 :     return IVAS_ERR_OK;
     495             : }

Generated by: LCOV version 1.14