LCOV - code coverage report
Current view: top level - lib_dec - ivas_objectRenderer_internal.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 78 139 56.1 %
Date: 2025-05-23 08:37:30 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.h"
      36             : #include "ivas_prot.h"
      37             : #include "ivas_prot_rend.h"
      38             : #include <math.h>
      39             : #include "ivas_rom_com.h"
      40             : #ifdef DEBUGGING
      41             : #include "debug.h"
      42             : #endif
      43             : #include "wmc_auto.h"
      44             : 
      45             : 
      46             : /*---------------------------------------------------------------------*
      47             :  * ivas_td_binaural_open()
      48             :  *
      49             :  * Open and initialize TD Object binaural renderer
      50             :  *---------------------------------------------------------------------*/
      51             : 
      52         993 : ivas_error ivas_td_binaural_open(
      53             :     Decoder_Struct *st_ivas /* i/o: IVAS decoder structure  */
      54             : )
      55             : {
      56             :     int16_t num_src;
      57             : 
      58         993 :     num_src = st_ivas->nchan_transport;
      59         993 :     if ( ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) || ( st_ivas->ism_mode == ISM_SBA_MODE_DISC ) )
      60             :     {
      61         669 :         num_src = st_ivas->nchan_ism;
      62             :     }
      63             : 
      64         993 :     if ( st_ivas->hHrtfTD == NULL && st_ivas->hDecoderConfig->Opt_HRTF_binary )
      65             :     {
      66           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "HRTF binary file present but not used in TD renderer" );
      67             :     }
      68             : 
      69         993 :     return ivas_td_binaural_open_unwrap( &st_ivas->hHrtfTD, st_ivas->hDecoderConfig->output_Fs, num_src, st_ivas->ivas_format,
      70         993 :                                          st_ivas->transport_config, st_ivas->hRenderConfig->directivity, st_ivas->hRenderConfig->distAtt, st_ivas->hTransSetup, &st_ivas->hBinRendererTd, &st_ivas->binaural_latency_ns );
      71             : }
      72             : 
      73             : 
      74             : /*---------------------------------------------------------------------*
      75             :  * ivas_td_binaural_renderer_sf()
      76             :  *
      77             :  * Receives the current frames for the object streams, updates metadata
      78             :  * and renders the current frame.
      79             :  *---------------------------------------------------------------------*/
      80             : 
      81      319600 : ivas_error ivas_td_binaural_renderer_sf(
      82             :     Decoder_Struct *st_ivas,            /* i/o: IVAS decoder structure              */
      83             :     float *output[],                    /* i/o: SCE channels / Binaural synthesis   */
      84             :     const int16_t n_samples_granularity /* i  : granularity of the renderer/buffer  */
      85             : )
      86             : {
      87             :     int16_t first_sf, last_sf, subframe_idx;
      88             :     float reverb_signal[BINAURAL_CHANNELS][L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES];
      89             :     float *p_reverb_signal[BINAURAL_CHANNELS];
      90             :     float *output_f_local[BINAURAL_CHANNELS];
      91             :     float *tc_local[MAX_TRANSPORT_CHANNELS];
      92             :     int16_t ch, slot_size, slots_to_render, output_frame;
      93             :     ivas_error error;
      94             : 
      95             :     int16_t ism_md_subframe_update_jbm;
      96             :     int16_t c_indx, nS;
      97             :     int16_t nchan_ism_internal, nchan_ism, ch_offset;
      98             : 
      99             :     /* Set the number of ISMs */
     100      319600 :     if ( st_ivas->ivas_format == MASA_ISM_FORMAT || ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->nchan_ism > 0 ) )
     101             :     {
     102        2308 :         nchan_ism_internal = st_ivas->nchan_ism;
     103        2308 :         nchan_ism = st_ivas->nchan_ism;
     104        2308 :         ch_offset = CPE_CHANNELS;
     105             :     }
     106      317292 :     else if ( st_ivas->ivas_format == SBA_ISM_FORMAT )
     107             :     {
     108       72385 :         nchan_ism_internal = st_ivas->nchan_ism;
     109       72385 :         nchan_ism = st_ivas->nchan_ism;
     110       72385 :         ch_offset = 0;
     111             :     }
     112             :     else
     113             :     {
     114      244907 :         nchan_ism_internal = st_ivas->hTcBuffer->nchan_transport_internal;
     115      244907 :         nchan_ism = st_ivas->nchan_transport;
     116      244907 :         ch_offset = 0;
     117             :     }
     118             : 
     119             :     /* Number of subframes to delay metadata to sync with audio */
     120      319600 :     if ( st_ivas->hDecoderConfig->Opt_delay_comp )
     121             :     {
     122      319600 :         ism_md_subframe_update_jbm = max( 0, st_ivas->hTcBuffer->nb_subframes - 3 );
     123             :     }
     124             :     else
     125             :     {
     126           0 :         ism_md_subframe_update_jbm = st_ivas->hTcBuffer->nb_subframes - 2;
     127             :     }
     128             : 
     129      319600 :     if ( st_ivas->ivas_format == MASA_ISM_FORMAT )
     130             :     {
     131        2308 :         ism_md_subframe_update_jbm = max( 0, st_ivas->hTcBuffer->nb_subframes - 2 );
     132             :     }
     133             : 
     134      958800 :     for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
     135             :     {
     136      639200 :         p_reverb_signal[ch] = reverb_signal[ch];
     137             :     }
     138             : 
     139     1337763 :     for ( ch = 0; ch < nchan_ism_internal; ch++ )
     140             :     {
     141     1018163 :         tc_local[ch] = st_ivas->hTcBuffer->tc[ch + ch_offset] + st_ivas->hTcBuffer->n_samples_rendered;
     142             :     }
     143             : 
     144      958800 :     for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ )
     145             :     {
     146      639200 :         output_f_local[ch] = output[ch];
     147             :     }
     148             : 
     149      319600 :     slot_size = st_ivas->hTcBuffer->n_samples_granularity;
     150             : 
     151             :     /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */
     152      319600 :     slots_to_render = min( st_ivas->hTcBuffer->num_slots - st_ivas->hTcBuffer->slots_rendered, n_samples_granularity / slot_size );
     153      319600 :     first_sf = st_ivas->hTcBuffer->subframes_rendered;
     154      319600 :     last_sf = first_sf;
     155      319600 :     st_ivas->hTcBuffer->slots_rendered += slots_to_render;
     156             : 
     157      865048 :     while ( slots_to_render > 0 )
     158             :     {
     159      545448 :         slots_to_render -= st_ivas->hTcBuffer->subframe_nbslots[last_sf];
     160      545448 :         last_sf++;
     161             :     }
     162             : 
     163      865048 :     for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
     164             :     {
     165      545448 :         output_frame = st_ivas->hTcBuffer->subframe_nbslots[subframe_idx] * st_ivas->hTcBuffer->n_samples_granularity;
     166             : 
     167             :         /* Update object position(s) */
     168      545448 :         c_indx = 0;
     169             : 
     170     2282334 :         for ( nS = 0; nS < nchan_ism; nS++ )
     171             :         {
     172     1736886 :             if ( !( st_ivas->ivas_format == MC_FORMAT && nS == LFE_CHANNEL ) ) /* Skip LFE for MC */
     173             :             {
     174     1699407 :                 st_ivas->hBinRendererTd->Sources[c_indx]->InputFrame_p = tc_local[nS];
     175     1699407 :                 st_ivas->hBinRendererTd->Sources[c_indx]->SrcRend_p->InputAvailable = TRUE;
     176     1699407 :                 c_indx++;
     177             :             }
     178             :         }
     179             : 
     180      545448 :         if ( subframe_idx == ism_md_subframe_update_jbm )
     181             :         {
     182      136578 :             if ( st_ivas->ivas_format == ISM_FORMAT || st_ivas->ivas_format == SBA_ISM_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT )
     183      127206 :             {
     184             :                 ISM_METADATA_FRAME ismMetaData[MAX_NUM_OBJECTS];
     185             :                 ISM_METADATA_HANDLE hIsmMetaData[MAX_NUM_OBJECTS];
     186             : 
     187      505221 :                 for ( nS = 0; nS < nchan_ism; nS++ )
     188             :                 {
     189      378015 :                     ismMetaData[nS].azimuth = st_ivas->hIsmMetaData[nS]->edited_azimuth;
     190      378015 :                     ismMetaData[nS].elevation = st_ivas->hIsmMetaData[nS]->edited_elevation;
     191      378015 :                     ismMetaData[nS].radius = st_ivas->hIsmMetaData[nS]->edited_radius;
     192      378015 :                     ismMetaData[nS].yaw = st_ivas->hIsmMetaData[nS]->edited_yaw;
     193      378015 :                     ismMetaData[nS].pitch = st_ivas->hIsmMetaData[nS]->edited_pitch;
     194      378015 :                     ismMetaData[nS].non_diegetic_flag = st_ivas->hIsmMetaData[nS]->non_diegetic_flag;
     195             : 
     196      378015 :                     if ( st_ivas->ivas_format == MASA_ISM_FORMAT )
     197             :                     {
     198             :                         /* DISC OMASA ISM gaining with TDREND is done in ivas_dec_prepare_renderer()*/
     199        3456 :                         ismMetaData[nS].gain = 1;
     200             :                     }
     201             :                     else
     202             :                     {
     203      374559 :                         ismMetaData[nS].gain = st_ivas->hIsmMetaData[nS]->edited_gain;
     204             :                     }
     205             : 
     206      378015 :                     hIsmMetaData[nS] = &ismMetaData[nS];
     207             :                 }
     208             : 
     209      127206 :                 if ( ( error = TDREND_Update_object_positions( st_ivas->hBinRendererTd, nchan_ism, st_ivas->ivas_format, hIsmMetaData ) ) != IVAS_ERR_OK )
     210             :                 {
     211           0 :                     return error;
     212             :                 }
     213             :             }
     214             :             else
     215             :             {
     216        9372 :                 if ( ( error = TDREND_Update_object_positions( st_ivas->hBinRendererTd, nchan_ism, st_ivas->ivas_format, st_ivas->hIsmMetaData ) ) != IVAS_ERR_OK )
     217             :                 {
     218           0 :                     return error;
     219             :                 }
     220             :             }
     221             :         }
     222             : 
     223             :         /* Update the listener's location/orientation */
     224     1122330 :         if ( ( error = TDREND_Update_listener_orientation( st_ivas->hBinRendererTd,
     225      545448 :                                                            ( st_ivas->hCombinedOrientationData != NULL ) ? st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx] : 0,
     226      545448 :                                                            ( st_ivas->hCombinedOrientationData != NULL ) ? &st_ivas->hCombinedOrientationData->Quaternions[st_ivas->hCombinedOrientationData->subframe_idx] : NULL,
     227      545448 :                                                            ( st_ivas->hCombinedOrientationData != NULL ) ? &st_ivas->hCombinedOrientationData->listenerPos[st_ivas->hCombinedOrientationData->subframe_idx] : NULL ) ) != IVAS_ERR_OK )
     228             :         {
     229           0 :             return error;
     230             :         }
     231      545448 :         if ( st_ivas->hRenderConfig != NULL && st_ivas->hOutSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB )
     232             :         {
     233       70188 :             if ( ( error = ivas_reverb_process( st_ivas->hReverb, st_ivas->transport_config, 0, tc_local, p_reverb_signal, 0 ) ) != IVAS_ERR_OK )
     234             :             {
     235           0 :                 return error;
     236             :             }
     237             :         }
     238             : 
     239             :         /* Render subframe */
     240             :         /* ism_md_subframe_update_jbm != subframe_idx: trigger update only for ism_md_subframe_update_jbm == subframe_idx,
     241             :            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 */
     242      545448 :         if ( ( error = TDREND_GetMix( st_ivas->hBinRendererTd, output_f_local, output_frame, 0 ) ) != IVAS_ERR_OK )
     243             :         {
     244           0 :             return error;
     245             :         }
     246      545448 :         if ( st_ivas->hRenderConfig != NULL && st_ivas->hOutSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB )
     247             :         {
     248             :             /* add reverb to rendered signals */
     249       70188 :             v_add( reverb_signal[0], output_f_local[0], output_f_local[0], output_frame );
     250       70188 :             v_add( reverb_signal[1], output_f_local[1], output_f_local[1], output_frame );
     251             :         }
     252             : 
     253             : 
     254     2282334 :         for ( ch = 0; ch < nchan_ism_internal; ch++ )
     255             :         {
     256     1736886 :             tc_local[ch] += output_frame;
     257             :         }
     258             : 
     259     1636344 :         for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ )
     260             :         {
     261     1090896 :             output_f_local[ch] += output_frame;
     262             :         }
     263             : 
     264             :         /* update combined orientation access index */
     265      545448 :         ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, output_frame );
     266             :     }
     267             : 
     268      319600 :     st_ivas->hTcBuffer->subframes_rendered = last_sf;
     269             : 
     270      319600 :     return IVAS_ERR_OK;
     271             : }
     272             : 
     273             : 
     274             : /*---------------------------------------------------------------------*
     275             :  * ivas_td_binaural_renderer_sf_splitBinaural()
     276             :  *
     277             :  * Render to multiple binaural pairs based on relative head positions for split rendering.
     278             :  *---------------------------------------------------------------------*/
     279             : 
     280           0 : ivas_error ivas_td_binaural_renderer_sf_splitBinaural(
     281             :     Decoder_Struct *st_ivas,       /* i/o: IVAS decoder structure                    */
     282             :     float *output[],               /* i/o: SCE channels / Binaural synthesis         */
     283             :     const int16_t nSamplesRendered /* i  : number of samples to render               */
     284             : )
     285             : {
     286             :     int16_t i;
     287             :     int16_t pos_idx;
     288             :     IVAS_QUATERNION originalHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES];
     289             :     MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
     290             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE origTdRendHandle;
     291             :     ivas_error error;
     292             :     int16_t original_subframes_rendered;
     293             :     int16_t original_slots_rendered;
     294             :     float *p_bin_output[BINAURAL_CHANNELS];
     295             :     float output_local[MAX_OUTPUT_CHANNELS][L_FRAME48k];
     296             : 
     297           0 :     push_wmops( "ivas_td_binaural_renderer_sf_splitBinaural" );
     298           0 :     pMultiBinPoseData = &st_ivas->hSplitBinRend->splitrend.multiBinPoseData;
     299             : 
     300             :     /* If not yet allocated, open additional instances of TD renderer */
     301           0 :     for ( i = 0; i < pMultiBinPoseData->num_poses - 1; ++i )
     302             :     {
     303           0 :         if ( st_ivas->hTdRendHandles[i] != NULL )
     304             :         {
     305           0 :             continue;
     306             :         }
     307             : 
     308           0 :         if ( ( error = ivas_td_binaural_open_unwrap( &st_ivas->hHrtfTD,
     309           0 :                                                      st_ivas->hDecoderConfig->output_Fs,
     310           0 :                                                      st_ivas->nchan_transport,
     311             :                                                      st_ivas->ivas_format,
     312             :                                                      st_ivas->transport_config,
     313           0 :                                                      st_ivas->hRenderConfig->directivity,
     314           0 :                                                      st_ivas->hRenderConfig->distAtt,
     315             :                                                      st_ivas->hTransSetup,
     316           0 :                                                      &st_ivas->hTdRendHandles[i],
     317             :                                                      &st_ivas->binaural_latency_ns ) ) != IVAS_ERR_OK )
     318             :         {
     319           0 :             return error;
     320             :         }
     321             :     }
     322             : 
     323             :     /* Save current head positions */
     324           0 :     for ( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i )
     325             :     {
     326           0 :         originalHeadRot[i] = st_ivas->hCombinedOrientationData->Quaternions[i];
     327             :     }
     328             : 
     329           0 :     original_subframes_rendered = st_ivas->hTcBuffer->subframes_rendered;
     330           0 :     original_slots_rendered = st_ivas->hTcBuffer->slots_rendered;
     331           0 :     origTdRendHandle = st_ivas->hBinRendererTd;
     332             : 
     333           0 :     for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
     334             :     {
     335             :         /* Update head positions */
     336           0 :         if ( pos_idx != 0 )
     337             :         {
     338           0 :             for ( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i )
     339             :             {
     340           0 :                 if ( originalHeadRot[i].w == -3.0f )
     341             :                 {
     342           0 :                     st_ivas->hCombinedOrientationData->Quaternions[i].w = -3.0f;
     343           0 :                     st_ivas->hCombinedOrientationData->Quaternions[i].x = originalHeadRot[i].x + pMultiBinPoseData->relative_head_poses[pos_idx][0];
     344           0 :                     st_ivas->hCombinedOrientationData->Quaternions[i].y = originalHeadRot[i].y + pMultiBinPoseData->relative_head_poses[pos_idx][1];
     345           0 :                     st_ivas->hCombinedOrientationData->Quaternions[i].z = originalHeadRot[i].z + pMultiBinPoseData->relative_head_poses[pos_idx][2];
     346             :                 }
     347             :                 else
     348             :                 {
     349           0 :                     st_ivas->hCombinedOrientationData->Quaternions[i].w = -3.0f;
     350             : 
     351           0 :                     Quat2EulerDegree( originalHeadRot[i], /* TODO tmu : fix bug with ordering*/
     352           0 :                                       &st_ivas->hCombinedOrientationData->Quaternions[i].z,
     353           0 :                                       &st_ivas->hCombinedOrientationData->Quaternions[i].y,
     354           0 :                                       &st_ivas->hCombinedOrientationData->Quaternions[i].x );
     355             : 
     356           0 :                     st_ivas->hCombinedOrientationData->Quaternions[i].x += pMultiBinPoseData->relative_head_poses[pos_idx][0];
     357           0 :                     st_ivas->hCombinedOrientationData->Quaternions[i].y += pMultiBinPoseData->relative_head_poses[pos_idx][1];
     358           0 :                     st_ivas->hCombinedOrientationData->Quaternions[i].z += pMultiBinPoseData->relative_head_poses[pos_idx][2];
     359             :                 }
     360             :             }
     361             :         }
     362             : 
     363             :         /* set output channels */
     364           0 :         for ( i = 0; i < BINAURAL_CHANNELS; i++ )
     365             :         {
     366           0 :             p_bin_output[i] = output_local[pos_idx * BINAURAL_CHANNELS + i];
     367             :         }
     368           0 :         st_ivas->hTcBuffer->subframes_rendered = original_subframes_rendered;
     369           0 :         st_ivas->hTcBuffer->slots_rendered = original_slots_rendered;
     370             : 
     371             :         /* update combined orientation access index */
     372           0 :         ivas_combined_orientation_set_to_start_index( st_ivas->hCombinedOrientationData );
     373             : 
     374             :         /* Render */
     375           0 :         if ( pos_idx != 0 )
     376             :         {
     377           0 :             st_ivas->hBinRendererTd = st_ivas->hTdRendHandles[pos_idx - 1];
     378             :         }
     379             : 
     380           0 :         if ( ( error = ivas_td_binaural_renderer_sf( st_ivas, p_bin_output, nSamplesRendered ) ) != IVAS_ERR_OK )
     381             :         {
     382           0 :             return error;
     383             :         }
     384             : 
     385           0 :         if ( st_ivas->ivas_format == MC_FORMAT )
     386             :         {
     387             :             float *p_tc[MAX_TRANSPORT_CHANNELS];
     388           0 :             for ( i = 0; i < st_ivas->nchan_transport; i++ )
     389             :             {
     390           0 :                 p_tc[i] = st_ivas->hTcBuffer->tc[i] + st_ivas->hTcBuffer->n_samples_rendered;
     391             :             }
     392           0 :             ivas_binaural_add_LFE( st_ivas, nSamplesRendered, p_tc, p_bin_output );
     393             :         }
     394             :     }
     395             : 
     396           0 :     for ( i = 0; i < pMultiBinPoseData->num_poses * BINAURAL_CHANNELS; i++ )
     397             :     {
     398           0 :         mvr2r( output_local[i], output[i], nSamplesRendered );
     399             :     }
     400             : 
     401             :     /* Restore original head rotation */
     402           0 :     for ( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i )
     403             :     {
     404           0 :         st_ivas->hCombinedOrientationData->Quaternions[i] = originalHeadRot[i];
     405             :     }
     406             : 
     407             :     /* restore original td renderer handle */
     408           0 :     st_ivas->hBinRendererTd = origTdRendHandle;
     409             : 
     410           0 :     pop_wmops();
     411           0 :     return IVAS_ERR_OK;
     412             : }

Generated by: LCOV version 1.14