LCOV - code coverage report
Current view: top level - lib_rend - ivas_objectRenderer_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ da9cc8ead0679b4682d329fdff98cf1616159273 Lines: 380 424 89.6 %
Date: 2025-10-13 22:24:20 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_fx.h"
      37             : #include "ivas_prot_rend_fx.h"
      38             : #include <math.h>
      39             : #include "ivas_rom_com.h"
      40             : #include "wmc_auto.h"
      41             : #include "ivas_prot_fx.h"
      42             : #include "debug.h"
      43             : 
      44             : 
      45             : /*---------------------------------------------------------------------*
      46             :  * Local function prototypes
      47             :  *---------------------------------------------------------------------*/
      48             : 
      49             : static void TDREND_Clear_Update_flags_fx(
      50             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd /* i/o: TD renderer handle */
      51             : );
      52             : 
      53             : 
      54             : static void angles_to_vec_fx(
      55             :     const Word16 radius,    /* i  : radius                              */
      56             :     const Word32 azimuth,   /* i  : Azimuth angle                       */
      57             :     const Word32 elevation, /* i  : Elevation angle                     */
      58             :     Word32 *vec             /* o  : Pos/Dir vector                      */
      59             : );
      60             : 
      61             : /*---------------------------------------------------------------------*
      62             :  * ivas_td_binaural_open_unwrap()
      63             :  *
      64             :  * Call TD open/init function without st_ivas
      65             :  *---------------------------------------------------------------------*/
      66             : 
      67         939 : ivas_error ivas_td_binaural_open_unwrap_fx(
      68             :     TDREND_HRFILT_FiltSet_t **hHrtfTD,                  /* i/o: HR filter model (from file or NULL) */
      69             :     const Word32 output_Fs,                             /* i  : Output sampling rate                */
      70             :     const Word16 nchan_transport,                       /* i  : Number of channels                  */
      71             :     const IVAS_FORMAT ivas_format,                      /* i  : IVAS format (ISM/MC)                */
      72             :     const AUDIO_CONFIG transport_config,                /* i  : Transport configuration             */
      73             :     const Word16 *directivity,                          /* i  : Directivity pattern (used for ISM)  */
      74             :     const Word32 *distAtt,                              /* i  : Distance attenuation (used for ISM) */
      75             :     const IVAS_OUTPUT_SETUP hTransSetup,                /* i  : Loudspeaker layout                  */
      76             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd, /* o  : TD renderer handle                  */
      77             :     Word32 *binaural_latency_ns,                        /* i  : Binauralization delay               */
      78             :     Word16 *SrcInd )
      79             : {
      80             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE pBinRendTd;
      81             :     TDREND_PosType_t PosType;
      82             :     Word16 nS;
      83             :     const Word32 *ls_azimuth_fx, *ls_elevation_fx;
      84             :     Word32 Pos_fx[3]; // Q25
      85             :     Word32 Dir_fx[3]; // Q30
      86             :     TDREND_DirAtten_t *DirAtten_p;
      87             :     TDREND_DistAtten_t DistAtten;
      88             :     Word16 nchan_rend;
      89             :     ivas_error error;
      90             : 
      91         939 :     error = IVAS_ERR_OK;
      92             : 
      93         939 :     IF( ( pBinRendTd = malloc( sizeof( BINAURAL_TD_OBJECT_RENDERER ) ) ) == NULL )
      94             :     {
      95           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
      96             :     }
      97         939 :     IF( ( pBinRendTd->TdRend_MixSpatSpec_p = malloc( sizeof( TDREND_MixSpatSpec_t ) ) ) == NULL )
      98             :     {
      99           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
     100             :     }
     101         939 :     IF( ( pBinRendTd->DirAtten_p = malloc( sizeof( TDREND_DirAtten_t ) ) ) == NULL )
     102             :     {
     103           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
     104             :     }
     105         939 :     IF( ( pBinRendTd->Listener_p = malloc( sizeof( TDREND_MIX_Listener_t ) ) ) == NULL )
     106             :     {
     107           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
     108             :     }
     109             : 
     110         939 :     pBinRendTd->NumOfSrcs = 0;
     111         939 :     pBinRendTd->MaxSrcInd = -1;
     112             : 
     113         939 :     move16();
     114         939 :     move16();
     115             :     /* Mixer spatial setup */
     116         939 :     pBinRendTd->TdRend_MixSpatSpec_p->UseCommonDistAttenModel = TRUE;
     117         939 :     move16();
     118         939 :     pBinRendTd->TdRend_MixSpatSpec_p->DistAttenModel = 0; /* 0=Turned off, else use TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED */
     119         939 :     move16();
     120             : 
     121         939 :     IF( NE_32( ( error = TDREND_MIX_Init_fx( pBinRendTd, hHrtfTD, pBinRendTd->TdRend_MixSpatSpec_p, output_Fs ) ), IVAS_ERR_OK ) )
     122             :     {
     123           0 :         return error;
     124             :     }
     125             : 
     126             :     /* Set the attenuation (or can set MixSpatSpec.DistAttenModel above) */
     127         939 :     IF( NE_32( ( error = TDREND_MIX_SetDistAttenModel( pBinRendTd, TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED ) ), IVAS_ERR_OK ) )
     128             :     {
     129           0 :         return error;
     130             :     }
     131             : 
     132             :     /* Add sources to module and mixer, headphones */
     133         939 :     PosType = TDREND_POSTYPE_ABSOLUTE; /* or TDREND_POSTYPE_RELATIVE_TO_LISTENER */
     134         939 :     move16();
     135         939 :     nchan_rend = nchan_transport;
     136         939 :     move16();
     137         939 :     test();
     138         939 :     if ( EQ_16( ivas_format, MC_FORMAT ) && NE_16( transport_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
     139             :     {
     140          19 :         nchan_rend = sub( nchan_rend, 1 ); /* Skip LFE channel -- added to the others */
     141             :     }
     142             : 
     143        2578 :     FOR( nS = 0; nS < nchan_rend; nS++ )
     144             :     {
     145        1639 :         IF( NE_32( ( error = TDREND_MIX_AddSrc_fx( pBinRendTd, &SrcInd[nS], PosType ) ), IVAS_ERR_OK ) )
     146             :         {
     147           0 :             return error;
     148             :         }
     149             :     }
     150         939 :     IF( EQ_16( ivas_format, MC_FORMAT ) )
     151             :     {
     152          43 :         SWITCH( transport_config )
     153             :         {
     154           7 :             case IVAS_AUDIO_CONFIG_5_1:
     155           7 :                 ls_azimuth_fx = ls_azimuth_CICP6_fx;     // Q22
     156           7 :                 ls_elevation_fx = ls_elevation_CICP6_fx; // Q22
     157           7 :                 BREAK;
     158          12 :             case IVAS_AUDIO_CONFIG_7_1:
     159          12 :                 ls_azimuth_fx = ls_azimuth_CICP12_fx;     // Q22
     160          12 :                 ls_elevation_fx = ls_elevation_CICP12_fx; // Q22
     161          12 :                 BREAK;
     162           0 :             case IVAS_AUDIO_CONFIG_5_1_2:
     163           0 :                 ls_azimuth_fx = ls_azimuth_CICP14_fx;     // Q22
     164           0 :                 ls_elevation_fx = ls_elevation_CICP14_fx; // Q22
     165           0 :                 BREAK;
     166           0 :             case IVAS_AUDIO_CONFIG_5_1_4:
     167           0 :                 ls_azimuth_fx = ls_azimuth_CICP16_fx;     // Q22
     168           0 :                 ls_elevation_fx = ls_elevation_CICP16_fx; // Q22
     169           0 :                 BREAK;
     170           0 :             case IVAS_AUDIO_CONFIG_7_1_4:
     171           0 :                 ls_azimuth_fx = ls_azimuth_CICP19_fx;     // Q22
     172           0 :                 ls_elevation_fx = ls_elevation_CICP19_fx; // Q22
     173           0 :                 BREAK;
     174          24 :             case IVAS_AUDIO_CONFIG_LS_CUSTOM:
     175          24 :                 ls_azimuth_fx = hTransSetup.ls_azimuth_fx;     // Q22
     176          24 :                 ls_elevation_fx = hTransSetup.ls_elevation_fx; // Q22
     177          24 :                 BREAK;
     178           0 :             default:
     179           0 :                 ls_azimuth_fx = NULL;
     180           0 :                 ls_elevation_fx = NULL;
     181             :         }
     182             : 
     183          43 :         DirAtten_p = pBinRendTd->DirAtten_p;
     184             : 
     185         318 :         FOR( nS = 0; nS < nchan_rend; nS++ )
     186             :         {
     187             :             /* Set source positions according to loudspeaker layout */
     188         275 :             angles_to_vec_fx( ONE_IN_Q9, ls_azimuth_fx[nS], ls_elevation_fx[nS], Pos_fx );
     189             : 
     190         275 :             Dir_fx[0] = ONE_IN_Q30;
     191         275 :             move32();
     192         275 :             Dir_fx[1] = 0;
     193         275 :             move32();
     194         275 :             Dir_fx[2] = 0;
     195         275 :             move32();
     196             :             /* Source directivity info */
     197         275 :             DirAtten_p->ConeInnerAngle_fx = DEG_360_IN_Q22;
     198         275 :             move32();
     199         275 :             DirAtten_p->ConeOuterAngle_fx = DEG_360_IN_Q22;
     200         275 :             move32();
     201         275 :             DirAtten_p->ConeOuterGain_fx = ONE_IN_Q30;
     202         275 :             move32();
     203             : 
     204         275 :             DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED; // Q0
     205         275 :             move16();
     206         275 :             DistAtten.MaxDist_fx = 2113929216; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ /*15.75 in Q27*/
     207         275 :             move32();
     208         275 :             DistAtten.RefDist_fx = ONE_IN_Q30; // Q30
     209         275 :             move32();
     210         275 :             DistAtten.RollOffFactor_fx = ONE_IN_Q30; // Q30
     211         275 :             move32();
     212             : 
     213             :             // TDREND_SRC_SPATIAL_t *SrcSpatial_p = pBinRendTd->Sources[nS]->SrcSpatial_p;
     214         275 :             IF( NE_32( ( error = TDREND_MIX_SRC_SetPos_fx( pBinRendTd, nS, Pos_fx ) ), IVAS_ERR_OK ) )
     215             :             {
     216           0 :                 return error;
     217             :             }
     218         275 :             IF( NE_32( ( error = TDREND_MIX_SRC_SetDir_fx( pBinRendTd, nS, Dir_fx, Q30 ) ), IVAS_ERR_OK ) )
     219             :             {
     220           0 :                 return error;
     221             :             }
     222         275 :             IF( NE_32( ( error = TDREND_MIX_SRC_SetPlayState( pBinRendTd, nS, TDREND_PLAYSTATUS_PLAYING ) ), IVAS_ERR_OK ) )
     223             :             {
     224           0 :                 return error;
     225             :             }
     226             :             /*TDREND_SRC_SPATIAL_t **/ // SrcSpatial_p = pBinRendTd->Sources[nS]->SrcSpatial_p;
     227         275 :             IF( NE_32( ( error = TDREND_MIX_SRC_SetDirAtten_fx( pBinRendTd, nS, DirAtten_p ) ), IVAS_ERR_OK ) )
     228             :             {
     229           0 :                 return error;
     230             :             }
     231         275 :             IF( NE_32( ( error = TDREND_MIX_SRC_SetDistAtten( pBinRendTd, nS, &DistAtten ) ), IVAS_ERR_OK ) )
     232             :             {
     233           0 :                 return error;
     234             :             }
     235             :         }
     236             :     }
     237         939 :     test();
     238         939 :     test();
     239         939 :     IF( EQ_16( ivas_format, ISM_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) || EQ_16( ivas_format, SBA_ISM_FORMAT ) )
     240             :     {
     241         896 :         DirAtten_p = pBinRendTd->DirAtten_p;
     242             : 
     243        2260 :         FOR( nS = 0; nS < nchan_rend; nS++ )
     244             :         {
     245        1364 :             IF( NULL == directivity )
     246             :             {
     247         305 :                 DirAtten_p->ConeInnerAngle_fx = DEG_360_IN_Q22;
     248         305 :                 DirAtten_p->ConeOuterAngle_fx = DEG_360_IN_Q22;
     249         305 :                 DirAtten_p->ConeOuterGain_fx = ONE_IN_Q30;
     250             :             }
     251             :             ELSE
     252             :             {
     253        1059 :                 DirAtten_p->ConeInnerAngle_fx = L_deposit_h( directivity[nS * 3] );                      // 9Q6 -> 9Q22
     254        1059 :                 DirAtten_p->ConeOuterAngle_fx = L_deposit_h( directivity[add( nS * 3, 1 )] );            // 9Q6 -> 9Q22
     255        1059 :                 DirAtten_p->ConeOuterGain_fx = L_shr( L_deposit_h( directivity[add( nS * 3, 2 )] ), 1 ); // 0Q15 -> 1Q30
     256             :             }
     257        1364 :             move32();
     258        1364 :             move32();
     259        1364 :             move32();
     260        1364 :             if ( NULL == distAtt )
     261             :             {
     262         305 :                 DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED; // Q0
     263         305 :                 move16();
     264         305 :                 DistAtten.MaxDist_fx = 2113929216; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ /*15.75 in Q27*/
     265         305 :                 move32();
     266         305 :                 DistAtten.RefDist_fx = ONE_IN_Q30; // Q30
     267         305 :                 move32();
     268         305 :                 DistAtten.RollOffFactor_fx = ONE_IN_Q30; // Q30
     269         305 :                 move32();
     270             :             }
     271             :             else
     272             :             {
     273        1059 :                 DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED; // Q0
     274        1059 :                 DistAtten.MaxDist_fx = distAtt[0];
     275        1059 :                 DistAtten.RefDist_fx = distAtt[1];
     276        1059 :                 DistAtten.RollOffFactor_fx = distAtt[2];
     277             :             }
     278        1364 :             IF( NE_32( ( error = TDREND_MIX_SRC_SetDirAtten_fx( pBinRendTd, nS, DirAtten_p ) ), IVAS_ERR_OK ) )
     279             :             {
     280           0 :                 return error;
     281             :             }
     282        1364 :             IF( NE_32( ( error = TDREND_MIX_SRC_SetDistAtten( pBinRendTd, nS, &DistAtten ) ), IVAS_ERR_OK ) )
     283             :             {
     284           0 :                 return error;
     285             :             }
     286             :         }
     287             :     }
     288             : 
     289         939 :     *hBinRendererTd = pBinRendTd;
     290         939 :     test();
     291         939 :     IF( NE_16( ivas_format, MASA_ISM_FORMAT ) && NE_16( ivas_format, SBA_ISM_FORMAT ) )
     292             :     {
     293             : #ifdef USE_TDREND_16BIT_ROM
     294         769 :         *binaural_latency_ns = L_shr_r( Mpy_32_32_r( ( *hBinRendererTd )->HrFiltSet_p->latency_s_fx, (Word32) 1000000000 ), ( *hBinRendererTd )->HrFiltSet_p->latency_s_Q_fx );
     295             : #else
     296             :         *binaural_latency_ns = Mult_32_32( ( *hBinRendererTd )->HrFiltSet_p->latency_s_fx, 1000000000 /* 1000000000.f in Q0 */ );
     297             : #endif
     298         769 :         move32();
     299             :     }
     300             : 
     301         939 :     return error;
     302             : }
     303             : 
     304             : 
     305             : /*---------------------------------------------------------------------*
     306             :  * ivas_td_binaural_close()
     307             :  *
     308             :  * Close TD Object binaural renderer
     309             :  *---------------------------------------------------------------------*/
     310             : 
     311       19427 : void ivas_td_binaural_close_fx(
     312             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd /* i/o: TD binaural object renderer handle */
     313             : )
     314             : {
     315       19427 :     test();
     316       19427 :     IF( hBinRendererTd == NULL || *hBinRendererTd == NULL )
     317             :     {
     318       18488 :         return;
     319             :     }
     320             : 
     321         939 :     free( ( *hBinRendererTd )->TdRend_MixSpatSpec_p );
     322         939 :     free( ( *hBinRendererTd )->DirAtten_p );
     323             : 
     324         939 :     TDREND_MIX_Dealloc_fx( *hBinRendererTd );
     325             : 
     326         939 :     free( *hBinRendererTd );
     327         939 :     *hBinRendererTd = NULL;
     328             : 
     329         939 :     return;
     330             : }
     331             : 
     332             : 
     333             : /*---------------------------------------------------------------------*
     334             :  * ivas_td_binaural_renderer_unwrap()
     335             :  *
     336             :  * Call ivas_td_binaural_renderer() without st_ivas.
     337             :  *---------------------------------------------------------------------*/
     338             : 
     339      324504 : ivas_error ivas_td_binaural_renderer_unwrap_fx(
     340             :     const REVERB_HANDLE hReverb,                          /* i  : Reverberator handle                                          */
     341             :     const AUDIO_CONFIG transport_config,                  /* i  : Transport configuration                                      */
     342             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd,    /* i/o: TD binaural object renderer handle                           */
     343             :     const Word16 num_src,                                 /* i  : number of sources to render                                  */
     344             :     const Word16 lfe_idx,                                 /* i  : LFE channel index                                            */
     345             :     const IVAS_FORMAT ivas_format,                        /* i  : IVAS format                                                  */
     346             :     ISM_METADATA_HANDLE *hIsmMetaData,                    /* i  : ISM metadata handle                                          */
     347             :     COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientaton data handle                              */
     348             :     const Word16 ism_md_subframe_update,                  /* i  : Number of subframes to delay ism metadata to sync with audio */
     349             :     Word32 *output_fx[],                                  /* i/o: SCE channels / Binaural synthesis   Q11                      */
     350             :     const Word16 output_frame,                            /* i  : output frame length                                          */
     351             :     const Word16 num_subframes                            /* i  : number of subframes to render                                */
     352             : )
     353             : {
     354             :     Word16 subframe_length;
     355             :     Word16 subframe_idx;
     356             :     ivas_error error;
     357             :     Word16 c_indx, nS;
     358             :     Word16 ch;
     359             :     Word16 *enableCombinedOrientation; /* i  : Combined orientation flag            */
     360             :     IVAS_QUATERNION *Quaternions;      /* i  : Head tracking data per subframe      */
     361             :     IVAS_VECTOR3 *Pos;                 /* i  : Listener position data per subframe  */
     362             : 
     363             : 
     364             :     Word32 reverb_signal_fx[BINAURAL_CHANNELS][L_FRAME48k];
     365             :     Word32 *p_reverb_signal_fx[BINAURAL_CHANNELS];
     366             : 
     367      324504 :     enableCombinedOrientation = NULL;
     368      324504 :     Quaternions = NULL;
     369      324504 :     Pos = NULL;
     370      324504 :     IF( hCombinedOrientationData != NULL )
     371             :     {
     372      168002 :         enableCombinedOrientation = hCombinedOrientationData->enableCombinedOrientation;
     373      168002 :         Quaternions = hCombinedOrientationData->Quaternions;
     374      168002 :         Pos = hCombinedOrientationData->listenerPos;
     375      168002 :         move16();
     376             :     }
     377             : 
     378      973512 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
     379             :     {
     380      649008 :         p_reverb_signal_fx[ch] = reverb_signal_fx[ch];
     381             :     }
     382             : 
     383      324504 :     subframe_length = idiv1616( output_frame, num_subframes );
     384             : 
     385      324504 :     c_indx = 0;
     386      324504 :     move16();
     387      886568 :     FOR( nS = 0; nS < num_src; nS++ )
     388             :     {
     389      562064 :         test();
     390      562064 :         IF( !( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( nS, lfe_idx ) ) ) /* Skip LFE for MC */
     391             :         {
     392      550564 :             hBinRendererTd->Sources[c_indx]->InputFrame_p_fx = output_fx[nS]; /* Q11 */
     393      550564 :             hBinRendererTd->Sources[c_indx]->SrcRend_p->InputAvailable = TRUE;
     394      550564 :             move16();
     395      550564 :             c_indx = add( c_indx, 1 );
     396             :         }
     397             :     }
     398             : 
     399      843714 :     FOR( subframe_idx = 0; subframe_idx < num_subframes; subframe_idx++ )
     400             :     {
     401      519210 :         IF( EQ_16( subframe_idx, ism_md_subframe_update ) )
     402             :         {
     403             :             /* Update object position(s) */
     404      324504 :             IF( NE_32( ( error = TDREND_Update_object_positions_fx( hBinRendererTd, num_src, ivas_format, hIsmMetaData ) ), IVAS_ERR_OK ) )
     405             :             {
     406           0 :                 return error;
     407             :             }
     408             :         }
     409             : 
     410             :         /* Update the listener's location/orientation */
     411             :         Word16 tmp_headRotEnabled;
     412      519210 :         tmp_headRotEnabled = 0;
     413      519210 :         move16();
     414             :         Word16 tmp_CombinedOrient_subframe_idx;
     415      519210 :         tmp_CombinedOrient_subframe_idx = 0;
     416      519210 :         move16();
     417      519210 :         IF( enableCombinedOrientation != NULL )
     418             :         {
     419      268805 :             tmp_headRotEnabled = enableCombinedOrientation[hCombinedOrientationData->subframe_idx];
     420      268805 :             move16();
     421      268805 :             tmp_CombinedOrient_subframe_idx = hCombinedOrientationData->subframe_idx;
     422             :         }
     423             : 
     424      519210 :         IF( NE_32( ( error = TDREND_Update_listener_orientation_fx( hBinRendererTd, tmp_headRotEnabled, &Quaternions[tmp_CombinedOrient_subframe_idx], &Pos[tmp_CombinedOrient_subframe_idx] ) ), IVAS_ERR_OK ) )
     425             :         {
     426           0 :             return error;
     427             :         }
     428             : 
     429      519210 :         IF( hReverb != NULL )
     430             :         {
     431             :             Word16 i;
     432             : 
     433     4236400 :             FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i )
     434             :             {
     435     3987200 :                 scale_sig32( output_fx[i], L_FRAME48k, -4 ); // Q11 - 4 = Q7
     436             :             }
     437             : 
     438      249200 :             IF( NE_32( ( error = ivas_reverb_process_fx( hReverb, transport_config, 0, output_fx, p_reverb_signal_fx, subframe_idx ) ), IVAS_ERR_OK ) ) // Q p_reverb_signal_fx = Q output_fx - 2 = 5
     439             :             {
     440           0 :                 return error;
     441             :             }
     442             : 
     443     4236400 :             FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i )
     444             :             {
     445     3987200 :                 scale_sig32( output_fx[i], L_FRAME48k, 4 ); // Q7 + 4 = Q11
     446             :             }
     447             : 
     448      747600 :             FOR( i = 0; i < BINAURAL_CHANNELS; ++i )
     449             :             {
     450      498400 :                 scale_sig32( p_reverb_signal_fx[i] + subframe_idx * hReverb->full_block_size, hReverb->full_block_size, 2 + 4 ); // Q5 + 6 = Q11
     451             :             }
     452             :         }
     453             : 
     454             :         /* Render subframe */
     455             : 
     456      519210 :         IF( NE_32( ( error = TDREND_GetMix_fx( hBinRendererTd, output_fx, subframe_length, subframe_idx ) ), IVAS_ERR_OK ) )
     457             :         {
     458           0 :             return error;
     459             :         }
     460             : 
     461             : 
     462             :         /* Advance subframe pointer */
     463      519210 :         c_indx = 0;
     464      519210 :         move16();
     465     1418570 :         FOR( nS = 0; nS < num_src; nS++ )
     466             :         {
     467      899360 :             test();
     468      899360 :             IF( !( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( nS, lfe_idx ) ) ) /* Skip LFE for MC */
     469             :             {
     470      880960 :                 hBinRendererTd->Sources[c_indx]->InputFrame_p_fx += subframe_length;
     471      880960 :                 c_indx = add( c_indx, 1 );
     472             :             }
     473             :         }
     474             : 
     475             :         /* update combined orientation access index */
     476      519210 :         ivas_combined_orientation_update_index( hCombinedOrientationData, subframe_length );
     477             :     }
     478             : 
     479      324504 :     IF( hReverb != NULL )
     480             :     {
     481      155750 :         v_add_32( reverb_signal_fx[0], output_fx[0], output_fx[0], output_frame ); // Q11
     482      155750 :         v_add_32( reverb_signal_fx[1], output_fx[1], output_fx[1], output_frame ); // Q11
     483             :     }
     484             : 
     485      324504 :     return IVAS_ERR_OK;
     486             : }
     487             : 
     488             : 
     489             : /*---------------------------------------------------------------------*
     490             :  * TDREND_GetMix()
     491             :  *
     492             :  * Render one 5 ms subframe from the mixer
     493             :  *---------------------------------------------------------------------*/
     494             : 
     495      685912 : ivas_error TDREND_GetMix_fx(
     496             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle                                           */
     497             :     Word32 *output[],                                  /* i/o: ISM object synth / rendered output in 0,1       Q11          */
     498             :     const Word16 subframe_length,                      /* i/o: subframe length                                              */
     499             :     const Word16 subframe_idx                          /* i  : Subframe index to 5 ms subframe                              */
     500             : )
     501             : {
     502             :     Word16 i;
     503             :     TDREND_SRC_t *Src_p;
     504             :     TDREND_SRC_SPATIAL_t *SrcSpatial_p;
     505             :     TDREND_SRC_REND_t *SrcRend_p;
     506             :     ivas_error error;
     507             :     Word32 output_buf[2][L_SPATIAL_SUBFR_48k]; /* Temp buffer for left/right rendered signal */
     508             :     Word32 hrf_left_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH];
     509             :     Word32 hrf_right_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH];
     510             :     Word16 intp_count;
     511             : 
     512      685912 :     Word16 hrf_left_delta_e = 0, hrf_right_delta_e = 0;
     513      685912 :     move16();
     514      685912 :     move16();
     515             : 
     516      685912 :     error = IVAS_ERR_OK;
     517      685912 :     move32();
     518             :     /* Clear the output buffer to accumulate rendered sources */
     519      685912 :     set32_fx( output_buf[0], 0, subframe_length );
     520      685912 :     set32_fx( output_buf[1], 0, subframe_length );
     521             :     /* Clear interpolation buffers and counter */
     522      685912 :     set32_fx( hrf_left_delta, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
     523      685912 :     set32_fx( hrf_right_delta, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
     524             : 
     525      685912 :     intp_count = 0;
     526      685912 :     move16();
     527             : 
     528             :     /* Create the mix */
     529             :     /* Loop through the source list and render each source */
     530     2074139 :     FOR( i = 0; i < hBinRendererTd->NumOfSrcs; i++ )
     531             :     {
     532     1388227 :         Src_p = hBinRendererTd->Sources[i];
     533     1388227 :         SrcSpatial_p = Src_p->SrcSpatial_p;
     534     1388227 :         SrcRend_p = Src_p->SrcRend_p;
     535             : 
     536             :         /* Update rendering params if needed */
     537     1388227 :         test();
     538     1388227 :         test();
     539     1388227 :         IF( EQ_16( SrcRend_p->PlayStatus, TDREND_PLAYSTATUS_PLAYING ) && ( hBinRendererTd->Listener_p->PoseUpdated || SrcSpatial_p->Updated ) )
     540             :         {
     541      917847 :             TDREND_SRC_REND_UpdateFiltersFromSpatialParams_fx( hBinRendererTd, SrcRend_p, SrcSpatial_p,
     542      917847 :                                                                Src_p->hrf_left_prev_fx, &Src_p->hrf_left_prev_e, Src_p->hrf_right_prev_fx, &Src_p->hrf_right_prev_e,
     543             :                                                                hrf_left_delta, &hrf_left_delta_e, hrf_right_delta, &hrf_right_delta_e,
     544             :                                                                &intp_count, &Src_p->filterlength, &Src_p->itd,
     545             :                                                                &Src_p->Gain_fx,
     546             :                                                                Src_p );
     547             :         }
     548             : 
     549             :         /* Render source if needed */
     550     1388227 :         test();
     551     1388227 :         IF( EQ_16( SrcRend_p->InputAvailable, TRUE ) && EQ_16( SrcRend_p->PlayStatus, TDREND_PLAYSTATUS_PLAYING ) )
     552             :         {
     553     1388227 :             error = TDREND_REND_RenderSourceHRFilt_fx( Src_p, hrf_left_delta, &hrf_left_delta_e,
     554             :                                                        hrf_right_delta, &hrf_right_delta_e, intp_count, output_buf, subframe_length );
     555             :         }
     556             :     }
     557             : 
     558             : 
     559             :     /* Populate output variable */
     560      685912 :     Copy32( output_buf[0], output[0] + imult1616( subframe_idx, subframe_length ), subframe_length ); /* Left same Q as Src_p->InputFrame_p_fx  Q11 */
     561      685912 :     Copy32( output_buf[1], output[1] + imult1616( subframe_idx, subframe_length ), subframe_length ); /* Right same Q as Src_p->InputFrame_p_fx Q11 */
     562             : 
     563             :     /* Clear the PoseUpdated and Source position update flags */
     564      685912 :     TDREND_Clear_Update_flags_fx( hBinRendererTd );
     565             : 
     566      685912 :     return error;
     567             : }
     568             : 
     569             : 
     570             : /*---------------------------------------------------------------------*
     571             :  * TDREND_Clear_Update_flags()
     572             :  *
     573             :  * Initializes the audio mixer module
     574             :  *---------------------------------------------------------------------*/
     575             : 
     576      685912 : static void TDREND_Clear_Update_flags_fx(
     577             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd /* i/o: TD renderer handle */
     578             : )
     579             : {
     580             :     Word16 i;
     581             : 
     582      685912 :     hBinRendererTd->Listener_p->PoseUpdated = FALSE;
     583      685912 :     move16();
     584             : 
     585     2074139 :     FOR( i = 0; i < hBinRendererTd->NumOfSrcs; i++ )
     586             :     {
     587     1388227 :         hBinRendererTd->Sources[i]->SrcSpatial_p->Updated = FALSE;
     588     1388227 :         move16();
     589             : #ifdef OBJ_EDITING_API
     590     1388227 :         hBinRendererTd->Sources[i]->SrcRend_p->SrcGainUpdated = FALSE;
     591     1388227 :         move16();
     592             : #endif
     593             :     }
     594             : 
     595      685912 :     return;
     596             : }
     597             : 
     598             : 
     599             : /*---------------------------------------------------------------------*
     600             :  * TDREND_Update_object_positions_fx()
     601             :  *
     602             :  * Update object position(s)
     603             :  *---------------------------------------------------------------------*/
     604             : 
     605      366089 : ivas_error TDREND_Update_object_positions_fx(
     606             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD Renderer handle               */
     607             :     const Word16 num_src,                              /* i  : number of sources to render      */
     608             :     const IVAS_FORMAT in_format,                       /* i  : Format of input sources          */
     609             :     const ISM_METADATA_HANDLE *hIsmMetaData            /* i  : Input metadata for ISM objects   */
     610             : )
     611             : {
     612             : #ifndef NONBE_1377_REND_DIRATT_CONF
     613             :     TDREND_DirAtten_t *DirAtten_p;
     614             : #endif
     615             :     Word16 nS;
     616             :     Word32 Pos_fx[3]; // Q25
     617             :     Word32 Dir_fx[3]; // Q30
     618             :     ivas_error error;
     619             : #ifndef NONBE_1377_REND_DIRATT_CONF
     620             :     DirAtten_p = hBinRendererTd->DirAtten_p;
     621             : #endif
     622             : 
     623             :     /* For each source, write the frame data to the source object*/
     624     1057915 :     FOR( nS = 0; nS < num_src; nS++ )
     625             :     {
     626      691826 :         test();
     627      691826 :         test();
     628      691826 :         IF( EQ_16( in_format, ISM_FORMAT ) || EQ_16( in_format, MASA_ISM_FORMAT ) || EQ_16( in_format, SBA_ISM_FORMAT ) )
     629             :         {
     630             :             /* Update the source positions */
     631             :             /* Source position and direction */
     632      410778 :             angles_to_vec_fx( hIsmMetaData[nS]->radius_fx /*Q9*/, hIsmMetaData[nS]->azimuth_fx, hIsmMetaData[nS]->elevation_fx, Pos_fx );
     633      410778 :             angles_to_vec_fx( ONE_IN_Q14, hIsmMetaData[nS]->yaw_fx, hIsmMetaData[nS]->pitch_fx, Dir_fx );
     634             : 
     635             :             // DirAtten_p->ConeInnerAngle_fx = DEG_360_IN_Q22;
     636             :             // move32();
     637             :             // DirAtten_p->ConeOuterAngle_fx = DEG_360_IN_Q22;
     638             :             // move32();
     639             :             // DirAtten_p->ConeOuterGain_fx = ONE_IN_Q30;
     640             :             // move32();
     641             : 
     642      410778 :             IF( NE_32( ( error = TDREND_MIX_SRC_SetPos_fx( hBinRendererTd, nS, Pos_fx ) ), IVAS_ERR_OK ) )
     643             :             {
     644           0 :                 return error;
     645             :             }
     646             : #ifndef NONBE_1377_REND_DIRATT_CONF
     647             :             IF( NE_32( ( error = TDREND_MIX_SRC_SetDirAtten_fx( hBinRendererTd, nS, DirAtten_p ) ), IVAS_ERR_OK ) )
     648             :             {
     649             :                 return error;
     650             :             }
     651             : #endif
     652             : 
     653      410778 :             IF( hIsmMetaData[nS]->non_diegetic_flag )
     654             :             {
     655         828 :                 Pos_fx[0] = 0;
     656             :                 /* Pos[1] = hIsmMetaData[nS]->azimuth / 90.f; */
     657         828 :                 Pos_fx[1] = L_shl( Mpy_32_32_r( hIsmMetaData[nS]->azimuth_fx, 23860929 /* 1 / 90.f in Q31 */ ), Q3 ); /* Q25 */
     658         828 :                 move32();
     659         828 :                 Pos_fx[2] = 0;
     660         828 :                 move32();
     661             : 
     662         828 :                 IF( NE_32( ( error = TDREND_MIX_SRC_SetPos_fx( hBinRendererTd, nS, Pos_fx ) ), IVAS_ERR_OK ) )
     663             :                 {
     664           0 :                     return error;
     665             :                 }
     666         828 :                 hBinRendererTd->Sources[nS]->SrcSpatial_p->PosType = TDREND_POSTYPE_NON_DIEGETIC;
     667         828 :                 move16();
     668             :             }
     669             :             ELSE
     670             :             {
     671      409950 :                 hBinRendererTd->Sources[nS]->SrcSpatial_p->PosType = TDREND_POSTYPE_ABSOLUTE;
     672      409950 :                 move16();
     673             :             }
     674             : 
     675      410778 :             IF( NE_32( ( error = TDREND_MIX_SRC_SetDir_fx( hBinRendererTd, nS, Dir_fx, Q30 ) ), IVAS_ERR_OK ) )
     676             :             {
     677           0 :                 return error;
     678             :             }
     679             :         }
     680             :     }
     681             : 
     682      366089 :     return IVAS_ERR_OK;
     683             : }
     684             : 
     685             : /*---------------------------------------------------------------------*
     686             :  * TDREND_Update_listener_orientation()
     687             :  *
     688             :  * Update listener orientation (s)
     689             :  *---------------------------------------------------------------------*/
     690             : 
     691      685912 : ivas_error TDREND_Update_listener_orientation_fx(
     692             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD Renderer handle           */
     693             :     const Word16 headRotEnabled,                       /* i  : Headrotation flag            */
     694             :     const IVAS_QUATERNION *headPosition_fx,            /* i  : Listener orientation     Qx  */
     695             :     const IVAS_VECTOR3 *Pos_fx                         /* i  : Listener Position            */
     696             : )
     697             : {
     698             :     Word32 FrontVec_fx[3];
     699             :     Word32 UpVec_fx[3];
     700             :     Word32 Rmat_fx[3][3];
     701             :     Word16 orient_q, headPosition_q;
     702             :     Word32 Pos_p_fx[3];
     703             :     ivas_error error;
     704             : 
     705      685912 :     IF( headRotEnabled )
     706             :     {
     707             :         Word16 Rmat_q;
     708             : 
     709      354498 :         headPosition_q = headPosition_fx->q_fact;
     710      354498 :         move16();
     711             : 
     712             :         /* Obtain head rotation matrix */
     713      354498 :         QuatToRotMat_fx( *headPosition_fx, Rmat_fx ); // Rmat_fx Q: 2*headPosition_q-32
     714      354498 :         Rmat_q = sub( shl( headPosition_q, 1 ), 32 );
     715             : 
     716             :         /* Apply rotation matrix to looking vector [1;0;0] */
     717      354498 :         FrontVec_fx[0] = Rmat_fx[0][0]; // Q Rmat_q
     718      354498 :         move32();
     719      354498 :         FrontVec_fx[1] = Rmat_fx[0][1]; // Q Rmat_q
     720      354498 :         move32();
     721      354498 :         FrontVec_fx[2] = Rmat_fx[0][2]; // Q Rmat_q
     722      354498 :         move32();
     723             : 
     724             :         /* Apply rotation matrix to up vector [0;0;1] */
     725      354498 :         UpVec_fx[0] = Rmat_fx[2][0]; // Q Rmat_q
     726      354498 :         move32();
     727      354498 :         UpVec_fx[1] = Rmat_fx[2][1]; // Q Rmat_q
     728      354498 :         move32();
     729      354498 :         UpVec_fx[2] = Rmat_fx[2][2]; // Q Rmat_q
     730      354498 :         move32();
     731             : 
     732      354498 :         orient_q = Rmat_q;
     733      354498 :         move16();
     734             : 
     735      354498 :         IF( Pos_fx != NULL )
     736             :         {
     737             :             /* Input position   */
     738      354498 :             Pos_p_fx[0] = ( *Pos_fx ).x_fx; // Q Pos_fx->q_fact
     739      354498 :             Pos_p_fx[1] = ( *Pos_fx ).y_fx; // Q Pos_fx->q_fact
     740      354498 :             Pos_p_fx[2] = ( *Pos_fx ).z_fx; // Q Pos_fx->q_fact
     741             :         }
     742             :         ELSE
     743             :         {
     744             :             /* Listener at the origin   */
     745           0 :             Pos_p_fx[0] = 0;
     746           0 :             Pos_p_fx[1] = 0;
     747           0 :             Pos_p_fx[2] = 0;
     748             :         }
     749      354498 :         move32();
     750      354498 :         move32();
     751      354498 :         move32();
     752             :     }
     753             :     ELSE
     754             :     {
     755             :         /* Oriented with looking vector along the x axis */
     756      331414 :         FrontVec_fx[0] = ONE_IN_Q30;
     757      331414 :         move32();
     758      331414 :         FrontVec_fx[1] = 0;
     759      331414 :         move32();
     760      331414 :         FrontVec_fx[2] = 0;
     761      331414 :         move32();
     762             :         /* Oriented with up vector along the z axis      */
     763      331414 :         UpVec_fx[0] = 0;
     764      331414 :         move32();
     765      331414 :         UpVec_fx[1] = 0;
     766      331414 :         move32();
     767      331414 :         UpVec_fx[2] = ONE_IN_Q30;
     768      331414 :         move32();
     769             : 
     770      331414 :         orient_q = Q30;
     771      331414 :         move32();
     772             : 
     773             :         /* Listener at the origin   */
     774      331414 :         Pos_p_fx[0] = 0;
     775      331414 :         move32();
     776      331414 :         Pos_p_fx[1] = 0;
     777      331414 :         move32();
     778      331414 :         Pos_p_fx[2] = 0;
     779      331414 :         move32();
     780             :     }
     781             : 
     782             :     /* Set the listener position and orientation:*/
     783      685912 :     TDREND_MIX_LIST_SetPos_fx( hBinRendererTd, Pos_p_fx );
     784      685912 :     error = TDREND_MIX_LIST_SetOrient_fx( hBinRendererTd, FrontVec_fx, UpVec_fx, orient_q );
     785             : 
     786      685912 :     return error;
     787             : }
     788             : 
     789             : 
     790             : /*---------------------------------------------------------------------*
     791             :  * ivas_td_binaural_open_ext()
     792             :  *
     793             :  *
     794             :  *---------------------------------------------------------------------*/
     795             : 
     796         737 : ivas_error ivas_td_binaural_open_ext_fx(
     797             :     TDREND_WRAPPER *pTDRend,
     798             :     AUDIO_CONFIG inConfig,
     799             :     RENDER_CONFIG_DATA *hRendCfg, /* i  : Renderer configuration */
     800             :     LSSETUP_CUSTOM_STRUCT *customLsInput,
     801             :     const Word32 outFs,
     802             : #ifdef NONBE_1377_REND_DIRATT_CONF
     803             :     const Word16 object_id, /* i: Object ID */
     804             : #endif
     805             :     Word16 *SrcInd,
     806             :     Word16 *num_src )
     807             : {
     808             :     Word16 nchan_transport;
     809             :     AUDIO_CONFIG transport_config;
     810             :     IVAS_FORMAT ivas_format;
     811             :     IVAS_OUTPUT_SETUP hTransSetup;
     812             :     ivas_error error;
     813         737 :     Word32 *distAtt_fx = NULL;
     814         737 :     Word16 *directivity_fx = NULL;
     815             : 
     816         737 :     IF( NE_16( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
     817             :     {
     818         713 :         IF( NE_32( ( error = getAudioConfigNumChannels( inConfig, &nchan_transport ) ), IVAS_ERR_OK ) )
     819             :         {
     820           0 :             return error;
     821             :         }
     822             :     }
     823             :     ELSE
     824             :     {
     825          24 :         nchan_transport = customLsInput->num_spk;
     826          24 :         move16();
     827             :     }
     828         737 :     *num_src = nchan_transport;
     829         737 :     move16();
     830             : 
     831         737 :     transport_config = inConfig;
     832         737 :     move16();
     833         737 :     IF( ( getAudioConfigType( inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) )
     834             :     {
     835          32 :         ivas_format = MC_FORMAT;
     836          32 :         move16();
     837             :     }
     838             :     ELSE
     839             :     {
     840         705 :         ivas_format = ISM_FORMAT;
     841         705 :         move16();
     842             :     }
     843         737 :     hTransSetup.ls_azimuth_fx = NULL;
     844         737 :     hTransSetup.ls_elevation_fx = NULL;
     845             : 
     846         737 :     IF( EQ_16( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
     847             :     {
     848          24 :         hTransSetup.ls_azimuth_fx = customLsInput->ls_azimuth_fx;
     849          24 :         hTransSetup.ls_elevation_fx = customLsInput->ls_elevation_fx;
     850             :     }
     851             : 
     852         737 :     if ( NULL != hRendCfg )
     853             :     {
     854             : #ifdef NONBE_1377_REND_DIRATT_CONF
     855         432 :         directivity_fx = hRendCfg->directivity_fx + 3 * object_id; /* Address calculation -- no BASOPs */
     856             : #else
     857             :         directivity_fx = hRendCfg->directivity_fx;
     858             : #endif
     859         432 :         distAtt_fx = hRendCfg->distAtt_fx;
     860             :     }
     861             : 
     862         737 :     return ivas_td_binaural_open_unwrap_fx( pTDRend->hHrtfTD, outFs, nchan_transport, ivas_format, transport_config, directivity_fx, distAtt_fx, hTransSetup, &pTDRend->hBinRendererTd, &pTDRend->binaural_latency_ns, SrcInd );
     863             : }
     864             : 
     865             : 
     866             : /*---------------------------------------------------------------------*
     867             :  * ivas_td_binaural_renderer_ext()
     868             :  *
     869             :  * Receives the current frames for the object streams, updates metadata
     870             :  * and renders the current frame.
     871             :  *---------------------------------------------------------------------*/
     872             : 
     873      324504 : ivas_error ivas_td_binaural_renderer_ext_fx(
     874             :     const TDREND_WRAPPER *pTDRend,                               /* i  : TD Renderer wrapper structure           */
     875             :     const AUDIO_CONFIG inConfig,                                 /* i  : Input audio configuration               */
     876             :     const LSSETUP_CUSTOM_STRUCT *customLsInput,                  /* i  : Input custom loudspeaker layout         */
     877             :     const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData, /* i  : Combined head and external orientations */
     878             :     const IVAS_ISM_METADATA *currentPos,                         /* i  : Object position                         */
     879             :     const REVERB_HANDLE hReverb,                                 /* i  : Reverberator handle                     */
     880             :     const Word16 ism_md_subframe_update_ext,                     /* i  : Metadata Delay in subframes to sync with audio delay */
     881             :     const Word32 output_Fs,                                      /* i  : output sampling rate                                    */
     882             :     const Word16 output_frame,                                   /* i  : output frame length                     */
     883             :     Word32 output[][L_FRAME48k],                                 /* i/o: SCE channels / Binaural synthesis   Q11 */
     884             :     Word16 *exp )
     885             : {
     886             :     ISM_METADATA_FRAME hIsmMetaDataFrame;
     887             :     ISM_METADATA_HANDLE hIsmMetaData[1];
     888             :     Word16 lfe_idx, exp_tmp;
     889             :     Word16 num_src;
     890             :     IVAS_FORMAT ivas_format;
     891             :     IVAS_REND_AudioConfigType inConfigType;
     892             :     AUDIO_CONFIG transport_config;
     893             :     ivas_error error;
     894             : 
     895             :     Word32 *p_output_fx[MAX_OUTPUT_CHANNELS];
     896     5516568 :     FOR( Word16 i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
     897             :     {
     898     5192064 :         p_output_fx[i] = output[i];
     899             :     }
     900             : 
     901      324504 :     push_wmops( "ivas_td_binaural_renderer_ext" );
     902             : 
     903      324504 :     inConfigType = getAudioConfigType( inConfig );
     904      324504 :     lfe_idx = LFE_CHANNEL;
     905      324504 :     move16();
     906      324504 :     hIsmMetaData[0] = NULL;
     907             : 
     908             : 
     909      324504 :     IF( EQ_32( inConfigType, IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) )
     910             :     {
     911       24504 :         ivas_format = MC_FORMAT;
     912       24504 :         move16();
     913       24504 :         transport_config = inConfig;
     914       24504 :         move16();
     915             : 
     916       24504 :         IF( NE_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
     917             :         {
     918       11500 :             IF( NE_32( ( error = getAudioConfigNumChannels( inConfig, &num_src ) ), IVAS_ERR_OK ) )
     919             :             {
     920           0 :                 return error;
     921             :             }
     922             :         }
     923             :         ELSE
     924             :         {
     925       13004 :             IF( customLsInput->num_lfe > 0 )
     926             :             {
     927           0 :                 lfe_idx = customLsInput->lfe_idx[0];
     928           0 :                 move16();
     929             :             }
     930             :             ELSE
     931             :             {
     932       13004 :                 lfe_idx = -1;
     933       13004 :                 move16();
     934             :             }
     935       13004 :             num_src = add( customLsInput->num_spk, customLsInput->num_lfe );
     936             :         }
     937             :     }
     938             :     ELSE
     939             :     {
     940      300000 :         ivas_format = ISM_FORMAT;
     941      300000 :         move16();
     942      300000 :         num_src = 1;
     943      300000 :         move16();
     944      300000 :         transport_config = IVAS_AUDIO_CONFIG_ISM1;
     945      300000 :         move16();
     946      300000 :         hIsmMetaData[0] = &hIsmMetaDataFrame;
     947      300000 :         move16();
     948      300000 :         hIsmMetaData[0]->azimuth_fx = currentPos->azimuth_fx;
     949      300000 :         move32();
     950      300000 :         hIsmMetaData[0]->elevation_fx = currentPos->elevation_fx;
     951      300000 :         move32();
     952      300000 :         hIsmMetaData[0]->yaw_fx = currentPos->yaw_fx;
     953      300000 :         move32();
     954      300000 :         hIsmMetaData[0]->pitch_fx = currentPos->pitch_fx;
     955      300000 :         move32();
     956      300000 :         hIsmMetaData[0]->radius_fx = currentPos->radius_fx;
     957      300000 :         move32();
     958      300000 :         hIsmMetaData[0]->non_diegetic_flag = currentPos->non_diegetic_flag;
     959      300000 :         move16();
     960             :     }
     961             : 
     962      324504 :     Word16 num_subframes = BASOP_Util_Divide3232_Scale( L_mult0( output_frame, FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ), output_Fs, &exp_tmp );
     963      324504 :     IF( sub( 15, exp_tmp ) )
     964             :     {
     965      324504 :         num_subframes = shr( num_subframes, sub( 15, exp_tmp ) );
     966             :     }
     967      843714 :     FOR( Word16 subframe_idx = 0; subframe_idx < num_subframes; subframe_idx++ )
     968             :     {
     969      519210 :         Word16 idx = subframe_idx;
     970      519210 :         move16();
     971      519210 :         Word16 pos_q = Q25;
     972      519210 :         move16();
     973             : 
     974      519210 :         test();
     975      519210 :         IF( *hCombinedOrientationData != NULL && ( *hCombinedOrientationData )->listenerPos != NULL )
     976             :         {
     977      268805 :             ( *hCombinedOrientationData )->listenerPos[idx].x_fx = L_shr( ( *hCombinedOrientationData )->listenerPos[idx].x_fx, sub( ( *hCombinedOrientationData )->listenerPos[idx].q_fact, pos_q ) );
     978      268805 :             move32();
     979      268805 :             ( *hCombinedOrientationData )->listenerPos[idx].y_fx = L_shr( ( *hCombinedOrientationData )->listenerPos[idx].y_fx, sub( ( *hCombinedOrientationData )->listenerPos[idx].q_fact, pos_q ) );
     980      268805 :             move32();
     981      268805 :             ( *hCombinedOrientationData )->listenerPos[idx].z_fx = L_shr( ( *hCombinedOrientationData )->listenerPos[idx].z_fx, sub( ( *hCombinedOrientationData )->listenerPos[idx].q_fact, pos_q ) );
     982      268805 :             move32();
     983      268805 :             ( *hCombinedOrientationData )->listenerPos[idx].q_fact = pos_q;
     984      268805 :             move16();
     985             :         }
     986     2076840 :         FOR( Word16 i = 0; i < 3; i++ )
     987             :         {
     988     1557630 :             pTDRend->hBinRendererTd->Listener_p->Pos_fx[i] = L_shr( pTDRend->hBinRendererTd->Listener_p->Pos_fx[i], sub( pTDRend->hBinRendererTd->Listener_p->Pos_q, pos_q ) );
     989     1557630 :             pTDRend->hBinRendererTd->Listener_p->Pos_q = pos_q;
     990     1557630 :             move32();
     991     1557630 :             move16();
     992             :         }
     993             :     }
     994             : 
     995      324504 :     IF( NE_32( ( error = ivas_td_binaural_renderer_unwrap_fx( hReverb, transport_config, pTDRend->hBinRendererTd, num_src, lfe_idx, ivas_format, hIsmMetaData, *hCombinedOrientationData,
     996             :                                                               ism_md_subframe_update_ext, p_output_fx, output_frame, num_subframes ) ),
     997             :                IVAS_ERR_OK ) )
     998             :     {
     999           0 :         return error;
    1000             :     }
    1001             : 
    1002      324504 :     IF( hReverb != NULL )
    1003             :     {
    1004      155750 :         *exp = sub( *exp, 2 );
    1005      155750 :         move16();
    1006             :     }
    1007             : 
    1008      324504 :     pop_wmops();
    1009             : 
    1010      324504 :     return IVAS_ERR_OK;
    1011             : }
    1012             : 
    1013             : 
    1014             : /*---------------------------------------------------------------------*
    1015             :  * angles_to_vec()
    1016             :  *
    1017             :  * Convert azimuth and elevation angles to position/orientation vector
    1018             :  *---------------------------------------------------------------------*/
    1019      821831 : static void angles_to_vec_fx(
    1020             :     const Word16 radius,    /* i  : radius                               Qx */
    1021             :     const Word32 azimuth,   /* i  : Azimuth angle                       Q22 */
    1022             :     const Word32 elevation, /* i  : Elevation angle                     Q22 */
    1023             :     Word32 *vec             /* o  : Pos/Dir vector                    Qx+16 */
    1024             : )
    1025             : {
    1026             :     Word16 elevation_fx, azimuth_fx;
    1027      821831 :     elevation_fx = (Word16) L_shr( Mult_32_16( elevation, 91 ), 7 ); // Q15
    1028      821831 :     move16();
    1029      821831 :     azimuth_fx = (Word16) L_shr( Mult_32_16( azimuth, 91 ), 7 ); // Q15
    1030      821831 :     move16();
    1031      821831 :     vec[0] = L_mult( radius, mult( getCosWord16R2( elevation_fx ), getCosWord16R2( azimuth_fx ) ) ); // Qx + 16
    1032      821831 :     move32();
    1033      821831 :     vec[1] = L_mult( radius, mult( getCosWord16R2( elevation_fx ), getSineWord16R2( azimuth_fx ) ) ); // Qx + 16
    1034      821831 :     move32();
    1035      821831 :     vec[2] = L_mult( radius, getSineWord16R2( elevation_fx ) ); // Qx + 16
    1036      821831 :     move32();
    1037      821831 :     return;
    1038             : }

Generated by: LCOV version 1.14