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

Generated by: LCOV version 1.14