LCOV - code coverage report
Current view: top level - lib_rend - ivas_objectRenderer_sources.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 8834b716eb6d7dfb881d5c69dd21cb18e1692722 Lines: 198 216 91.7 %
Date: 2025-07-09 08:36:12 Functions: 20 20 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 <stdint.h>
      34             : #include "options.h"
      35             : #include <math.h>
      36             : #include "prot.h"
      37             : #include "ivas_prot_rend.h"
      38             : #include "wmc_auto.h"
      39             : #ifdef DEBUGGING
      40             : #include "debug.h"
      41             : #endif
      42             : 
      43             : 
      44             : /*---------------------------------------------------------------------*
      45             :  * Local function prototypes
      46             :  *---------------------------------------------------------------------*/
      47             : 
      48             : static void TDREND_SRC_SPATIAL_Dealloc( TDREND_SRC_SPATIAL_t *SrcSpatial_p );
      49             : 
      50             : static void TDREND_SRC_SPATIAL_Init( TDREND_SRC_SPATIAL_t *SrcSpatial_p, const TDREND_PosType_t PosType );
      51             : 
      52             : static void TDREND_SRC_SPATIAL_SetDirAtten( TDREND_SRC_SPATIAL_t *SrcSpatial_p, const TDREND_DirAtten_t *DirAtten_p );
      53             : 
      54             : static void TDREND_SRC_SPATIAL_SetDistAtten( TDREND_SRC_SPATIAL_t *SrcSpatial_p, const TDREND_DistAtten_t *DistAtten_p );
      55             : 
      56             : static void TDREND_SRC_SPATIAL_SetGain( const TDREND_SRC_t *Src_p, const float Gain );
      57             : 
      58             : static float TDREND_SRC_SPATIAL_GetDirGain( const TDREND_DirAtten_t *DirAtten_p, const float *Front_p, const float *RelPos_p );
      59             : 
      60             : static float TDREND_SRC_SPATIAL_GetDistGain( const TDREND_DistAtten_t *DistAtten_p, const float Dist );
      61             : 
      62             : static ivas_error TDREND_SRC_REND_Alloc( TDREND_SRC_REND_t **SrcRend_pp );
      63             : 
      64             : static void TDREND_SRC_REND_Init( TDREND_SRC_REND_t *SrcRend_p );
      65             : 
      66             : 
      67             : /*-------------------------------------------------------------------*
      68             :  * TDREND_MIX_SRC_SetPos()
      69             :  *
      70             :  * Set source position
      71             :  --------------------------------------------------------------------*/
      72             : 
      73      981120 : ivas_error TDREND_MIX_SRC_SetPos(
      74             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle  */
      75             :     const int16_t SrcInd,                              /* i  : Source index        */
      76             :     const float *Vec_p                                 /* i  : Position vector     */
      77             : )
      78             : {
      79             :     TDREND_SRC_SPATIAL_t *SrcSpatial_p;
      80             : 
      81      981120 :     if ( SrcInd > hBinRendererTd->MaxSrcInd )
      82             :     {
      83           0 :         return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index!\n" ) );
      84             :     }
      85             :     else
      86             :     {
      87      981120 :         SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
      88             : 
      89      981120 :         if ( SrcSpatial_p->Pos_p[0] != Vec_p[0] || SrcSpatial_p->Pos_p[1] != Vec_p[1] || SrcSpatial_p->Pos_p[2] != Vec_p[2] )
      90             :         {
      91      604845 :             mvr2r( Vec_p, SrcSpatial_p->Pos_p, 3 );
      92      604845 :             SrcSpatial_p->Updated = TRUE;
      93             :         }
      94             :     }
      95             : 
      96      981120 :     return IVAS_ERR_OK;
      97             : }
      98             : 
      99             : 
     100             : /*-------------------------------------------------------------------*
     101             :  * TDREND_MIX_SRC_SetDir()
     102             :  *
     103             :  * Set source direction
     104             :  --------------------------------------------------------------------*/
     105             : 
     106      978636 : ivas_error TDREND_MIX_SRC_SetDir(
     107             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle  */
     108             :     const int16_t SrcInd,                              /* i  : Source index        */
     109             :     const float *Vec_p                                 /* i  : Direction vector    */
     110             : )
     111             : {
     112             :     TDREND_SRC_SPATIAL_t *SrcSpatial_p;
     113             : 
     114             :     /* Value verification */
     115      978636 :     if ( ( Vec_p[0] == 0.0f ) && ( Vec_p[1] == 0.0f ) && ( Vec_p[2] == 0.0f ) )
     116             :     {
     117           0 :         return ( IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Zero direction vector. Command is ignored!\n" ) );
     118             :     }
     119      978636 :     if ( SrcInd > hBinRendererTd->MaxSrcInd )
     120             :     {
     121           0 :         return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index!\n" ) );
     122             :     }
     123             :     else
     124             :     {
     125      978636 :         SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
     126      978636 :         TDREND_SPATIAL_VecNormalize( Vec_p, SrcSpatial_p->Front_p );
     127      978636 :         SrcSpatial_p->Updated = TRUE;
     128             :     }
     129             : 
     130      978636 :     return IVAS_ERR_OK;
     131             : }
     132             : 
     133             : 
     134             : /*-------------------------------------------------------------------*
     135             :  * TDREND_MIX_SRC_SetGain()
     136             :  *
     137             :  * Set source gain
     138             :  --------------------------------------------------------------------*/
     139             : 
     140      978015 : ivas_error TDREND_MIX_SRC_SetGain(
     141             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle   */
     142             :     const int16_t SrcInd,                              /* i  : Source index         */
     143             :     const float Gain                                   /* i  : Gain                 */
     144             : )
     145             : {
     146      978015 :     TDREND_SRC_SPATIAL_SetGain( hBinRendererTd->Sources[SrcInd], Gain );
     147             : 
     148      978015 :     return IVAS_ERR_OK;
     149             : }
     150             : 
     151             : 
     152             : /*-------------------------------------------------------------------*
     153             :  * TDREND_MIX_SRC_SetDirAtten()
     154             :  *
     155             :  * Set directional attenuation for the mixer.
     156             :  --------------------------------------------------------------------*/
     157             : 
     158      983363 : ivas_error TDREND_MIX_SRC_SetDirAtten(
     159             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle                */
     160             :     const int16_t SrcInd,                              /* i  : Source index                      */
     161             :     const TDREND_DirAtten_t *DirAtten_p                /* i  : Directional attenuation specifier */
     162             : )
     163             : {
     164             :     TDREND_SRC_SPATIAL_t *SrcSpatial_p;
     165      983363 :     if ( SrcInd > hBinRendererTd->MaxSrcInd )
     166             :     {
     167           0 :         return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index\n" ) );
     168             :     }
     169             :     else
     170             :     {
     171      983363 :         SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
     172      983363 :         TDREND_SRC_SPATIAL_SetDirAtten( SrcSpatial_p, DirAtten_p );
     173             :     }
     174             : 
     175      983363 :     return IVAS_ERR_OK;
     176             : }
     177             : 
     178             : /*-------------------------------------------------------------------*
     179             :  * TDREND_MIX_SRC_SetDistAtten()
     180             :  *
     181             :  * Set distance attenuation for the mixer.
     182             :  --------------------------------------------------------------------*/
     183             : 
     184        5348 : ivas_error TDREND_MIX_SRC_SetDistAtten(
     185             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle                */
     186             :     const int16_t SrcInd,                              /* i  : Source index                      */
     187             :     const TDREND_DistAtten_t *DistAtten_p              /* i  : Distance attenuation specifier */
     188             : )
     189             : {
     190             :     TDREND_SRC_SPATIAL_t *SrcSpatial_p;
     191        5348 :     if ( SrcInd > hBinRendererTd->MaxSrcInd )
     192             :     {
     193           0 :         return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index\n" ) );
     194             :     }
     195             :     else
     196             :     {
     197        5348 :         SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
     198        5348 :         TDREND_SRC_SPATIAL_SetDistAtten( SrcSpatial_p, DistAtten_p );
     199             :     }
     200             : 
     201        5348 :     return IVAS_ERR_OK;
     202             : }
     203             : 
     204             : /*-------------------------------------------------------------------*
     205             :  * TDREND_MIX_SRC_SetPlayState()
     206             :  *
     207             :  * Set play state for the source.
     208             :  --------------------------------------------------------------------*/
     209             : 
     210         621 : ivas_error TDREND_MIX_SRC_SetPlayState(
     211             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle                      */
     212             :     const int16_t SrcInd,                              /* i  : Source index        */
     213             :     const TDREND_PlayStatus_t PlayStatus               /* i  : Play state          */
     214             : )
     215             : {
     216         621 :     if ( SrcInd > hBinRendererTd->MaxSrcInd )
     217             :     {
     218           0 :         return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index\n" ) );
     219             :     }
     220             :     else
     221             :     {
     222         621 :         hBinRendererTd->Sources[SrcInd]->SrcRend_p->PlayStatus = PlayStatus;
     223             :     }
     224         621 :     return IVAS_ERR_OK;
     225             : }
     226             : 
     227             : 
     228             : /*-------------------------------------------------------------------*
     229             :  * TDREND_SRC_REND_Alloc()
     230             :  *
     231             :  * Renderer allocation
     232             :  --------------------------------------------------------------------*/
     233             : 
     234        5348 : static ivas_error TDREND_SRC_REND_Alloc(
     235             :     TDREND_SRC_REND_t **SrcRend_pp /* i/o: Source object */
     236             : )
     237             : {
     238             :     TDREND_SRC_REND_t *SrcRend_p;
     239             : 
     240        5348 :     *SrcRend_pp = NULL;
     241             : 
     242             :     /* Allocate the TDREND_SRC_REND_t variable */
     243        5348 :     if ( ( SrcRend_p = (TDREND_SRC_REND_t *) malloc( sizeof( TDREND_SRC_REND_t ) ) ) == NULL )
     244             :     {
     245           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "SrcRend_p allocation error\n" ) );
     246             :     }
     247             : 
     248        5348 :     *SrcRend_pp = SrcRend_p;
     249             : 
     250        5348 :     return IVAS_ERR_OK;
     251             : }
     252             : 
     253             : 
     254             : /*-------------------------------------------------------------------*
     255             :  * TDREND_SRC_REND_Init()
     256             :  *
     257             :  * Initialize rendering aspects of source.
     258             :  --------------------------------------------------------------------*/
     259             : 
     260        5348 : static void TDREND_SRC_REND_Init(
     261             :     TDREND_SRC_REND_t *SrcRend_p /* i/o: Source object        */
     262             : )
     263             : {
     264             :     int16_t nC;
     265             : 
     266             :     /* Internal state */
     267        5348 :     SrcRend_p->InputAvailable = FALSE;
     268        5348 :     SrcRend_p->PlayStatus = TDREND_PLAYSTATUS_PLAYING;
     269             :     /* SrcGain  */
     270       10696 :     for ( nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ )
     271             :     {
     272        5348 :         SrcRend_p->SrcGainMin_p[nC] = 0.0f;
     273        5348 :         SrcRend_p->SrcGain_p[nC] = 1.0f;
     274        5348 :         SrcRend_p->SrcGainMax_p[nC] = 2.0f;
     275             :     }
     276        5348 :     SrcRend_p->SrcGainUpdated = FALSE;
     277             : 
     278             :     /* Init directional and distance gains */
     279       10696 :     for ( nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ )
     280             :     {
     281        5348 :         SrcRend_p->DirGain_p[nC] = 1.0f;
     282        5348 :         SrcRend_p->DistGain_p[nC] = 1.0f;
     283             :     }
     284             : 
     285             : 
     286        5348 :     return;
     287             : }
     288             : 
     289             : 
     290             : /*-------------------------------------------------------------------*
     291             :  * TDREND_SRC_REND_UpdateFiltersFromSpatialParams()
     292             :  *
     293             :  * Update the HR filter due to spatial change.
     294             :  --------------------------------------------------------------------*/
     295             : 
     296     2139222 : void TDREND_SRC_REND_UpdateFiltersFromSpatialParams(
     297             :     BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle               */
     298             :     TDREND_SRC_REND_t *SrcRend_p,                      /* i/o: Source object                    */
     299             :     TDREND_SRC_SPATIAL_t *SrcSpatial_p,                /* i  : Spatial aspects of source        */
     300             :     float *hrf_left_prev,                              /* o  : Left filter                      */
     301             :     float *hrf_right_prev,                             /* o  : Right filter                     */
     302             :     float *hrf_left_delta,                             /* o  : Left filter interpolation delta  */
     303             :     float *hrf_right_delta,                            /* o  : Right filter interpolation delta */
     304             :     int16_t *intp_count,                               /* o  : Interpolation count              */
     305             :     int16_t *filterlength,                             /* o  : Length of filters                */
     306             :     int16_t *itd,                                      /* o  : ITD value                        */
     307             :     float *Gain,                                       /* o  : Gain value                       */
     308             :     TDREND_SRC_t *Src_p                                /* i/o: Source pointer                   */
     309             : )
     310             : {
     311             :     TDREND_MIX_Listener_t *Listener_p;
     312             :     TDREND_HRFILT_FiltSet_t *HrFiltSet_p;
     313             :     float ListRelPos[3], ListRelDist;
     314             :     float ListRelPosAbs[3]; /* Relative position, ignoring orientation of listener */
     315             :     float Azim, Elev;
     316             :     float hrf_left[SFX_SPAT_BIN_MAX_FILTER_LENGTH];
     317             :     float hrf_right[SFX_SPAT_BIN_MAX_FILTER_LENGTH];
     318             :     float azim_delta;
     319             :     float elev_delta;
     320             : 
     321             :     /* Evaluate the HR filters from the source and listener positions and orientations */
     322     2139222 :     Listener_p = hBinRendererTd->Listener_p;
     323     2139222 :     HrFiltSet_p = hBinRendererTd->HrFiltSet_p;
     324             : 
     325     2139222 :     *filterlength = min( HrFiltSet_p->FiltLength, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
     326             : 
     327     2139222 :     if ( SrcSpatial_p->PosType == TDREND_POSTYPE_ABSOLUTE )
     328             :     {
     329             : 
     330             :         /* Absolute position */
     331     2136738 :         TDREND_SPATIAL_VecMapToNewCoordSystem( SrcSpatial_p->Pos_p, Listener_p->Pos, Listener_p->Front, Listener_p->Up, Listener_p->Right, ListRelPos, ListRelPosAbs );
     332     2136738 :         ListRelDist = TDREND_SPATIAL_VecNorm( ListRelPos );
     333             : 
     334             :         /* 2. Evaluate the Elevation and Azimuth angles  */
     335     2136738 :         if ( ( ListRelPos[0] == 0 ) && ( ListRelPos[1] == 0 ) && ( ListRelPos[2] == 0 ) )
     336             :         {
     337        4809 :             Elev = 0.0;
     338        4809 :             Azim = 0.0;
     339             :         }
     340             :         else
     341             :         {
     342     2131929 :             Elev = _180_OVER_PI * atan2f( ListRelPos[2], sqrtf( ListRelPos[0] * ListRelPos[0] + ListRelPos[1] * ListRelPos[1] ) );
     343             :             /* Basis set is [front, right, up], which is a left-handed coordinate system. Minus sign here is to change to a positive-left system for azimuth */
     344     2131929 :             Azim = -1.0f * _180_OVER_PI * (float) atan2f( ListRelPos[1], ListRelPos[0] );
     345             :         }
     346             : 
     347     2136738 :         GetFilterFromAngle( HrFiltSet_p, Elev, Azim, *filterlength, hrf_left, hrf_right, itd );
     348             : 
     349             :         /* 6. Evaluate the directional and distance gains */
     350             :         /* Directional gain */
     351     2136738 :         *SrcRend_p->DirGain_p = 1.0f;
     352     2136738 :         if ( SrcSpatial_p->DirAttenEnabled )
     353             :         {
     354     2136738 :             *SrcRend_p->DirGain_p = TDREND_SRC_SPATIAL_GetDirGain( &SrcSpatial_p->DirAtten, SrcSpatial_p->Front_p, ListRelPosAbs );
     355             :         }
     356             : 
     357             :         /* Distance gain */
     358     2136738 :         *SrcRend_p->DistGain_p = 1.0f;
     359     2136738 :         if ( hBinRendererTd->UseCommonDistAttenModel )
     360             :         {
     361     2136738 :             if ( hBinRendererTd->DistAttenEnabled )
     362             :             {
     363     2136738 :                 SrcSpatial_p->DistAtten.DistAttenModel = hBinRendererTd->DistAttenModel;
     364     2136738 :                 *SrcRend_p->DistGain_p = TDREND_SRC_SPATIAL_GetDistGain( &SrcSpatial_p->DistAtten, ListRelDist );
     365             :             }
     366             :         }
     367             :         else
     368             :         {
     369           0 :             if ( SrcSpatial_p->DistAttenEnabled )
     370             :             {
     371           0 :                 *SrcRend_p->DistGain_p = TDREND_SRC_SPATIAL_GetDistGain( &SrcSpatial_p->DistAtten, ListRelDist );
     372             :             }
     373             :         }
     374             : 
     375             :         /* Update total gains */
     376     2136738 :         *Gain = ( *SrcRend_p->SrcGain_p ) * ( *SrcRend_p->DirGain_p ) * ( *SrcRend_p->DistGain_p ) * hBinRendererTd->Gain;
     377             : 
     378             :         /* Delta for interpolation, in case the angular step exceeds MAX_ANGULAR_STEP */
     379     2136738 :         elev_delta = Elev - Src_p->elev_prev;
     380     2136738 :         azim_delta = Azim - Src_p->azim_prev;
     381     2136738 :         Src_p->elev_prev = Elev;
     382     2136738 :         Src_p->azim_prev = Azim;
     383             : 
     384     2136738 :         azim_delta = ( azim_delta > 180.0f ) ? ( azim_delta - 360 ) : ( ( azim_delta < -180.0f ) ? ( azim_delta + 360 ) : ( azim_delta ) ); /* map to -180:180 range */
     385     2136738 :         *intp_count = min( MAX_INTERPOLATION_STEPS, max( (int16_t) ( fabsf( azim_delta ) * MAX_ANGULAR_STEP_INV ), (int16_t) ( fabsf( elev_delta ) * MAX_ANGULAR_STEP_INV ) ) );
     386             :     }
     387             :     else /* TDREND_POSTYPE_NON_DIEGETIC */
     388             :     {
     389        2484 :         *itd = 0;
     390        2484 :         *Gain = 1.0f;
     391        2484 :         set_f( hrf_left, 0.0f, *filterlength );
     392        2484 :         set_f( hrf_right, 0.0f, *filterlength );
     393        2484 :         hrf_left[0] = ( SrcSpatial_p->Pos_p[1] + 1.f ) * 0.5f;
     394        2484 :         hrf_right[0] = 1.f - hrf_left[0];
     395        2484 :         *intp_count = MAX_INTERPOLATION_STEPS;
     396        2484 :         Src_p->elev_prev = 0;
     397        2484 :         Src_p->azim_prev = 360.0f; /* Dummy angle -- sets max interpolation if switching to TDREND_POSTYPE_ABSOLUTE */
     398             :     }
     399             : 
     400     2139222 :     if ( ( *intp_count > 0 ) )
     401             :     {
     402             :         /* Set deltas for interpolation */
     403     1881496 :         v_sub( hrf_left, hrf_left_prev, hrf_left_delta, *filterlength );
     404     1881496 :         v_multc( hrf_left_delta, 1.0f / *intp_count, hrf_left_delta, *filterlength );
     405     1881496 :         v_sub( hrf_right, hrf_right_prev, hrf_right_delta, *filterlength );
     406     1881496 :         v_multc( hrf_right_delta, 1.0f / *intp_count, hrf_right_delta, *filterlength );
     407             :     }
     408             :     else
     409             :     {
     410             :         /* No interpolation, just set the new filters and reset deltas */
     411      257726 :         mvr2r( hrf_left, hrf_left_prev, *filterlength );
     412      257726 :         mvr2r( hrf_right, hrf_right_prev, *filterlength );
     413      257726 :         set_f( hrf_left_delta, 0.0f, *filterlength );
     414      257726 :         set_f( hrf_right_delta, 0.0f, *filterlength );
     415             :     }
     416             : 
     417     2139222 :     return;
     418             : }
     419             : 
     420             : 
     421             : /*-------------------------------------------------------------------*
     422             :  * TDREND_SRC_SPATIAL_Alloc()
     423             :  *
     424             :  * Allocatie spatial properties of a source.
     425             :  --------------------------------------------------------------------*/
     426             : 
     427        5348 : static ivas_error TDREND_SRC_SPATIAL_Alloc(
     428             :     TDREND_SRC_SPATIAL_t **SrcSpatial_pp /* i/o: Source spatial parameters */
     429             : )
     430             : {
     431             :     TDREND_SRC_SPATIAL_t *SrcSpatial_p;
     432             : 
     433        5348 :     *SrcSpatial_pp = NULL;
     434             : 
     435             :     /* Allocate the TDREND_SRC_t variable */
     436        5348 :     if ( ( SrcSpatial_p = (TDREND_SRC_SPATIAL_t *) malloc( sizeof( TDREND_SRC_SPATIAL_t ) ) ) == NULL )
     437             :     {
     438           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "TDREND_SRC_SPATIAL_t allocation error\n" ) );
     439             :     }
     440             : 
     441        5348 :     *SrcSpatial_pp = SrcSpatial_p;
     442             : 
     443        5348 :     return IVAS_ERR_OK;
     444             : }
     445             : 
     446             : 
     447             : /*-------------------------------------------------------------------*
     448             :  * TDREND_SRC_SPATIAL_Dealloc()
     449             :  *
     450             :  * Deallocate spatial properties of a source.
     451             :  --------------------------------------------------------------------*/
     452             : 
     453        5348 : static void TDREND_SRC_SPATIAL_Dealloc(
     454             :     TDREND_SRC_SPATIAL_t *SrcSpatial_p /* i/o: Source spatial parameters */
     455             : )
     456             : {
     457        5348 :     if ( SrcSpatial_p == NULL )
     458             :     {
     459           0 :         return;
     460             :     }
     461             :     /* Free the SrcSpatial_p variable */
     462        5348 :     free( SrcSpatial_p );
     463        5348 :     SrcSpatial_p = NULL;
     464             : 
     465        5348 :     return;
     466             : }
     467             : 
     468             : 
     469             : /*-------------------------------------------------------------------*
     470             :  * TDREND_SRC_SPATIAL_Init()
     471             :  *
     472             :  * Initialize spatial properties of a source.
     473             :  --------------------------------------------------------------------*/
     474             : 
     475        5348 : static void TDREND_SRC_SPATIAL_Init(
     476             :     TDREND_SRC_SPATIAL_t *SrcSpatial_p, /* i/o: Source spatial parameters       */
     477             :     const TDREND_PosType_t PosType      /* i  : Relative/absolute position type */
     478             : )
     479             : {
     480             :     int16_t nC;
     481             : 
     482             :     /* Initialize variables */
     483        5348 :     SrcSpatial_p->Updated = FALSE;
     484             : 
     485             :     /* Source position, velocity and direction vectors */
     486        5348 :     SrcSpatial_p->PosType = PosType;
     487       10696 :     for ( nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ )
     488             :     {
     489             :         /* Source position */
     490        5348 :         TDREND_SPATIAL_VecInit( SrcSpatial_p->Pos_p + nC * 3, 0.0f, 0.0f, 0.0f );
     491             : 
     492             :         /* Source direction */
     493        5348 :         TDREND_SPATIAL_VecInit( SrcSpatial_p->Front_p + nC * 3, 0.0f, 0.0f, 1.0f );
     494             :     }
     495             : 
     496             :     /* Source directional attenuation */
     497        5348 :     SrcSpatial_p->DirAttenEnabled = FALSE;
     498        5348 :     SrcSpatial_p->DirAtten.ConeInnerAngle = 360.0f;
     499        5348 :     SrcSpatial_p->DirAtten.ConeOuterAngle = 360.0f;
     500        5348 :     SrcSpatial_p->DirAtten.ConeOuterGain = 1.0f;
     501             : 
     502             :     /* Source distance attenuation */
     503        5348 :     SrcSpatial_p->DistAttenEnabled = FALSE;
     504        5348 :     SrcSpatial_p->DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED;
     505        5348 :     SrcSpatial_p->DistAtten.RefDist = 1.0f;
     506        5348 :     SrcSpatial_p->DistAtten.MaxDist = 15.75f; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */
     507        5348 :     SrcSpatial_p->DistAtten.RollOffFactor = 1.0f;
     508             : 
     509        5348 :     return;
     510             : }
     511             : 
     512             : 
     513             : /*-------------------------------------------------------------------*
     514             :  * TDREND_SRC_SPATIAL_SetDirAtten()
     515             :  *
     516             :  * Sets the directional attenuation mode.
     517             :  --------------------------------------------------------------------*/
     518             : 
     519      983363 : static void TDREND_SRC_SPATIAL_SetDirAtten(
     520             :     TDREND_SRC_SPATIAL_t *SrcSpatial_p, /* i/o: Source spatial parameters    */
     521             :     const TDREND_DirAtten_t *DirAtten_p /* i  : Directionality specification */
     522             : )
     523             : {
     524             :     /* Set directional attenuation */
     525      983363 :     SrcSpatial_p->DirAttenEnabled = TRUE;
     526      983363 :     SrcSpatial_p->DirAtten.ConeInnerAngle = DirAtten_p->ConeInnerAngle;
     527      983363 :     SrcSpatial_p->DirAtten.ConeOuterAngle = DirAtten_p->ConeOuterAngle;
     528      983363 :     SrcSpatial_p->DirAtten.ConeOuterGain = DirAtten_p->ConeOuterGain;
     529             : 
     530      983363 :     return;
     531             : }
     532             : 
     533             : /*-------------------------------------------------------------------*
     534             :  * TDREND_SRC_SPATIAL_SetDistAtten()
     535             :  *
     536             :  * Sets the distance attenuation.
     537             :  --------------------------------------------------------------------*/
     538             : 
     539        5348 : static void TDREND_SRC_SPATIAL_SetDistAtten(
     540             :     TDREND_SRC_SPATIAL_t *SrcSpatial_p,
     541             :     const TDREND_DistAtten_t *DistAtten_p )
     542             : {
     543             :     /* Set distance attenuation */
     544        5348 :     SrcSpatial_p->DistAttenEnabled = TRUE;
     545        5348 :     SrcSpatial_p->DistAtten.DistAttenModel = DistAtten_p->DistAttenModel;
     546        5348 :     SrcSpatial_p->DistAtten.MaxDist = DistAtten_p->MaxDist;
     547        5348 :     SrcSpatial_p->DistAtten.RefDist = DistAtten_p->RefDist;
     548        5348 :     SrcSpatial_p->DistAtten.RollOffFactor = DistAtten_p->RollOffFactor;
     549             : 
     550        5348 :     return;
     551             : }
     552             : 
     553             : 
     554             : /*-------------------------------------------------------------------*
     555             :  * TDREND_SRC_SPATIAL_SetGain()
     556             :  *
     557             :  * Set the object gain
     558             :  --------------------------------------------------------------------*/
     559             : 
     560      978015 : static void TDREND_SRC_SPATIAL_SetGain(
     561             :     const TDREND_SRC_t *Src_p, /* i  : Directional attenuation specification */
     562             :     const float Gain           /* i  : Front-pointing vector                 */
     563             : )
     564             : {
     565      978015 :     Src_p->SrcRend_p->SrcGain_p[0] = Gain;
     566             : 
     567      978015 :     return;
     568             : }
     569             : 
     570             : 
     571             : /*-------------------------------------------------------------------*
     572             :  * TDREND_SRC_SPATIAL_GetDirGain()
     573             :  *
     574             :  * Returns the gain due to object orientation.
     575             :  --------------------------------------------------------------------*/
     576             : 
     577             : /*! r: Gain value */
     578     2136738 : static float TDREND_SRC_SPATIAL_GetDirGain(
     579             :     const TDREND_DirAtten_t *DirAtten_p, /* i  : Directional attenuation specification */
     580             :     const float *Front_p,                /* i  : Front-pointing vector                 */
     581             :     const float *RelPos_p                /* i  : Relative position                     */
     582             : )
     583             : {
     584             :     float DirGain;
     585             :     float Vec[3];
     586             :     float ProjCoef, NormRelPos;
     587             :     float AngleDeg;
     588             : 
     589     2136738 :     DirGain = 1.0f;
     590             : 
     591             :     /* Note that the front vector is unit norm, thus */
     592             :     /* Angle = acos ( Proj coeff from projecting -RelPos onto Front / norm(RelPos) ); */
     593     2136738 :     v_multc( RelPos_p, -1, Vec, 3 );
     594     2136738 :     ProjCoef = dotp( Vec, Front_p, 3 );
     595     2136738 :     NormRelPos = TDREND_SPATIAL_VecNorm( RelPos_p );
     596             : 
     597     2136738 :     if ( NormRelPos != 0.0f )
     598             :     {
     599     2131929 :         AngleDeg = _180_OVER_PI * acosf( ProjCoef / NormRelPos );
     600             :     }
     601             :     else
     602             :     {
     603        4809 :         AngleDeg = 0.0f;
     604             :     }
     605             : 
     606     2136738 :     if ( 2.0f * AngleDeg <= DirAtten_p->ConeInnerAngle )
     607             :     {
     608     2031093 :         DirGain = 1.0f;
     609             :     }
     610      105645 :     else if ( 2.0f * AngleDeg <= DirAtten_p->ConeOuterAngle )
     611             :     {
     612      100296 :         DirGain = 1.0f - ( 2.0f * AngleDeg - DirAtten_p->ConeInnerAngle ) / ( DirAtten_p->ConeOuterAngle - DirAtten_p->ConeInnerAngle ) * ( 1.0f - DirAtten_p->ConeOuterGain );
     613             :     }
     614             :     else
     615             :     {
     616        5349 :         DirGain = DirAtten_p->ConeOuterGain;
     617             :     }
     618             : 
     619     2136738 :     return DirGain;
     620             : }
     621             : 
     622             : 
     623             : /*-------------------------------------------------------------------*
     624             :  * TDREND_SRC_SPATIAL_GetDistGain()
     625             :  *
     626             :  * Returns the gain due to distance.
     627             :  --------------------------------------------------------------------*/
     628             : 
     629             : /*! r: Gain value */
     630     2136738 : static float TDREND_SRC_SPATIAL_GetDistGain(
     631             :     const TDREND_DistAtten_t *DistAtten_p, /* i  : Distance attenuation parameters   */
     632             :     const float Dist                       /* i  : Distance value                    */
     633             : )
     634             : {
     635             :     float DistGain;
     636             :     float Dist2;
     637             : 
     638     2136738 :     DistGain = 1.0f;
     639     2136738 :     Dist2 = Dist;
     640             : 
     641     2136738 :     switch ( DistAtten_p->DistAttenModel )
     642             :     {
     643           0 :         case TDREND_DIST_ATTEN_MODEL_INV_DIST:
     644           0 :             DistGain = powf( DistAtten_p->RefDist / Dist2, DistAtten_p->RollOffFactor );
     645           0 :             break;
     646             : 
     647     2136738 :         case TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED:
     648     2136738 :             if ( Dist2 < DistAtten_p->RefDist )
     649             :             {
     650      489657 :                 Dist2 = DistAtten_p->RefDist;
     651             :             }
     652             : 
     653     2136738 :             if ( Dist2 > DistAtten_p->MaxDist )
     654             :             {
     655       24935 :                 Dist2 = DistAtten_p->MaxDist;
     656             :             }
     657     2136738 :             DistGain = powf( DistAtten_p->RefDist / Dist2, DistAtten_p->RollOffFactor );
     658     2136738 :             break;
     659             :     }
     660             : 
     661     2136738 :     return DistGain;
     662             : }
     663             : 
     664             : 
     665             : /*-------------------------------------------------------------------*
     666             :  * TDREND_SRC_Alloc()
     667             :  *
     668             :  * Allocate a source.
     669             :  --------------------------------------------------------------------*/
     670             : 
     671        5348 : ivas_error TDREND_SRC_Alloc(
     672             :     TDREND_SRC_t **Src_pp /* i/o: Source          */
     673             : )
     674             : {
     675             :     ivas_error error;
     676             :     TDREND_SRC_t *Src_p;
     677             : 
     678        5348 :     *Src_pp = NULL;
     679             : 
     680             :     /* Allocate the TDREND_SRC_t variable */
     681        5348 :     if ( ( Src_p = (TDREND_SRC_t *) malloc( sizeof( TDREND_SRC_t ) ) ) == NULL )
     682             :     {
     683           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, " TDREND_SRC_Alloc: Allocation error\n" ) );
     684             :     }
     685             : 
     686        5348 :     Src_p->SrcSpatial_p = NULL;
     687             :     /* If source type is dynamic alloc the TDREND_SRC_SPATIAL_t variable */
     688        5348 :     if ( ( error = TDREND_SRC_SPATIAL_Alloc( &Src_p->SrcSpatial_p ) ) != IVAS_ERR_OK )
     689             :     {
     690           0 :         return error;
     691             :     }
     692             : 
     693        5348 :     if ( ( error = TDREND_SRC_REND_Alloc( &Src_p->SrcRend_p ) ) != IVAS_ERR_OK )
     694             :     {
     695           0 :         return error;
     696             :     }
     697             : 
     698        5348 :     *Src_pp = Src_p;
     699             : 
     700        5348 :     return IVAS_ERR_OK;
     701             : }
     702             : 
     703             : 
     704             : /*-------------------------------------------------------------------*
     705             :  * TDREND_SRC_Dealloc()
     706             :  *
     707             :  * Deallocate a source.
     708             :  --------------------------------------------------------------------*/
     709             : 
     710        5348 : void TDREND_SRC_Dealloc(
     711             :     TDREND_SRC_t *Src_p )
     712             : {
     713        5348 :     if ( Src_p == NULL )
     714             :     {
     715           0 :         return;
     716             :     }
     717             : 
     718             :     /* Delloc the TDREND_SRC_Spatial_t variable */
     719        5348 :     TDREND_SRC_SPATIAL_Dealloc( Src_p->SrcSpatial_p );
     720             : 
     721             :     /* Delloc the TDREND_SRC_REND__t variable */
     722        5348 :     free( Src_p->SrcRend_p );
     723        5348 :     Src_p->SrcRend_p = NULL;
     724             : 
     725             :     /* Free the Src_p variable */
     726        5348 :     free( Src_p );
     727        5348 :     Src_p = NULL;
     728             : 
     729        5348 :     return;
     730             : }
     731             : 
     732             : 
     733             : /*-------------------------------------------------------------------*
     734             :  * TDREND_SRC_Init()
     735             :  *
     736             :  * Initializes a source.
     737             :  --------------------------------------------------------------------*/
     738             : 
     739        5348 : void TDREND_SRC_Init(
     740             :     TDREND_SRC_t *Src_p,           /* i/o: Source to initialize    */
     741             :     const TDREND_PosType_t PosType /* i  : Position type specifier */
     742             : )
     743             : {
     744             :     /* Init the TDREND_SRC_Spatial_t variable */
     745        5348 :     if ( Src_p->SrcSpatial_p != NULL )
     746             :     {
     747        5348 :         TDREND_SRC_SPATIAL_Init( Src_p->SrcSpatial_p, PosType );
     748             :     }
     749             : 
     750             :     /* Init the TDREND_SRC_REND_t variable */
     751        5348 :     TDREND_SRC_REND_Init( Src_p->SrcRend_p );
     752             : 
     753             :     /* Reset memory buffers */
     754        5348 :     Src_p->itd = 0;
     755        5348 :     Src_p->previtd = 0;
     756        5348 :     Src_p->filterlength = 1; /* Init to unit impulse of length 1 */
     757        5348 :     set_f( Src_p->mem_itd, 0.0f, ITD_MEM_LEN );
     758        5348 :     set_f( Src_p->mem_hrf_left, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 );
     759        5348 :     set_f( Src_p->mem_hrf_right, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 );
     760             : 
     761        5348 :     set_f( Src_p->hrf_left_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
     762        5348 :     set_f( Src_p->hrf_right_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
     763        5348 :     Src_p->hrf_left_prev[0] = 1;
     764        5348 :     Src_p->hrf_right_prev[0] = 1;
     765        5348 :     Src_p->azim_prev = 0.0f;
     766        5348 :     Src_p->elev_prev = 0.0f;
     767        5348 :     Src_p->Gain = 1;
     768        5348 :     Src_p->prevGain = 1.0f;
     769             : 
     770        5348 :     return;
     771             : }

Generated by: LCOV version 1.14