LCOV - code coverage report
Current view: top level - lib_rend - ivas_objectRenderer.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ fec202a8f89be4a2f278a9fc377bfb58b58fab11 Lines: 242 286 84.6 %
Date: 2025-09-13 07:56:34 Functions: 10 10 100.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 "ivas_stat_rend.h"
      34             : #include <stdint.h>
      35             : #include "options.h"
      36             : #include "prot.h"
      37             : #include "ivas_prot.h"
      38             : #include "ivas_prot_rend.h"
      39             : #include <math.h>
      40             : #include "ivas_rom_com.h"
      41             : #ifdef DEBUGGING
      42             : #include "debug.h"
      43             : #endif
      44             : #include "wmc_auto.h"
      45             : 
      46             : 
      47             : /*---------------------------------------------------------------------*
      48             :  * Local function prototypes
      49             :  *---------------------------------------------------------------------*/
      50             : 
      51             : static void TDREND_Clear_Update_flags( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd );
      52             : 
      53             : static void angles_to_vec( const float radius, const float azimuth, const float elevation, float *vec );
      54             : 
      55             : 
      56             : /*---------------------------------------------------------------------*
      57             :  * ivas_td_binaural_open_unwrap()
      58             :  *
      59             :  * Call TD open/init function without st_ivas
      60             :  *---------------------------------------------------------------------*/
      61             : 
      62       24372 : ivas_error ivas_td_binaural_open_unwrap(
      63             :     TDREND_HRFILT_FiltSet_t **hHrtfTD,                  /* i/o: HR filter model (from file or NULL) */
      64             :     const int32_t output_Fs,                            /* i  : Output sampling rate                */
      65             :     const int16_t nchan_transport,                      /* i  : Number of channels                  */
      66             :     const IVAS_FORMAT ivas_format,                      /* i  : IVAS format (ISM/MC)                */
      67             :     const AUDIO_CONFIG transport_config,                /* i  : Transport configuration             */
      68             :     const float *directivity,                           /* i  : Directivity pattern (used for ISM)  */
      69             :     const float *distAtt,                               /* i  : Distance attenuation (used for ISM) */
      70             :     const IVAS_OUTPUT_SETUP hTransSetup,                /* i  : Loudspeaker layout                  */
      71             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd, /* o  : TD renderer handle                  */
      72             :     int32_t *binaural_latency_ns                        /* i  : Binauralization delay               */
      73             : )
      74             : {
      75             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE pBinRendTd;
      76             :     TDREND_PosType_t PosType;
      77             :     int16_t nS;
      78             :     int16_t SrcInd[MAX_NUM_TDREND_CHANNELS];
      79             :     const float *ls_azimuth, *ls_elevation;
      80             :     float Pos[3];
      81             :     float Dir[3];
      82             :     TDREND_DirAtten_t *DirAtten_p;
      83             :     TDREND_DistAtten_t DistAtten;
      84             :     int16_t nchan_rend;
      85             :     ivas_error error;
      86             : 
      87       24372 :     error = IVAS_ERR_OK;
      88             : 
      89       24372 :     if ( ( pBinRendTd = malloc( sizeof( BINAURAL_TD_OBJECT_RENDERER ) ) ) == NULL )
      90             :     {
      91           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
      92             :     }
      93       24372 :     if ( ( pBinRendTd->TdRend_MixSpatSpec_p = malloc( sizeof( TDREND_MixSpatSpec_t ) ) ) == NULL )
      94             :     {
      95           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
      96             :     }
      97       24372 :     if ( ( pBinRendTd->DirAtten_p = malloc( sizeof( TDREND_DirAtten_t ) ) ) == NULL )
      98             :     {
      99           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
     100             :     }
     101       24372 :     if ( ( pBinRendTd->Listener_p = malloc( sizeof( TDREND_MIX_Listener_t ) ) ) == NULL )
     102             :     {
     103           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
     104             :     }
     105             : 
     106       24372 :     pBinRendTd->NumOfSrcs = 0;
     107       24372 :     pBinRendTd->MaxSrcInd = -1;
     108             : 
     109             :     /* Mixer spatial setup */
     110       24372 :     pBinRendTd->TdRend_MixSpatSpec_p->UseCommonDistAttenModel = TRUE;
     111       24372 :     pBinRendTd->TdRend_MixSpatSpec_p->DistAttenModel = 0; /* 0=Turned off, else use TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED */
     112             : 
     113       24372 :     if ( ( error = TDREND_MIX_Init( pBinRendTd, hHrtfTD, pBinRendTd->TdRend_MixSpatSpec_p, output_Fs ) ) != IVAS_ERR_OK )
     114             :     {
     115           0 :         return error;
     116             :     }
     117             : 
     118             :     /* Set the attenuation (or can set MixSpatSpec.DistAttenModel above) */
     119       24372 :     if ( ( error = TDREND_MIX_SetDistAttenModel( pBinRendTd, TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED ) ) != IVAS_ERR_OK )
     120             :     {
     121           0 :         return error;
     122             :     }
     123             : 
     124             :     /* Add sources to module and mixer, headphones */
     125       24372 :     PosType = TDREND_POSTYPE_ABSOLUTE; /* or TDREND_POSTYPE_RELATIVE_TO_LISTENER */
     126             : 
     127       24372 :     nchan_rend = nchan_transport;
     128       24372 :     if ( ( ivas_format == MC_FORMAT ) && ( transport_config != IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
     129             :     {
     130          81 :         nchan_rend--; /* Skip LFE channel -- added to the others */
     131             :     }
     132             : 
     133       52284 :     for ( nS = 0; nS < nchan_rend; nS++ )
     134             :     {
     135       27912 :         if ( ( error = TDREND_MIX_AddSrc( pBinRendTd, &SrcInd[nS], PosType ) ) != IVAS_ERR_OK )
     136             :         {
     137           0 :             return error;
     138             :         }
     139             :     }
     140             : 
     141       24372 :     if ( ivas_format == MC_FORMAT )
     142             :     {
     143         225 :         switch ( transport_config )
     144             :         {
     145          33 :             case IVAS_AUDIO_CONFIG_5_1:
     146          33 :                 ls_azimuth = ls_azimuth_CICP6;
     147          33 :                 ls_elevation = ls_elevation_CICP6;
     148          33 :                 break;
     149          48 :             case IVAS_AUDIO_CONFIG_7_1:
     150          48 :                 ls_azimuth = ls_azimuth_CICP12;
     151          48 :                 ls_elevation = ls_elevation_CICP12;
     152          48 :                 break;
     153           0 :             case IVAS_AUDIO_CONFIG_5_1_2:
     154           0 :                 ls_azimuth = ls_azimuth_CICP14;
     155           0 :                 ls_elevation = ls_elevation_CICP14;
     156           0 :                 break;
     157           0 :             case IVAS_AUDIO_CONFIG_5_1_4:
     158           0 :                 ls_azimuth = ls_azimuth_CICP16;
     159           0 :                 ls_elevation = ls_elevation_CICP16;
     160           0 :                 break;
     161           0 :             case IVAS_AUDIO_CONFIG_7_1_4:
     162           0 :                 ls_azimuth = ls_azimuth_CICP19;
     163           0 :                 ls_elevation = ls_elevation_CICP19;
     164           0 :                 break;
     165         144 :             case IVAS_AUDIO_CONFIG_LS_CUSTOM:
     166         144 :                 ls_azimuth = hTransSetup.ls_azimuth;
     167         144 :                 ls_elevation = hTransSetup.ls_elevation;
     168         144 :                 break;
     169           0 :             default:
     170           0 :                 ls_azimuth = NULL;
     171           0 :                 ls_elevation = NULL;
     172             :         }
     173             : 
     174         225 :         DirAtten_p = pBinRendTd->DirAtten_p;
     175             : 
     176        1662 :         for ( nS = 0; nS < nchan_rend; nS++ )
     177             :         {
     178             :             /* Set source positions according to loudspeaker layout */
     179        1437 :             angles_to_vec( 1.0f, ls_azimuth[nS], ls_elevation[nS], Pos );
     180        1437 :             Dir[0] = 1.0f;
     181        1437 :             Dir[1] = 0.0f;
     182        1437 :             Dir[2] = 0.0f;
     183             : 
     184             :             /* Source directivity info */
     185        1437 :             DirAtten_p->ConeInnerAngle = 360.0f;
     186        1437 :             DirAtten_p->ConeOuterAngle = 360.0f;
     187        1437 :             DirAtten_p->ConeOuterGain = 1.0f;
     188             : 
     189        1437 :             DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED;
     190        1437 :             DistAtten.MaxDist = 15.75f;
     191        1437 :             DistAtten.RefDist = 1.0f;
     192        1437 :             DistAtten.RollOffFactor = 1.0f;
     193             : 
     194        1437 :             if ( ( error = TDREND_MIX_SRC_SetPos( pBinRendTd, nS, Pos ) ) != IVAS_ERR_OK )
     195             :             {
     196           0 :                 return error;
     197             :             }
     198             : 
     199        1437 :             if ( ( error = TDREND_MIX_SRC_SetDir( pBinRendTd, nS, Dir ) ) != IVAS_ERR_OK )
     200             :             {
     201           0 :                 return error;
     202             :             }
     203             : 
     204        1437 :             if ( ( error = TDREND_MIX_SRC_SetPlayState( pBinRendTd, nS, TDREND_PLAYSTATUS_PLAYING ) ) != IVAS_ERR_OK )
     205             :             {
     206           0 :                 return error;
     207             :             }
     208             : 
     209        1437 :             if ( ( error = TDREND_MIX_SRC_SetDirAtten( pBinRendTd, nS, DirAtten_p ) ) != IVAS_ERR_OK )
     210             :             {
     211           0 :                 return error;
     212             :             }
     213        1437 :             if ( ( error = TDREND_MIX_SRC_SetDistAtten( pBinRendTd, nS, &DistAtten ) ) != IVAS_ERR_OK )
     214             :             {
     215           0 :                 return error;
     216             :             }
     217             :         }
     218             :     }
     219             : 
     220       24372 :     if ( ivas_format == ISM_FORMAT || ivas_format == MASA_ISM_FORMAT || ivas_format == SBA_ISM_FORMAT )
     221             :     {
     222       24147 :         DirAtten_p = pBinRendTd->DirAtten_p;
     223             : 
     224       50622 :         for ( nS = 0; nS < nchan_rend; nS++ )
     225             :         {
     226       26475 :             if ( NULL == directivity )
     227             :             {
     228        8790 :                 DirAtten_p->ConeInnerAngle = 360.0f; /* Front cone */
     229        8790 :                 DirAtten_p->ConeOuterAngle = 360.0f; /* Back cone */
     230        8790 :                 DirAtten_p->ConeOuterGain = 1.0f;    /* Back attenuation */
     231             :             }
     232             :             else
     233             :             {
     234       17685 :                 DirAtten_p->ConeInnerAngle = directivity[nS * 3];
     235       17685 :                 DirAtten_p->ConeOuterAngle = directivity[nS * 3 + 1];
     236       17685 :                 DirAtten_p->ConeOuterGain = directivity[nS * 3 + 2];
     237             :             }
     238       26475 :             if ( NULL == distAtt )
     239             :             {
     240        8790 :                 DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED;
     241        8790 :                 DistAtten.MaxDist = 15.75f;
     242        8790 :                 DistAtten.RefDist = 1.0f;
     243        8790 :                 DistAtten.RollOffFactor = 1.0f;
     244             :             }
     245             :             else
     246             :             {
     247       17685 :                 DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED;
     248       17685 :                 DistAtten.MaxDist = distAtt[0];
     249       17685 :                 DistAtten.RefDist = distAtt[1];
     250       17685 :                 DistAtten.RollOffFactor = distAtt[2];
     251             :             }
     252       26475 :             if ( ( error = TDREND_MIX_SRC_SetDirAtten( pBinRendTd, nS, DirAtten_p ) ) != IVAS_ERR_OK )
     253             :             {
     254           0 :                 return error;
     255             :             }
     256       26475 :             if ( ( error = TDREND_MIX_SRC_SetDistAtten( pBinRendTd, nS, &DistAtten ) ) != IVAS_ERR_OK )
     257             :             {
     258           0 :                 return error;
     259             :             }
     260             :         }
     261             :     }
     262             : 
     263       24372 :     *hBinRendererTd = pBinRendTd;
     264             : 
     265       24372 :     if ( ivas_format != MASA_ISM_FORMAT && ivas_format != SBA_ISM_FORMAT )
     266             :     {
     267       23706 :         *binaural_latency_ns = (int32_t) ( ( *hBinRendererTd )->HrFiltSet_p->latency_s * 1000000000.f );
     268             :     }
     269             : 
     270       24372 :     return error;
     271             : }
     272             : 
     273             : 
     274             : /*---------------------------------------------------------------------*
     275             :  * ivas_td_binaural_close()
     276             :  *
     277             :  * Close TD Object binaural renderer
     278             :  *---------------------------------------------------------------------*/
     279             : 
     280      249708 : void ivas_td_binaural_close(
     281             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd /* i/o: TD binaural object renderer handle */
     282             : )
     283             : {
     284      249708 :     if ( hBinRendererTd == NULL || *hBinRendererTd == NULL )
     285             :     {
     286      225336 :         return;
     287             :     }
     288             : 
     289       24372 :     free( ( *hBinRendererTd )->TdRend_MixSpatSpec_p );
     290       24372 :     free( ( *hBinRendererTd )->DirAtten_p );
     291             : 
     292       24372 :     TDREND_MIX_Dealloc( *hBinRendererTd );
     293             : 
     294       24372 :     free( *hBinRendererTd );
     295       24372 :     *hBinRendererTd = NULL;
     296             : 
     297       24372 :     return;
     298             : }
     299             : 
     300             : 
     301             : /*---------------------------------------------------------------------*
     302             :  * ivas_td_binaural_renderer_unwrap()
     303             :  *
     304             :  * Call ivas_td_binaural_renderer() without st_ivas.
     305             :  *---------------------------------------------------------------------*/
     306             : 
     307     6091464 : ivas_error ivas_td_binaural_renderer_unwrap(
     308             :     const REVERB_HANDLE hReverb,                          /* i  : Reverberator handle                  */
     309             :     const AUDIO_CONFIG transport_config,                  /* i  : Transport configuration              */
     310             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd,    /* i/o: TD binaural object renderer handle   */
     311             :     const int16_t num_src,                                /* i  : number of sources to render          */
     312             :     const int16_t lfe_idx,                                /* i  : LFE channel index                    */
     313             :     const IVAS_FORMAT ivas_format,                        /* i  : IVAS format                          */
     314             :     ISM_METADATA_HANDLE *hIsmMetaData,                    /* i  : ISM metadata handle                  */
     315             :     COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientaton data handle   */
     316             :     const int16_t ism_md_subframe_update,                 /* i  : Number of subframes to delay ism metadata to sync with audio */
     317             :     float *output[],                                      /* i/o: SCE channels / Binaural synthesis    */
     318             :     const int16_t output_frame,                           /* i  : output frame length                  */
     319             :     const int16_t num_subframes                           /* i  : number of subframes to render */
     320             : )
     321             : {
     322             :     int16_t subframe_length;
     323             :     int16_t subframe_idx;
     324             :     float reverb_signal[BINAURAL_CHANNELS][L_FRAME48k];
     325             :     ivas_error error;
     326             :     int16_t c_indx, nS;
     327             :     float *p_reverb_signal[BINAURAL_CHANNELS];
     328             :     int16_t ch;
     329             :     int16_t *enableCombinedOrientation; /* i  : Combined orientation flag            */
     330             :     IVAS_QUATERNION *Quaternions;       /* i  : Head tracking data per subframe      */
     331             :     IVAS_VECTOR3 *Pos;                  /* i  : Listener position data per subframe  */
     332             : 
     333     6091464 :     enableCombinedOrientation = NULL;
     334     6091464 :     Quaternions = NULL;
     335     6091464 :     Pos = NULL;
     336     6091464 :     if ( hCombinedOrientationData != NULL )
     337             :     {
     338     3080256 :         enableCombinedOrientation = hCombinedOrientationData->enableCombinedOrientation;
     339     3080256 :         Quaternions = hCombinedOrientationData->Quaternions;
     340     3080256 :         Pos = hCombinedOrientationData->listenerPos;
     341             :     }
     342             : 
     343    18274392 :     for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
     344             :     {
     345    12182928 :         p_reverb_signal[ch] = reverb_signal[ch];
     346             :     }
     347             : 
     348     6091464 :     subframe_length = output_frame / num_subframes;
     349             : 
     350     6091464 :     c_indx = 0;
     351    13609368 :     for ( nS = 0; nS < num_src; nS++ )
     352             :     {
     353     7517904 :         if ( !( ivas_format == MC_FORMAT && nS == lfe_idx ) ) /* Skip LFE for MC */
     354             :         {
     355     7448856 :             hBinRendererTd->Sources[c_indx]->InputFrame_p = output[nS];
     356     7448856 :             hBinRendererTd->Sources[c_indx]->SrcRend_p->InputAvailable = TRUE;
     357     7448856 :             c_indx++;
     358             :         }
     359             :     }
     360             : 
     361    15841824 :     for ( subframe_idx = 0; subframe_idx < num_subframes; subframe_idx++ )
     362             :     {
     363     9750360 :         if ( subframe_idx == ism_md_subframe_update )
     364             :         {
     365             :             /* Update object position(s) */
     366     5658984 :             if ( ( error = TDREND_Update_object_positions( hBinRendererTd, num_src, ivas_format, hIsmMetaData ) ) != IVAS_ERR_OK )
     367             :             {
     368           0 :                 return error;
     369             :             }
     370             :         }
     371             : 
     372             :         /* Update the listener's location/orientation */
     373     9750360 :         if ( ( error = TDREND_Update_listener_orientation( hBinRendererTd, ( enableCombinedOrientation != NULL ) ? enableCombinedOrientation[hCombinedOrientationData->subframe_idx] : 0, ( Quaternions != NULL ) ? &Quaternions[hCombinedOrientationData->subframe_idx] : NULL, ( Pos != NULL ) ? &Pos[hCombinedOrientationData->subframe_idx] : NULL ) ) != IVAS_ERR_OK )
     374             :         {
     375           0 :             return error;
     376             :         }
     377             : 
     378     9750360 :         if ( hReverb != NULL )
     379             :         {
     380     4812660 :             if ( ( error = ivas_reverb_process( hReverb, transport_config, 0, output, p_reverb_signal, subframe_idx ) ) != IVAS_ERR_OK )
     381             :             {
     382           0 :                 return error;
     383             :             }
     384             :         }
     385             : 
     386             :         /* Render subframe */
     387     9750360 :         if ( ( error = TDREND_GetMix( hBinRendererTd, output, subframe_length, subframe_idx ) ) != IVAS_ERR_OK )
     388             :         {
     389           0 :             return error;
     390             :         }
     391             : 
     392             :         /* Advance subframe pointer */
     393     9750360 :         c_indx = 0;
     394    21784320 :         for ( nS = 0; nS < num_src; nS++ )
     395             :         {
     396    12033960 :             if ( !( ivas_format == MC_FORMAT && nS == lfe_idx ) ) /* Skip LFE for MC */
     397             :             {
     398    11923440 :                 hBinRendererTd->Sources[c_indx]->InputFrame_p += subframe_length;
     399    11923440 :                 c_indx++;
     400             :             }
     401             :         }
     402             : 
     403             :         /* update combined orientation access index */
     404     9750360 :         ivas_combined_orientation_update_index( hCombinedOrientationData, subframe_length );
     405             :     }
     406             : 
     407     6091464 :     if ( hReverb != NULL )
     408             :     {
     409             :         /* add reverb to rendered signals */
     410     3006684 :         v_add( reverb_signal[0], output[0], output[0], output_frame );
     411     3006684 :         v_add( reverb_signal[1], output[1], output[1], output_frame );
     412             :     }
     413             : 
     414     6091464 :     return IVAS_ERR_OK;
     415             : }
     416             : 
     417             : 
     418             : /*---------------------------------------------------------------------*
     419             :  * TDREND_GetMix()
     420             :  *
     421             :  * Render one 5 ms subframe from the mixer
     422             :  *---------------------------------------------------------------------*/
     423             : 
     424    10283808 : ivas_error TDREND_GetMix(
     425             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle                        */
     426             :     float *output[],                                   /* i/o: ISM object synth / rendered output in 0,1 */
     427             :     const int16_t subframe_length,                     /* i/o: subframe length                           */
     428             :     const int16_t subframe_idx                         /* i  : Subframe index to 5 ms subframe           */
     429             : )
     430             : {
     431             :     int16_t i;
     432             :     TDREND_SRC_t *Src_p;
     433             :     TDREND_SRC_SPATIAL_t *SrcSpatial_p;
     434             :     TDREND_SRC_REND_t *SrcRend_p;
     435             :     ivas_error error;
     436             :     float output_buf[2][L_SPATIAL_SUBFR_48k]; /* Temp buffer for left/right rendered signal */
     437             :     float hrf_left_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH];
     438             :     float hrf_right_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH];
     439             :     int16_t intp_count;
     440             :     int16_t currShift, prevShift, transition_len, length_in2;
     441             : 
     442    10283808 :     error = IVAS_ERR_OK;
     443             : 
     444             :     /* Clear the output buffer to accumulate rendered sources */
     445    10283808 :     set_f( output_buf[0], 0.0f, subframe_length );
     446    10283808 :     set_f( output_buf[1], 0.0f, subframe_length );
     447             : 
     448             :     /* Clear interpolation buffers and counter */
     449    10283808 :     set_f( hrf_left_delta, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
     450    10283808 :     set_f( hrf_right_delta, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
     451    10283808 :     intp_count = 0;
     452             : 
     453             :     /* Create the mix */
     454             :     /* Loop through the source list and render each source */
     455    23858655 :     for ( i = 0; i < hBinRendererTd->NumOfSrcs; i++ )
     456             :     {
     457    13574847 :         Src_p = hBinRendererTd->Sources[i];
     458    13574847 :         SrcSpatial_p = Src_p->SrcSpatial_p;
     459    13574847 :         SrcRend_p = Src_p->SrcRend_p;
     460             : 
     461             :         /* Update rendering params if needed */
     462    13574847 :         if ( ( SrcRend_p->PlayStatus == TDREND_PLAYSTATUS_PLAYING ) && ( hBinRendererTd->Listener_p->PoseUpdated || SrcSpatial_p->Updated ) )
     463             :         {
     464     9857616 :             TDREND_SRC_REND_UpdateFiltersFromSpatialParams( hBinRendererTd, SrcRend_p, SrcSpatial_p, Src_p->hrf_left_prev,
     465     9857616 :                                                             Src_p->hrf_right_prev, hrf_left_delta, hrf_right_delta, &intp_count, &Src_p->filterlength, &Src_p->itd, &Src_p->Gain, Src_p );
     466             : 
     467             :             /* For large ITD values at lower sampling rate, check if the transition can be done */
     468     9857616 :             if ( Src_p->itd * Src_p->previtd < 0 )
     469             :             {
     470      206419 :                 currShift = (int16_t) abs( Src_p->itd );
     471      206419 :                 prevShift = (int16_t) abs( Src_p->previtd );
     472      206419 :                 transition_len = subframe_length - max( 0, SFX_SPAT_BIN_SINC_M - currShift );
     473      206419 :                 length_in2 = transition_len - (int16_t) ( ( (float) ( transition_len * prevShift ) / ( (float) ( prevShift + currShift ) ) ) + 0.5f ) - currShift;
     474      206419 :                 if ( length_in2 <= 0 )
     475             :                 {
     476             :                     /* Subframe too short for ITD transition -- change to ITD=0 and push the rest of the transition to next subframe */
     477           0 :                     Src_p->itd = 0;
     478             :                 }
     479             :             }
     480             :         }
     481             : 
     482             :         /* Render source if needed */
     483    13574847 :         if ( ( SrcRend_p->InputAvailable == TRUE ) && ( SrcRend_p->PlayStatus == TDREND_PLAYSTATUS_PLAYING ) )
     484             :         {
     485    13574847 :             error = TDREND_REND_RenderSourceHRFilt( Src_p, hrf_left_delta, hrf_right_delta, intp_count, output_buf, subframe_length );
     486             :         }
     487             :     }
     488             : 
     489             :     /* Populate output variable */
     490    10283808 :     mvr2r( output_buf[0], output[0] + subframe_idx * subframe_length, subframe_length ); /* Left */
     491    10283808 :     mvr2r( output_buf[1], output[1] + subframe_idx * subframe_length, subframe_length ); /* Right */
     492             : 
     493             :     /* Clear the PoseUpdated and Source position update flags */
     494    10283808 :     TDREND_Clear_Update_flags( hBinRendererTd );
     495             : 
     496    10283808 :     return error;
     497             : }
     498             : 
     499             : 
     500             : /*---------------------------------------------------------------------*
     501             :  * TDREND_Clear_Update_flags()
     502             :  *
     503             :  * Initializes the audio mixer module
     504             :  *---------------------------------------------------------------------*/
     505             : 
     506    10283808 : static void TDREND_Clear_Update_flags(
     507             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd /* i/o: TD renderer handle */
     508             : )
     509             : {
     510             :     int16_t i;
     511             : 
     512    10283808 :     hBinRendererTd->Listener_p->PoseUpdated = FALSE;
     513             : 
     514    23858655 :     for ( i = 0; i < hBinRendererTd->NumOfSrcs; i++ )
     515             :     {
     516    13574847 :         hBinRendererTd->Sources[i]->SrcSpatial_p->Updated = FALSE;
     517    13574847 :         hBinRendererTd->Sources[i]->SrcRend_p->SrcGainUpdated = FALSE;
     518             :     }
     519             : 
     520    10283808 :     return;
     521             : }
     522             : 
     523             : 
     524             : /*---------------------------------------------------------------------*
     525             :  * TDREND_Update_object_positions()
     526             :  *
     527             :  * Update object position(s)
     528             :  *---------------------------------------------------------------------*/
     529             : 
     530     5792274 : ivas_error TDREND_Update_object_positions(
     531             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD Renderer handle               */
     532             :     const int16_t num_src,                             /* i  : number of sources to render      */
     533             :     const IVAS_FORMAT in_format,                       /* i  : Format of input sources          */
     534             :     const ISM_METADATA_HANDLE *hIsmMetaData            /* i  : Input metadata for ISM objects   */
     535             : )
     536             : {
     537             : #ifndef NONBE_1377_REND_DIRATT_CONF
     538             :     TDREND_DirAtten_t *DirAtten_p;
     539             : #endif
     540             :     int16_t nS;
     541             :     float Pos[3];
     542             :     float Dir[3];
     543             :     ivas_error error;
     544             : #ifndef NONBE_1377_REND_DIRATT_CONF
     545             :     DirAtten_p = hBinRendererTd->DirAtten_p;
     546             : #endif
     547             : 
     548             :     /* For each source, write the frame data to the source object*/
     549    13299663 :     for ( nS = 0; nS < num_src; nS++ )
     550             :     {
     551     7507389 :         if ( in_format == ISM_FORMAT || in_format == MASA_ISM_FORMAT || in_format == SBA_ISM_FORMAT )
     552             :         {
     553             :             /* Update the source positions */
     554             :             /* Source position and direction */
     555     5876853 :             angles_to_vec( hIsmMetaData[nS]->radius, hIsmMetaData[nS]->azimuth, hIsmMetaData[nS]->elevation, Pos );
     556     5876853 :             angles_to_vec( 1.0f, hIsmMetaData[nS]->yaw, hIsmMetaData[nS]->pitch, Dir );
     557             : 
     558     5876853 :             if ( ( error = TDREND_MIX_SRC_SetPos( hBinRendererTd, nS, Pos ) ) != IVAS_ERR_OK )
     559             :             {
     560           0 :                 return error;
     561             :             }
     562             : 
     563             : #ifndef NONBE_1377_REND_DIRATT_CONF
     564             :             if ( ( error = TDREND_MIX_SRC_SetDirAtten( hBinRendererTd, nS, DirAtten_p ) ) != IVAS_ERR_OK )
     565             :             {
     566             :                 return error;
     567             :             }
     568             : #endif
     569     5876853 :             if ( ( error = TDREND_MIX_SRC_SetGain( hBinRendererTd, nS, hIsmMetaData[nS]->gain ) ) != IVAS_ERR_OK )
     570             :             {
     571           0 :                 return error;
     572             :             }
     573             : 
     574     5876853 :             if ( hIsmMetaData[nS]->non_diegetic_flag )
     575             :             {
     576        2484 :                 Pos[0] = 0;
     577        2484 :                 Pos[1] = hIsmMetaData[nS]->azimuth / 90.f;
     578        2484 :                 Pos[2] = 0;
     579        2484 :                 if ( ( error = TDREND_MIX_SRC_SetPos( hBinRendererTd, nS, Pos ) ) != IVAS_ERR_OK )
     580             :                 {
     581           0 :                     return error;
     582             :                 }
     583        2484 :                 hBinRendererTd->Sources[nS]->SrcSpatial_p->PosType = TDREND_POSTYPE_NON_DIEGETIC;
     584             :             }
     585             :             else
     586             :             {
     587     5874369 :                 hBinRendererTd->Sources[nS]->SrcSpatial_p->PosType = TDREND_POSTYPE_ABSOLUTE;
     588             :             }
     589             : 
     590     5876853 :             if ( ( error = TDREND_MIX_SRC_SetDir( hBinRendererTd, nS, Dir ) ) != IVAS_ERR_OK )
     591             :             {
     592           0 :                 return error;
     593             :             }
     594             :         }
     595             :     }
     596             : 
     597     5792274 :     return IVAS_ERR_OK;
     598             : }
     599             : 
     600             : 
     601             : /*---------------------------------------------------------------------*
     602             :  * TDREND_Update_listener_orientation()
     603             :  *
     604             :  * Update listener orientation (s)
     605             :  *---------------------------------------------------------------------*/
     606             : 
     607    10283808 : ivas_error TDREND_Update_listener_orientation(
     608             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD Renderer handle    */
     609             :     const int16_t headRotEnabled,                      /* i  : Headrotation flag     */
     610             :     const IVAS_QUATERNION *headPosition,               /* i  : Listener orientation  */
     611             :     const IVAS_VECTOR3 *Pos                            /* i  : Listener Position     */
     612             : )
     613             : {
     614             :     float FrontVec[3];
     615             :     float UpVec[3];
     616             :     float Rmat[3][3];
     617             :     float Pos_p[3];
     618             :     ivas_error error;
     619             : 
     620    10283808 :     if ( headRotEnabled )
     621             :     {
     622             :         /* Obtain head rotation matrix */
     623     5187447 :         QuatToRotMat( *headPosition, Rmat );
     624             :         /* Apply rotation matrix to looking vector [1;0;0] */
     625     5187447 :         FrontVec[0] = Rmat[0][0];
     626     5187447 :         FrontVec[1] = Rmat[0][1];
     627     5187447 :         FrontVec[2] = Rmat[0][2];
     628             :         /* Apply rotation matrix to up vector [0;0;1] */
     629     5187447 :         UpVec[0] = Rmat[2][0];
     630     5187447 :         UpVec[1] = Rmat[2][1];
     631     5187447 :         UpVec[2] = Rmat[2][2];
     632     5187447 :         if ( Pos != NULL )
     633             :         {
     634             :             /* Input position   */
     635     5187447 :             Pos_p[0] = ( *Pos ).x;
     636     5187447 :             Pos_p[1] = ( *Pos ).y;
     637     5187447 :             Pos_p[2] = ( *Pos ).z;
     638             :         }
     639             :         else
     640             :         {
     641             :             /* Listener at the origin   */
     642           0 :             Pos_p[0] = 0.0f;
     643           0 :             Pos_p[1] = 0.0f;
     644           0 :             Pos_p[2] = 0.0f;
     645             :         }
     646             :     }
     647             :     else
     648             :     {
     649             :         /* Oriented with looking vector along the x axis */
     650     5096361 :         FrontVec[0] = 1.0f;
     651     5096361 :         FrontVec[1] = 0.0f;
     652     5096361 :         FrontVec[2] = 0.0f;
     653             :         /* Oriented with up vector along the z axis      */
     654     5096361 :         UpVec[0] = 0.0f;
     655     5096361 :         UpVec[1] = 0.0f;
     656     5096361 :         UpVec[2] = 1.0f;
     657             :         /* Listener at the origin   */
     658     5096361 :         Pos_p[0] = 0.0f;
     659     5096361 :         Pos_p[1] = 0.0f;
     660     5096361 :         Pos_p[2] = 0.0f;
     661             :     }
     662             : 
     663             :     /* Set the listener position and orientation:*/
     664    10283808 :     TDREND_MIX_LIST_SetPos( hBinRendererTd, Pos_p );
     665    10283808 :     error = TDREND_MIX_LIST_SetOrient( hBinRendererTd, FrontVec, UpVec );
     666             : 
     667    10283808 :     return error;
     668             : }
     669             : 
     670             : 
     671             : /*---------------------------------------------------------------------*
     672             :  * ivas_td_binaural_open_ext()
     673             :  *
     674             :  *
     675             :  *---------------------------------------------------------------------*/
     676             : 
     677       23382 : ivas_error ivas_td_binaural_open_ext(
     678             :     TDREND_WRAPPER *pTDRend,
     679             :     AUDIO_CONFIG inConfig,
     680             :     RENDER_CONFIG_DATA *hRendCfg, /* i  : Renderer configuration */
     681             :     LSSETUP_CUSTOM_STRUCT *customLsInput,
     682             : #ifdef NONBE_1377_REND_DIRATT_CONF
     683             :     const int32_t outFs,    /* i: output sampling rate */
     684             :     const int16_t object_id /* i: Object ID */
     685             : )
     686             : #else
     687             :     const int32_t outFs )
     688             : #endif
     689             : {
     690             :     int16_t nchan_transport;
     691             :     AUDIO_CONFIG transport_config;
     692             :     IVAS_FORMAT ivas_format;
     693             :     IVAS_OUTPUT_SETUP hTransSetup;
     694             :     ivas_error error;
     695             : 
     696       23382 :     float *distAtt = NULL;
     697       23382 :     float *directivity = NULL;
     698             : 
     699       23382 :     if ( inConfig != IVAS_AUDIO_CONFIG_LS_CUSTOM )
     700             :     {
     701       23238 :         if ( ( error = getAudioConfigNumChannels( inConfig, &nchan_transport ) ) != IVAS_ERR_OK )
     702             :         {
     703           0 :             return error;
     704             :         }
     705             :     }
     706             :     else
     707             :     {
     708         144 :         nchan_transport = customLsInput->num_spk;
     709             :     }
     710             : 
     711       23382 :     transport_config = inConfig;
     712       23382 :     ivas_format = ( getAudioConfigType( inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) ? MC_FORMAT : ISM_FORMAT;
     713             : 
     714       23382 :     hTransSetup.ls_azimuth = NULL;
     715       23382 :     hTransSetup.ls_elevation = NULL;
     716             : 
     717       23382 :     if ( inConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM )
     718             :     {
     719         144 :         hTransSetup.ls_azimuth = customLsInput->ls_azimuth;
     720         144 :         hTransSetup.ls_elevation = customLsInput->ls_elevation;
     721             :     }
     722             : 
     723       23382 :     if ( NULL != hRendCfg )
     724             :     {
     725             : #ifdef NONBE_1377_REND_DIRATT_CONF
     726       14592 :         directivity = hRendCfg->directivity + 3 * object_id;
     727             : #else
     728             :         directivity = hRendCfg->directivity;
     729             : #endif
     730       14592 :         distAtt = hRendCfg->distAtt;
     731             :     }
     732             : 
     733       23382 :     return ivas_td_binaural_open_unwrap( pTDRend->hHrtfTD, outFs, nchan_transport, ivas_format, transport_config, directivity, distAtt, hTransSetup, &pTDRend->hBinRendererTd, &pTDRend->binaural_latency_ns );
     734             : }
     735             : 
     736             : 
     737             : /*---------------------------------------------------------------------*
     738             :  * ivas_td_binaural_renderer_ext()
     739             :  *
     740             :  * Receives the current frames for the object streams, updates metadata
     741             :  * and renders the current frame.
     742             :  *---------------------------------------------------------------------*/
     743             : 
     744     6091464 : ivas_error ivas_td_binaural_renderer_ext(
     745             :     const TDREND_WRAPPER *pTDRend,                               /* i  : TD Renderer wrapper structure           */
     746             :     const AUDIO_CONFIG inConfig,                                 /* i  : Input audio configuration               */
     747             :     const LSSETUP_CUSTOM_STRUCT *customLsInput,                  /* i  : Input custom loudspeaker layout         */
     748             :     const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData, /* i  : Combined head and external orientations */
     749             :     const IVAS_ISM_METADATA *currentPos,                         /* i  : Object position                         */
     750             :     const REVERB_HANDLE hReverb,                                 /* i  : Reverberator handle                     */
     751             :     const int16_t ism_md_subframe_update_ext,                    /* i  : Metadata Delay in subframes to sync with audio delay */
     752             :     const int32_t output_Fs,                                     /* i  : output sampling rate                                    */
     753             :     const int16_t output_frame,                                  /* i  : output frame length                     */
     754             :     float output[][L_FRAME48k]                                   /* i/o: SCE channels / Binaural synthesis       */
     755             : )
     756             : {
     757             :     ISM_METADATA_FRAME hIsmMetaDataFrame;
     758             :     ISM_METADATA_HANDLE hIsmMetaData[1];
     759             :     int16_t lfe_idx;
     760             :     int16_t num_src;
     761             :     IVAS_FORMAT ivas_format;
     762             :     IVAS_REND_AudioConfigType inConfigType;
     763             :     AUDIO_CONFIG transport_config;
     764             :     ivas_error error;
     765             :     float *p_output[MAX_OUTPUT_CHANNELS];
     766             :     int16_t ch;
     767             : 
     768   103554888 :     for ( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ )
     769             :     {
     770    97463424 :         p_output[ch] = output[ch];
     771             :     }
     772             : 
     773     6091464 :     push_wmops( "ivas_td_binaural_renderer_ext" );
     774             : 
     775     6091464 :     inConfigType = getAudioConfigType( inConfig );
     776     6091464 :     lfe_idx = LFE_CHANNEL;
     777     6091464 :     hIsmMetaData[0] = NULL;
     778             : 
     779             : 
     780     6091464 :     if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED )
     781             :     {
     782      147144 :         ivas_format = MC_FORMAT;
     783      147144 :         transport_config = inConfig;
     784      147144 :         if ( inConfig != IVAS_AUDIO_CONFIG_LS_CUSTOM )
     785             :         {
     786       69048 :             if ( ( error = getAudioConfigNumChannels( inConfig, &num_src ) ) != IVAS_ERR_OK )
     787             :             {
     788           0 :                 return error;
     789             :             }
     790             :         }
     791             :         else
     792             :         {
     793       78096 :             lfe_idx = ( customLsInput->num_lfe > 0 ) ? customLsInput->lfe_idx[0] : -1;
     794       78096 :             num_src = customLsInput->num_spk + customLsInput->num_lfe;
     795             :         }
     796             :     }
     797             :     else
     798             :     {
     799     5944320 :         ivas_format = ISM_FORMAT;
     800     5944320 :         num_src = 1;
     801     5944320 :         transport_config = IVAS_AUDIO_CONFIG_ISM1;
     802     5944320 :         hIsmMetaData[0] = &hIsmMetaDataFrame;
     803     5944320 :         hIsmMetaData[0]->azimuth = currentPos->azimuth;
     804     5944320 :         hIsmMetaData[0]->elevation = currentPos->elevation;
     805     5944320 :         hIsmMetaData[0]->yaw = currentPos->yaw;
     806     5944320 :         hIsmMetaData[0]->pitch = currentPos->pitch;
     807     5944320 :         hIsmMetaData[0]->radius = currentPos->radius;
     808     5944320 :         hIsmMetaData[0]->gain = 1.0f;
     809             : 
     810     5944320 :         hIsmMetaData[0]->non_diegetic_flag = currentPos->non_diegetic_flag;
     811             :     }
     812             : 
     813     6091464 :     if ( ( error = ivas_td_binaural_renderer_unwrap( hReverb, transport_config, pTDRend->hBinRendererTd, num_src, lfe_idx, ivas_format, hIsmMetaData, *hCombinedOrientationData,
     814     6091464 :                                                      ism_md_subframe_update_ext, p_output, output_frame, (int16_t) ( ( output_frame * FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) / output_Fs ) ) ) != IVAS_ERR_OK )
     815             :     {
     816           0 :         return error;
     817             :     }
     818             : 
     819     6091464 :     pop_wmops();
     820             : 
     821     6091464 :     return IVAS_ERR_OK;
     822             : }
     823             : 
     824             : 
     825             : /*---------------------------------------------------------------------*
     826             :  * angles_to_vec()
     827             :  *
     828             :  * Convert azimuth and elevation angles to position/orientation vector
     829             :  *---------------------------------------------------------------------*/
     830             : 
     831    11755143 : static void angles_to_vec(
     832             :     const float radius,    /* i  : radius                              */
     833             :     const float azimuth,   /* i  : Azimuth angle                       */
     834             :     const float elevation, /* i  : Elevation angle                     */
     835             :     float *vec             /* o  : Pos/Dir vector                      */
     836             : )
     837             : {
     838    11755143 :     vec[0] = radius * cosf( elevation * PI_OVER_180 ) * cosf( azimuth * PI_OVER_180 );
     839    11755143 :     vec[1] = radius * cosf( elevation * PI_OVER_180 ) * sinf( azimuth * PI_OVER_180 );
     840    11755143 :     vec[2] = radius * sinf( elevation * PI_OVER_180 );
     841             : 
     842    11755143 :     return;
     843             : }

Generated by: LCOV version 1.14