LCOV - code coverage report
Current view: top level - lib_rend - ivas_objectRenderer_sources.c (source / functions) Hit Total Coverage
Test: Coverage on main @ 6baab0c613aa6c7100498ed7b93676aa8198a493 Lines: 198 216 91.7 %
Date: 2025-05-29 08:28:55 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     2707097 : 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     2707097 :     if ( SrcInd > hBinRendererTd->MaxSrcInd )
      82             :     {
      83           0 :         return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index!\n" ) );
      84             :     }
      85             :     else
      86             :     {
      87     2707097 :         SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
      88             : 
      89     2707097 :         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     2218488 :             mvr2r( Vec_p, SrcSpatial_p->Pos_p, 3 );
      92     2218488 :             SrcSpatial_p->Updated = TRUE;
      93             :         }
      94             :     }
      95             : 
      96     2707097 :     return IVAS_ERR_OK;
      97             : }
      98             : 
      99             : 
     100             : /*-------------------------------------------------------------------*
     101             :  * TDREND_MIX_SRC_SetDir()
     102             :  *
     103             :  * Set source direction
     104             :  --------------------------------------------------------------------*/
     105             : 
     106     2607939 : 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     2607939 :     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     2607939 :     if ( SrcInd > hBinRendererTd->MaxSrcInd )
     120             :     {
     121           0 :         return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index!\n" ) );
     122             :     }
     123             :     else
     124             :     {
     125     2607939 :         SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
     126     2607939 :         TDREND_SPATIAL_VecNormalize( Vec_p, SrcSpatial_p->Front_p );
     127     2607939 :         SrcSpatial_p->Updated = TRUE;
     128             :     }
     129             : 
     130     2607939 :     return IVAS_ERR_OK;
     131             : }
     132             : 
     133             : 
     134             : /*-------------------------------------------------------------------*
     135             :  * TDREND_MIX_SRC_SetGain()
     136             :  *
     137             :  * Set source gain
     138             :  --------------------------------------------------------------------*/
     139             : 
     140     2604330 : 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     2604330 :     TDREND_SRC_SPATIAL_SetGain( hBinRendererTd->Sources[SrcInd], Gain );
     147             : 
     148     2604330 :     return IVAS_ERR_OK;
     149             : }
     150             : 
     151             : 
     152             : /*-------------------------------------------------------------------*
     153             :  * TDREND_MIX_SRC_SetDirAtten()
     154             :  *
     155             :  * Set directional attenuation for the mixer.
     156             :  --------------------------------------------------------------------*/
     157             : 
     158     2643981 : 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     2643981 :     if ( SrcInd > hBinRendererTd->MaxSrcInd )
     166             :     {
     167           0 :         return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index\n" ) );
     168             :     }
     169             :     else
     170             :     {
     171     2643981 :         SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
     172     2643981 :         TDREND_SRC_SPATIAL_SetDirAtten( SrcSpatial_p, DirAtten_p );
     173             :     }
     174             : 
     175     2643981 :     return IVAS_ERR_OK;
     176             : }
     177             : 
     178             : /*-------------------------------------------------------------------*
     179             :  * TDREND_MIX_SRC_SetDistAtten()
     180             :  *
     181             :  * Set distance attenuation for the mixer.
     182             :  --------------------------------------------------------------------*/
     183             : 
     184       39651 : 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       39651 :     if ( SrcInd > hBinRendererTd->MaxSrcInd )
     192             :     {
     193           0 :         return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index\n" ) );
     194             :     }
     195             :     else
     196             :     {
     197       39651 :         SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
     198       39651 :         TDREND_SRC_SPATIAL_SetDistAtten( SrcSpatial_p, DistAtten_p );
     199             :     }
     200             : 
     201       39651 :     return IVAS_ERR_OK;
     202             : }
     203             : 
     204             : /*-------------------------------------------------------------------*
     205             :  * TDREND_MIX_SRC_SetPlayState()
     206             :  *
     207             :  * Set play state for the source.
     208             :  --------------------------------------------------------------------*/
     209             : 
     210        3609 : 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        3609 :     if ( SrcInd > hBinRendererTd->MaxSrcInd )
     217             :     {
     218           0 :         return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index\n" ) );
     219             :     }
     220             :     else
     221             :     {
     222        3609 :         hBinRendererTd->Sources[SrcInd]->SrcRend_p->PlayStatus = PlayStatus;
     223             :     }
     224        3609 :     return IVAS_ERR_OK;
     225             : }
     226             : 
     227             : 
     228             : /*-------------------------------------------------------------------*
     229             :  * TDREND_SRC_REND_Alloc()
     230             :  *
     231             :  * Renderer allocation
     232             :  --------------------------------------------------------------------*/
     233             : 
     234       39651 : 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       39651 :     *SrcRend_pp = NULL;
     241             : 
     242             :     /* Allocate the TDREND_SRC_REND_t variable */
     243       39651 :     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       39651 :     *SrcRend_pp = SrcRend_p;
     249             : 
     250       39651 :     return IVAS_ERR_OK;
     251             : }
     252             : 
     253             : 
     254             : /*-------------------------------------------------------------------*
     255             :  * TDREND_SRC_REND_Init()
     256             :  *
     257             :  * Initialize rendering aspects of source.
     258             :  --------------------------------------------------------------------*/
     259             : 
     260       39651 : 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       39651 :     SrcRend_p->InputAvailable = FALSE;
     268       39651 :     SrcRend_p->PlayStatus = TDREND_PLAYSTATUS_PLAYING;
     269             :     /* SrcGain  */
     270       79302 :     for ( nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ )
     271             :     {
     272       39651 :         SrcRend_p->SrcGainMin_p[nC] = 0.0f;
     273       39651 :         SrcRend_p->SrcGain_p[nC] = 1.0f;
     274       39651 :         SrcRend_p->SrcGainMax_p[nC] = 2.0f;
     275             :     }
     276       39651 :     SrcRend_p->SrcGainUpdated = FALSE;
     277             : 
     278             :     /* Init directional and distance gains */
     279       79302 :     for ( nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ )
     280             :     {
     281       39651 :         SrcRend_p->DirGain_p[nC] = 1.0f;
     282       39651 :         SrcRend_p->DistGain_p[nC] = 1.0f;
     283             :     }
     284             : 
     285             : 
     286       39651 :     return;
     287             : }
     288             : 
     289             : 
     290             : /*-------------------------------------------------------------------*
     291             :  * TDREND_SRC_REND_UpdateFiltersFromSpatialParams()
     292             :  *
     293             :  * Update the HR filter due to spatial change.
     294             :  --------------------------------------------------------------------*/
     295             : 
     296     4816792 : 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     4816792 :     Listener_p = hBinRendererTd->Listener_p;
     323     4816792 :     HrFiltSet_p = hBinRendererTd->HrFiltSet_p;
     324             : 
     325     4816792 :     *filterlength = min( HrFiltSet_p->FiltLength, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
     326             : 
     327     4816792 :     if ( SrcSpatial_p->PosType == TDREND_POSTYPE_ABSOLUTE )
     328             :     {
     329             : 
     330             :         /* Absolute position */
     331     4715472 :         TDREND_SPATIAL_VecMapToNewCoordSystem( SrcSpatial_p->Pos_p, Listener_p->Pos, Listener_p->Front, Listener_p->Up, Listener_p->Right, ListRelPos, ListRelPosAbs );
     332     4715472 :         ListRelDist = TDREND_SPATIAL_VecNorm( ListRelPos );
     333             : 
     334             :         /* 2. Evaluate the Elevation and Azimuth angles  */
     335     4715472 :         if ( ( ListRelPos[0] == 0 ) && ( ListRelPos[1] == 0 ) && ( ListRelPos[2] == 0 ) )
     336             :         {
     337       49574 :             Elev = 0.0;
     338       49574 :             Azim = 0.0;
     339             :         }
     340             :         else
     341             :         {
     342     4665898 :             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     4665898 :             Azim = -1.0f * _180_OVER_PI * (float) atan2f( ListRelPos[1], ListRelPos[0] );
     345             :         }
     346             : 
     347     4715472 :         GetFilterFromAngle( HrFiltSet_p, Elev, Azim, *filterlength, hrf_left, hrf_right, itd );
     348             : 
     349             :         /* 6. Evaluate the directional and distance gains */
     350             :         /* Directional gain */
     351     4715472 :         *SrcRend_p->DirGain_p = 1.0f;
     352     4715472 :         if ( SrcSpatial_p->DirAttenEnabled )
     353             :         {
     354     4715472 :             *SrcRend_p->DirGain_p = TDREND_SRC_SPATIAL_GetDirGain( &SrcSpatial_p->DirAtten, SrcSpatial_p->Front_p, ListRelPosAbs );
     355             :         }
     356             : 
     357             :         /* Distance gain */
     358     4715472 :         *SrcRend_p->DistGain_p = 1.0f;
     359     4715472 :         if ( hBinRendererTd->UseCommonDistAttenModel )
     360             :         {
     361     4715472 :             if ( hBinRendererTd->DistAttenEnabled )
     362             :             {
     363     4715472 :                 SrcSpatial_p->DistAtten.DistAttenModel = hBinRendererTd->DistAttenModel;
     364     4715472 :                 *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     4715472 :         *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     4715472 :         elev_delta = Elev - Src_p->elev_prev;
     380     4715472 :         azim_delta = Azim - Src_p->azim_prev;
     381     4715472 :         Src_p->elev_prev = Elev;
     382     4715472 :         Src_p->azim_prev = Azim;
     383             : 
     384     4715472 :         azim_delta = ( azim_delta > 180.0f ) ? ( azim_delta - 360 ) : ( ( azim_delta < -180.0f ) ? ( azim_delta + 360 ) : ( azim_delta ) ); /* map to -180:180 range */
     385     4715472 :         *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      101320 :         *itd = 0;
     390      101320 :         *Gain = 1.0f;
     391      101320 :         set_f( hrf_left, 0.0f, *filterlength );
     392      101320 :         set_f( hrf_right, 0.0f, *filterlength );
     393      101320 :         hrf_left[0] = ( SrcSpatial_p->Pos_p[1] + 1.f ) * 0.5f;
     394      101320 :         hrf_right[0] = 1.f - hrf_left[0];
     395      101320 :         *intp_count = MAX_INTERPOLATION_STEPS;
     396      101320 :         Src_p->elev_prev = 0;
     397      101320 :         Src_p->azim_prev = 360.0f; /* Dummy angle -- sets max interpolation if switching to TDREND_POSTYPE_ABSOLUTE */
     398             :     }
     399             : 
     400     4816792 :     if ( ( *intp_count > 0 ) )
     401             :     {
     402             :         /* Set deltas for interpolation */
     403     4320375 :         v_sub( hrf_left, hrf_left_prev, hrf_left_delta, *filterlength );
     404     4320375 :         v_multc( hrf_left_delta, 1.0f / *intp_count, hrf_left_delta, *filterlength );
     405     4320375 :         v_sub( hrf_right, hrf_right_prev, hrf_right_delta, *filterlength );
     406     4320375 :         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      496417 :         mvr2r( hrf_left, hrf_left_prev, *filterlength );
     412      496417 :         mvr2r( hrf_right, hrf_right_prev, *filterlength );
     413      496417 :         set_f( hrf_left_delta, 0.0f, *filterlength );
     414      496417 :         set_f( hrf_right_delta, 0.0f, *filterlength );
     415             :     }
     416             : 
     417     4816792 :     return;
     418             : }
     419             : 
     420             : 
     421             : /*-------------------------------------------------------------------*
     422             :  * TDREND_SRC_SPATIAL_Alloc()
     423             :  *
     424             :  * Allocatie spatial properties of a source.
     425             :  --------------------------------------------------------------------*/
     426             : 
     427       39651 : 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       39651 :     *SrcSpatial_pp = NULL;
     434             : 
     435             :     /* Allocate the TDREND_SRC_t variable */
     436       39651 :     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       39651 :     *SrcSpatial_pp = SrcSpatial_p;
     442             : 
     443       39651 :     return IVAS_ERR_OK;
     444             : }
     445             : 
     446             : 
     447             : /*-------------------------------------------------------------------*
     448             :  * TDREND_SRC_SPATIAL_Dealloc()
     449             :  *
     450             :  * Deallocate spatial properties of a source.
     451             :  --------------------------------------------------------------------*/
     452             : 
     453       39651 : static void TDREND_SRC_SPATIAL_Dealloc(
     454             :     TDREND_SRC_SPATIAL_t *SrcSpatial_p /* i/o: Source spatial parameters */
     455             : )
     456             : {
     457       39651 :     if ( SrcSpatial_p == NULL )
     458             :     {
     459           0 :         return;
     460             :     }
     461             :     /* Free the SrcSpatial_p variable */
     462       39651 :     free( SrcSpatial_p );
     463       39651 :     SrcSpatial_p = NULL;
     464             : 
     465       39651 :     return;
     466             : }
     467             : 
     468             : 
     469             : /*-------------------------------------------------------------------*
     470             :  * TDREND_SRC_SPATIAL_Init()
     471             :  *
     472             :  * Initialize spatial properties of a source.
     473             :  --------------------------------------------------------------------*/
     474             : 
     475       39651 : 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       39651 :     SrcSpatial_p->Updated = FALSE;
     484             : 
     485             :     /* Source position, velocity and direction vectors */
     486       39651 :     SrcSpatial_p->PosType = PosType;
     487       79302 :     for ( nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ )
     488             :     {
     489             :         /* Source position */
     490       39651 :         TDREND_SPATIAL_VecInit( SrcSpatial_p->Pos_p + nC * 3, 0.0f, 0.0f, 0.0f );
     491             : 
     492             :         /* Source direction */
     493       39651 :         TDREND_SPATIAL_VecInit( SrcSpatial_p->Front_p + nC * 3, 0.0f, 0.0f, 1.0f );
     494             :     }
     495             : 
     496             :     /* Source directional attenuation */
     497       39651 :     SrcSpatial_p->DirAttenEnabled = FALSE;
     498       39651 :     SrcSpatial_p->DirAtten.ConeInnerAngle = 360.0f;
     499       39651 :     SrcSpatial_p->DirAtten.ConeOuterAngle = 360.0f;
     500       39651 :     SrcSpatial_p->DirAtten.ConeOuterGain = 1.0f;
     501             : 
     502             :     /* Source distance attenuation */
     503       39651 :     SrcSpatial_p->DistAttenEnabled = FALSE;
     504       39651 :     SrcSpatial_p->DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED;
     505       39651 :     SrcSpatial_p->DistAtten.RefDist = 1.0f;
     506       39651 :     SrcSpatial_p->DistAtten.MaxDist = 15.75f; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */
     507       39651 :     SrcSpatial_p->DistAtten.RollOffFactor = 1.0f;
     508             : 
     509       39651 :     return;
     510             : }
     511             : 
     512             : 
     513             : /*-------------------------------------------------------------------*
     514             :  * TDREND_SRC_SPATIAL_SetDirAtten()
     515             :  *
     516             :  * Sets the directional attenuation mode.
     517             :  --------------------------------------------------------------------*/
     518             : 
     519     2643981 : 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     2643981 :     SrcSpatial_p->DirAttenEnabled = TRUE;
     526     2643981 :     SrcSpatial_p->DirAtten.ConeInnerAngle = DirAtten_p->ConeInnerAngle;
     527     2643981 :     SrcSpatial_p->DirAtten.ConeOuterAngle = DirAtten_p->ConeOuterAngle;
     528     2643981 :     SrcSpatial_p->DirAtten.ConeOuterGain = DirAtten_p->ConeOuterGain;
     529             : 
     530     2643981 :     return;
     531             : }
     532             : 
     533             : /*-------------------------------------------------------------------*
     534             :  * TDREND_SRC_SPATIAL_SetDistAtten()
     535             :  *
     536             :  * Sets the distance attenuation.
     537             :  --------------------------------------------------------------------*/
     538             : 
     539       39651 : 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       39651 :     SrcSpatial_p->DistAttenEnabled = TRUE;
     545       39651 :     SrcSpatial_p->DistAtten.DistAttenModel = DistAtten_p->DistAttenModel;
     546       39651 :     SrcSpatial_p->DistAtten.MaxDist = DistAtten_p->MaxDist;
     547       39651 :     SrcSpatial_p->DistAtten.RefDist = DistAtten_p->RefDist;
     548       39651 :     SrcSpatial_p->DistAtten.RollOffFactor = DistAtten_p->RollOffFactor;
     549             : 
     550       39651 :     return;
     551             : }
     552             : 
     553             : 
     554             : /*-------------------------------------------------------------------*
     555             :  * TDREND_SRC_SPATIAL_SetGain()
     556             :  *
     557             :  * Set the object gain
     558             :  --------------------------------------------------------------------*/
     559             : 
     560     2604330 : 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     2604330 :     Src_p->SrcRend_p->SrcGain_p[0] = Gain;
     566             : 
     567     2604330 :     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     4715472 : 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     4715472 :     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     4715472 :     v_multc( RelPos_p, -1, Vec, 3 );
     594     4715472 :     ProjCoef = dotp( Vec, Front_p, 3 );
     595     4715472 :     NormRelPos = TDREND_SPATIAL_VecNorm( RelPos_p );
     596             : 
     597     4715472 :     if ( NormRelPos != 0.0f )
     598             :     {
     599     4665898 :         AngleDeg = _180_OVER_PI * acosf( ProjCoef / NormRelPos );
     600             :     }
     601             :     else
     602             :     {
     603       49574 :         AngleDeg = 0.0f;
     604             :     }
     605             : 
     606     4715472 :     if ( 2.0f * AngleDeg <= DirAtten_p->ConeInnerAngle )
     607             :     {
     608     4403421 :         DirGain = 1.0f;
     609             :     }
     610      312051 :     else if ( 2.0f * AngleDeg <= DirAtten_p->ConeOuterAngle )
     611             :     {
     612      301021 :         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       11030 :         DirGain = DirAtten_p->ConeOuterGain;
     617             :     }
     618             : 
     619     4715472 :     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     4715472 : 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     4715472 :     DistGain = 1.0f;
     639     4715472 :     Dist2 = Dist;
     640             : 
     641     4715472 :     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     4715472 :         case TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED:
     648     4715472 :             if ( Dist2 < DistAtten_p->RefDist )
     649             :             {
     650     1271684 :                 Dist2 = DistAtten_p->RefDist;
     651             :             }
     652             : 
     653     4715472 :             if ( Dist2 > DistAtten_p->MaxDist )
     654             :             {
     655       56614 :                 Dist2 = DistAtten_p->MaxDist;
     656             :             }
     657     4715472 :             DistGain = powf( DistAtten_p->RefDist / Dist2, DistAtten_p->RollOffFactor );
     658     4715472 :             break;
     659             :     }
     660             : 
     661     4715472 :     return DistGain;
     662             : }
     663             : 
     664             : 
     665             : /*-------------------------------------------------------------------*
     666             :  * TDREND_SRC_Alloc()
     667             :  *
     668             :  * Allocate a source.
     669             :  --------------------------------------------------------------------*/
     670             : 
     671       39651 : 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       39651 :     *Src_pp = NULL;
     679             : 
     680             :     /* Allocate the TDREND_SRC_t variable */
     681       39651 :     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       39651 :     Src_p->SrcSpatial_p = NULL;
     687             :     /* If source type is dynamic alloc the TDREND_SRC_SPATIAL_t variable */
     688       39651 :     if ( ( error = TDREND_SRC_SPATIAL_Alloc( &Src_p->SrcSpatial_p ) ) != IVAS_ERR_OK )
     689             :     {
     690           0 :         return error;
     691             :     }
     692             : 
     693       39651 :     if ( ( error = TDREND_SRC_REND_Alloc( &Src_p->SrcRend_p ) ) != IVAS_ERR_OK )
     694             :     {
     695           0 :         return error;
     696             :     }
     697             : 
     698       39651 :     *Src_pp = Src_p;
     699             : 
     700       39651 :     return IVAS_ERR_OK;
     701             : }
     702             : 
     703             : 
     704             : /*-------------------------------------------------------------------*
     705             :  * TDREND_SRC_Dealloc()
     706             :  *
     707             :  * Deallocate a source.
     708             :  --------------------------------------------------------------------*/
     709             : 
     710       39651 : void TDREND_SRC_Dealloc(
     711             :     TDREND_SRC_t *Src_p )
     712             : {
     713       39651 :     if ( Src_p == NULL )
     714             :     {
     715           0 :         return;
     716             :     }
     717             : 
     718             :     /* Delloc the TDREND_SRC_Spatial_t variable */
     719       39651 :     TDREND_SRC_SPATIAL_Dealloc( Src_p->SrcSpatial_p );
     720             : 
     721             :     /* Delloc the TDREND_SRC_REND__t variable */
     722       39651 :     free( Src_p->SrcRend_p );
     723       39651 :     Src_p->SrcRend_p = NULL;
     724             : 
     725             :     /* Free the Src_p variable */
     726       39651 :     free( Src_p );
     727       39651 :     Src_p = NULL;
     728             : 
     729       39651 :     return;
     730             : }
     731             : 
     732             : 
     733             : /*-------------------------------------------------------------------*
     734             :  * TDREND_SRC_Init()
     735             :  *
     736             :  * Initializes a source.
     737             :  --------------------------------------------------------------------*/
     738             : 
     739       39651 : 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       39651 :     if ( Src_p->SrcSpatial_p != NULL )
     746             :     {
     747       39651 :         TDREND_SRC_SPATIAL_Init( Src_p->SrcSpatial_p, PosType );
     748             :     }
     749             : 
     750             :     /* Init the TDREND_SRC_REND_t variable */
     751       39651 :     TDREND_SRC_REND_Init( Src_p->SrcRend_p );
     752             : 
     753             :     /* Reset memory buffers */
     754       39651 :     Src_p->itd = 0;
     755       39651 :     Src_p->previtd = 0;
     756       39651 :     Src_p->filterlength = 1; /* Init to unit impulse of length 1 */
     757       39651 :     set_f( Src_p->mem_itd, 0.0f, ITD_MEM_LEN );
     758       39651 :     set_f( Src_p->mem_hrf_left, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 );
     759       39651 :     set_f( Src_p->mem_hrf_right, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 );
     760             : 
     761       39651 :     set_f( Src_p->hrf_left_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
     762       39651 :     set_f( Src_p->hrf_right_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
     763       39651 :     Src_p->hrf_left_prev[0] = 1;
     764       39651 :     Src_p->hrf_right_prev[0] = 1;
     765       39651 :     Src_p->azim_prev = 0.0f;
     766       39651 :     Src_p->elev_prev = 0.0f;
     767       39651 :     Src_p->Gain = 1;
     768       39651 :     Src_p->prevGain = 1.0f;
     769             : 
     770       39651 :     return;
     771             : }

Generated by: LCOV version 1.14