LCOV - code coverage report
Current view: top level - lib_rend - ivas_shoebox_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 261 288 90.6 %
Date: 2025-08-23 01:22:27 Functions: 6 6 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 "options.h"
      34             : #include <stdint.h>
      35             : #include <math.h>
      36             : #include "ivas_prot_rend_fx.h"
      37             : #include "ivas_stat_rend.h"
      38             : #include "ivas_prot_fx.h"
      39             : #include "ivas_cnst.h"
      40             : #include "prot_fx.h"
      41             : #include "wmc_auto.h"
      42             : #include "ivas_rom_com.h"
      43             : #include "ivas_rom_com_fx.h"
      44             : 
      45             : 
      46             : /*-------------------------------------------------------------------------
      47             :  * Local constants
      48             :  *------------------------------------------------------------------------*/
      49             : 
      50             : #define ER_MAX_SOURCES                   25
      51             : #define ER_REF_ORDER                     1
      52             : #define ER_AIR_COEFF_FX                  ( Word32 )( 2942053 ) // 0.00137f in Q.31
      53             : #define ER_SOUND_SPEED_FX                ( Word32 )( 6260885 ) // 1/343.0f in Q1.31
      54             : #define ER_MIN_WALL_DIST_FX              ( Word32 )( 419430 )  // Q.22
      55             : #define ER_EUCLIDEAN_SCALE_FX            ( 0x1 )               // Q.22
      56             : #define ER_RECIPROCAL_EUCLIDEAN_SCALE_FX ( 0x1 )               // Q.22
      57             : 
      58             : 
      59             : /*-----------------------------------------------------------------------------------------*
      60             :  * Function ivas_shoebox_config_init
      61             :  *
      62             :  * Function transfer the parameters from the reverb config handle to the shoebox
      63             :  * calibration data structure.
      64             :  *-----------------------------------------------------------------------------------------*/
      65             : 
      66           4 : void ivas_shoebox_config_init(
      67             :     shoebox_config_t *cal,
      68             :     RENDER_CONFIG_HANDLE hRenderConfig /* i  : Renderer configuration handle     */
      69             : )
      70             : {
      71             :     UWord16 wall_idx;
      72             : 
      73             : 
      74           4 :     cal->room_L_fx = hRenderConfig->roomAcoustics.dimensions.x_fx; // Q.22
      75           4 :     cal->room_W_fx = hRenderConfig->roomAcoustics.dimensions.y_fx; // Q.22
      76           4 :     cal->room_H_fx = hRenderConfig->roomAcoustics.dimensions.z_fx; // Q.22
      77           4 :     move32();
      78           4 :     move32();
      79           4 :     move32();
      80             : 
      81             :     /*  Absorption Coefficients */
      82             :     /*  Convention: [Front wall, Back wall, Left wall, Right wall, Ceiling, Floor] */
      83          28 :     FOR( wall_idx = 0; wall_idx < 6; wall_idx++ )
      84             :     {
      85          24 :         cal->abs_coeff_fx[wall_idx] = hRenderConfig->roomAcoustics.AbsCoeff_fx[wall_idx]; // Q2.30
      86          24 :         move32();
      87             :     }
      88             : 
      89             :     /* Listener position (only X and Y can be pos. or neg. ) */
      90           4 :     cal->list_orig_fx[0] = hRenderConfig->roomAcoustics.ListenerOrigin.x_fx; // Q.22
      91           4 :     cal->list_orig_fx[1] = hRenderConfig->roomAcoustics.ListenerOrigin.y_fx; // Q.22
      92           4 :     cal->list_orig_fx[2] = hRenderConfig->roomAcoustics.ListenerOrigin.z_fx; // Q.22
      93           4 :     move32();
      94           4 :     move32();
      95           4 :     move32();
      96             : 
      97           4 :     return;
      98             : }
      99             : 
     100             : 
     101             : /*-----------------------------------------------------------------------------------------*
     102             :  * Function ivas_shoebox_init()
     103             :  *
     104             :  * Function initializes the shoebox operating parameters by setting limits and defaults,
     105             :  * also contains the calibration structure.
     106             :  *-----------------------------------------------------------------------------------------*/
     107           4 : void ivas_shoebox_init(
     108             :     shoebox_obj_t *obj,
     109             :     shoebox_config_t *cal )
     110             : {
     111             :     UWord16 i;
     112             : 
     113             :     /* Add cal to obj struct */
     114           4 :     obj->cal = *cal;
     115           4 :     move32();
     116             :     /* Add defaults */
     117           4 :     obj->max_bands = 1;
     118           4 :     obj->MAX_SOURCES = ER_MAX_SOURCES; // Q0
     119           4 :     obj->REF_ORDER = ER_REF_ORDER;     // Q0
     120           4 :     move16();
     121           4 :     move16();
     122           4 :     move16();
     123             : 
     124             :     /*  Positions */
     125             : 
     126           4 :     set32_fx( &obj->src_pos_fx[0], 0, 75U );
     127           4 :     set32_fx( &obj->src_dist_fx[0], 0, 25U );
     128             : 
     129          16 :     FOR( i = 0; i < 3; i++ )
     130             :     {
     131          12 :         obj->list_pos_fx[i] = cal->list_orig_fx[i]; // Q.22
     132          12 :         move32();
     133             :     }
     134             : 
     135             :     /*  Pointer */
     136           4 :     obj->nSrc = 0;
     137           4 :     move16();
     138             : 
     139             :     /*  Flags */
     140           4 :     obj->isCartesian = 1;
     141           4 :     obj->isRelative = 1;
     142           4 :     obj->isZHeight = 1;
     143           4 :     obj->isRadians = 1;
     144           4 :     move16();
     145           4 :     move16();
     146           4 :     move16();
     147           4 :     move16();
     148             : 
     149             :     /*  Params */
     150           4 :     obj->radius_fx = ER_RADIUS_FX;               // Q30
     151           4 :     obj->min_wall_dist_fx = ER_MIN_WALL_DIST_FX; // Q22
     152           4 :     obj->soundspeed_fx = ER_SOUND_SPEED_FX;      // Q31
     153           4 :     obj->air_coeff_fx = ER_AIR_COEFF_FX;         // Q31
     154           4 :     move32();
     155           4 :     move32();
     156           4 :     move32();
     157           4 :     move32();
     158             : 
     159           4 :     return;
     160             : }
     161             : 
     162             : 
     163             : /*-----------------------------------------------------------------------------------------*
     164             :  * Function shoebox_bound()
     165             :  *
     166             :  *  SHOEBOX_BOUND takes in CARTESIAN coordinates of either a receiver or
     167             :  *  source and checks if it is within the virtual room boundaries established
     168             :  *  by the surface parameters. If object is out of bounds, then new cartesian
     169             :  *  coordinates are established to collapse the object position.
     170             :  *-----------------------------------------------------------------------------------------*/
     171          42 : static void shoebox_bound_fx(
     172             :     shoebox_obj_t *obj,
     173             :     Word32 *out_pos // Q22
     174             : )
     175             : {
     176             :     Word32 out_tmp, out_tmp1;
     177             :     Word32 i;
     178             : 
     179          42 :     out_tmp = L_sub( L_shr( obj->cal.room_L_fx, 1 ), obj->min_wall_dist_fx );              // Q.22
     180          42 :     out_tmp1 = L_add( L_shr( L_negate( obj->cal.room_L_fx ), 1 ), obj->min_wall_dist_fx ); // Q.22
     181          42 :     test();
     182          42 :     IF( GT_32( out_pos[0], out_tmp ) || LT_32( out_pos[0], out_tmp1 ) )
     183             :     {
     184           1 :         IF( out_pos[0] < 0 )
     185             :         {
     186           0 :             i = -1;
     187           0 :             move32();
     188             :         }
     189             :         ELSE
     190             :         {
     191           1 :             IF( out_pos[0] > 0 )
     192             :             {
     193           1 :                 i = (Word32) 1;
     194             :             }
     195             :             ELSE
     196             :             {
     197           0 :                 i = (Word32) 0;
     198             :             }
     199           1 :             move32();
     200             :         }
     201             : 
     202           1 :         out_pos[0] = W_extract_l( W_mult0_32_32( out_tmp, i ) );
     203           1 :         move32();
     204             :     }
     205             : 
     206          42 :     out_tmp = L_sub( L_shr( obj->cal.room_W_fx, 1 ), obj->min_wall_dist_fx );              // Q.22
     207          42 :     out_tmp1 = L_add( L_shr( L_negate( obj->cal.room_W_fx ), 1 ), obj->min_wall_dist_fx ); // Q.22
     208             : 
     209          42 :     test();
     210          42 :     IF( GT_32( out_pos[1], out_tmp ) || LT_32( out_pos[1], out_tmp1 ) )
     211             :     {
     212           1 :         IF( out_pos[1] < 0 )
     213             :         {
     214           1 :             i = -1;
     215           1 :             move32();
     216             :         }
     217             :         ELSE
     218             :         {
     219           0 :             IF( out_pos[1] > 0 )
     220             :             {
     221           0 :                 i = (Word32) 1;
     222             :             }
     223             :             ELSE
     224             :             {
     225           0 :                 i = (Word32) 0;
     226             :             }
     227           0 :             move32();
     228             :         }
     229           1 :         out_pos[1] = W_extract_l( W_mult0_32_32( out_tmp, i ) ); // Q22
     230           1 :         move32();
     231             :     }
     232             : 
     233          42 :     out_tmp = L_sub( L_shr( obj->cal.room_H_fx, 1 ), obj->min_wall_dist_fx );              // Q.22
     234          42 :     out_tmp1 = L_add( L_shr( L_negate( obj->cal.room_H_fx ), 1 ), obj->min_wall_dist_fx ); // Q.22
     235             : 
     236          42 :     test();
     237          42 :     IF( GT_32( out_pos[2], out_tmp ) || LT_32( out_pos[2], out_tmp1 ) )
     238             :     {
     239           0 :         IF( out_pos[2] < 0 )
     240             :         {
     241           0 :             i = -1;
     242           0 :             move32();
     243             :         }
     244             :         ELSE
     245             :         {
     246           0 :             IF( out_pos[2] > 0 )
     247             :             {
     248           0 :                 i = (Word32) 1;
     249             :             }
     250             :             ELSE
     251             :             {
     252           0 :                 i = (Word32) 0;
     253             :             }
     254           0 :             move32();
     255             :         }
     256           0 :         out_pos[2] = W_extract_l( W_mult0_32_32( out_tmp, (Word32) i ) ); // Q22
     257           0 :         move32();
     258             :     }
     259             : 
     260          42 :     return;
     261             : }
     262             : 
     263             : 
     264             : /*-----------------------------------------------------------------------------------------*
     265             :  * Function shoebox_get_coord()
     266             :  *
     267             :  * Transform relative spherical coordinate to 3D cartesian point
     268             :  *-----------------------------------------------------------------------------------------*/
     269             : 
     270             : 
     271          38 : static void shoebox_get_coord_fx(
     272             :     shoebox_obj_t *obj,
     273             :     Word32 *fcnOutput_data,      // 0th and 1st idx in Q0 and 2nd idx in Q30
     274             :     const Word32 src_pos_data[], // Q22
     275             :     Word32 *tmp_pos,             // Q22
     276             :     Word32 out_tmp,
     277             :     Word32 coord,
     278             :     Word32 loop_ub,
     279             :     Word32 k,
     280             :     UWord16 isRelative )
     281             : {
     282             :     Word32 tmp_data[3];
     283             :     Word32 rcoselev;
     284             :     Word32 tmp_size_idx_1;
     285             :     Word32 n;
     286             : 
     287          38 :     tmp_size_idx_1 = 3;
     288          38 :     move32();
     289          38 :     IF( obj->isCartesian == 0 )
     290             :     {
     291             :         /*   Convert Spherical to Cartesian  */
     292          38 :         tmp_data[2] = Mpy_32_32( fcnOutput_data[2] /* Q30 */, shoebox_sin_cos_tbl_fx[fcnOutput_data[1] /* Q0 */][0] ); // Q29 = .Q30 * Q30
     293          38 :         move32();
     294          38 :         rcoselev = Mpy_32_32( fcnOutput_data[2] /* Q30 */, shoebox_sin_cos_tbl_fx[fcnOutput_data[1] /* Q0 */][1] ); // Q29 = Q30 * Q30
     295          38 :         tmp_data[0] = Mpy_32_32( rcoselev, shoebox_sin_cos_tbl_fx[fcnOutput_data[0] /* Q0 */][1] );                 // Q28 =Q29*Q30
     296          38 :         move32();
     297          38 :         tmp_data[1] = Mpy_32_32( rcoselev, shoebox_sin_cos_tbl_fx[fcnOutput_data[0] /* Q0 */][0] ); // Q28 = Q29*Q30
     298          38 :         move32();
     299          38 :         tmp_data[0] = L_shr( tmp_data[0], 6 ); // Q28 -> Q22
     300          38 :         move32();
     301          38 :         tmp_data[1] = L_shr( tmp_data[1], 6 ); // Q28 -> Q22
     302          38 :         move32();
     303          38 :         tmp_data[2] = L_shr( tmp_data[2], 7 ); // Q29 -> Q22
     304          38 :         move32();
     305             :     }
     306             :     ELSE
     307             :     {
     308             :         /*   CARTESIAN CASE */
     309           0 :         tmp_size_idx_1 = loop_ub;
     310           0 :         move32();
     311           0 :         FOR( n = 0; n < loop_ub; n++ )
     312             :         {
     313           0 :             tmp_data[n] = src_pos_data[k + n];
     314           0 :             move32();
     315             :         }
     316           0 :         IF( obj->isZHeight != 0 )
     317             :         {
     318             :             /*  FIX Z COORDINATE */
     319           0 :             tmp_data[2] = L_sub( src_pos_data[k + 2] /* Q22 */, L_shr( obj->cal.room_H_fx, 1 ) ); // Q22
     320           0 :             move32();
     321             :         }
     322             :     }
     323             : 
     324         152 :     FOR( k = 0; k < tmp_size_idx_1; k++ )
     325             :     {
     326         114 :         obj->src_pos_fx[coord + k - 1] = tmp_data[k]; // Q22
     327         114 :         move32();
     328             :     }
     329             : 
     330             :     /*   CENTER TO LISTENER */
     331             : 
     332          38 :     k = L_add( out_tmp, 1 );
     333             : 
     334          38 :     tmp_pos[0] = obj->src_pos_fx[k - 1]; // Q22
     335          38 :     tmp_pos[1] = obj->src_pos_fx[k];     // Q22
     336          38 :     tmp_pos[2] = obj->src_pos_fx[k + 1]; // Q22
     337          38 :     move32();
     338          38 :     move32();
     339          38 :     move32();
     340             : 
     341          38 :     IF( isRelative != 0 )
     342             :     {
     343          38 :         tmp_pos[0] = L_add( tmp_pos[0], obj->list_pos_fx[0] ); // Q22
     344          38 :         tmp_pos[1] = L_add( tmp_pos[1], obj->list_pos_fx[1] ); // Q22
     345          38 :         tmp_pos[2] = L_add( tmp_pos[2], obj->list_pos_fx[2] ); // Q22
     346             : 
     347          38 :         move32();
     348          38 :         move32();
     349          38 :         move32();
     350             :     }
     351             : 
     352          38 :     return;
     353             : }
     354             : 
     355             : 
     356             : /*-----------------------------------------------------------------------------------------*
     357             :  * Function shoebox_get_euclidian_distance_internal()
     358             :  *
     359             :  * Get 3D source distance from receiver
     360             :  *-----------------------------------------------------------------------------------------*/
     361         266 : static Word32 shoebox_get_euclidian_distance_internal_fx(
     362             :     shoebox_obj_t *obj,
     363             :     Word32 *tmp_pos, // Q22
     364             :     Word32 *scale    // Q22
     365             : )
     366             : {
     367             :     Word32 absxk, out_tmp, t;
     368             :     Word16 q;
     369             : 
     370         266 :     absxk = L_abs( L_sub( obj->list_pos_fx[0], tmp_pos[0] ) ); // Q22-Q22
     371             : 
     372         266 :     IF( GT_32( absxk, ER_EUCLIDEAN_SCALE_FX ) )
     373             :     {
     374         236 :         out_tmp = ONE_IN_Q22; // 1 in Q22
     375         236 :         *scale = absxk;       // Q22
     376         236 :         move32();
     377         236 :         move32();
     378             :     }
     379             :     ELSE
     380             :     {
     381          30 :         t = (Word32) W_mult0_32_32( absxk, ER_RECIPROCAL_EUCLIDEAN_SCALE_FX ); // Q22
     382          30 :         out_tmp = W_extract_h( W_shl( W_mult_32_32( t, t ), 9 ) );             // Q22 + Q22 + Q1 + Q9 - 32 = Q22
     383             :     }
     384             : 
     385         266 :     absxk = L_abs( L_sub( obj->list_pos_fx[1], tmp_pos[1] ) );
     386             : 
     387         266 :     IF( GT_32( absxk, *scale ) )
     388             :     {
     389         100 :         q = Q22;
     390         100 :         move16();
     391         100 :         t = (Word32) BASOP_Util_Divide3232_Scale_newton( *scale, absxk, &q );
     392             : 
     393         100 :         out_tmp = W_extract_h( W_shl( W_mult_32_32( out_tmp, t ), q ) ); // Q22 + Q31 + Q1 - 32 = Q22
     394         100 :         out_tmp = W_extract_h( W_shl( W_mult_32_32( out_tmp, t ), q ) ); // Q22 + Q31 + Q1 - 32 = Q22
     395         100 :         out_tmp = L_add( out_tmp, ONE_IN_Q22 );                          // Q22
     396         100 :         *scale = absxk;                                                  // Q22
     397         100 :         move32();
     398             :     }
     399             :     ELSE
     400             :     {
     401         166 :         t = (Word32) BASOP_Util_Divide3232_Scale_newton( absxk, *scale, &q );
     402         166 :         t = W_extract_h( W_shl( W_mult_32_32( t, t ), sub( shl( q, 1 ), 9 ) ) ); // Q31 + Q31 + Q1 - 9 - 32 = Q22
     403         166 :         out_tmp = L_add( out_tmp, t );                                           // Q22
     404         166 :         move32();
     405             :     }
     406             : 
     407         266 :     absxk = L_abs( L_sub( obj->list_pos_fx[2], tmp_pos[2] ) );
     408             : 
     409         266 :     IF( GE_32( absxk, *scale ) )
     410             :     {
     411          76 :         t = (Word32) BASOP_Util_Divide3232_Scale_newton( *scale, absxk, &q );
     412             : 
     413          76 :         out_tmp = W_extract_h( W_shl( W_mult_32_32( out_tmp, t ), q ) ); // Q22 + Q31 + Q1 - 32 = Q22
     414          76 :         out_tmp = W_extract_h( W_shl( W_mult_32_32( out_tmp, t ), q ) ); // Q22 + Q31 + Q1 - 32 = Q22
     415          76 :         out_tmp = L_add( out_tmp, ONE_IN_Q22 );                          // Q22
     416          76 :         *scale = absxk;                                                  // Q22
     417          76 :         move32();
     418             :     }
     419             :     ELSE
     420             :     {
     421         190 :         t = (Word32) BASOP_Util_Divide3232_Scale_newton( absxk, *scale, &q );
     422         190 :         t = W_extract_h( W_shl( W_mult_32_32( t, t ), sub( shl( q, 1 ), 9 ) ) ); // Q31 + Q31 + Q1 - 9 - 32 = Q22
     423         190 :         out_tmp = L_add( out_tmp, t );                                           // Q22
     424             :     }
     425             : 
     426         266 :     return out_tmp;
     427             : }
     428             : 
     429             : 
     430             : /*-----------------------------------------------------------------------------------------*
     431             :  * Function ivas_shoebox_set_scene()
     432             :  *
     433             :  * Initial scene setup returning computed reflection (arrival times, DOA and gain).
     434             :  *-----------------------------------------------------------------------------------------*/
     435             : 
     436           4 : void ivas_shoebox_set_scene(
     437             :     shoebox_obj_t *obj,
     438             :     shoebox_output_t *ER_PARAMS,
     439             :     const Word32 list_pos_fx[3], // Q22
     440             :     const Word32 src_pos_data[], // 0th and 1st idx in Q0 and 2nd idx in Q30
     441             :     const UWord16 isCartesian,
     442             :     const UWord16 isRelative )
     443             : {
     444             : 
     445             :     Word32 tmp_pos_fx[3];
     446             :     Word32 out_tmp;
     447             :     Word32 k, n;
     448             :     Word32 loop_ub, out_tmp_fx;
     449             :     Word16 q_format1, q_format, i, j;
     450             : 
     451             :     /*  ------------- SET FLAGS ------------- */
     452           4 :     obj->isCartesian = isCartesian;
     453           4 :     obj->isRelative = isRelative;
     454           4 :     move16();
     455           4 :     move16();
     456             :     /*  ------------- CHECK DIMENSIONS ------------- */
     457           4 :     IF( GE_16( ER_PARAMS->n_sources, obj->MAX_SOURCES ) )
     458             :     {
     459           0 :         obj->nSrc = obj->MAX_SOURCES;
     460             :     }
     461             :     ELSE
     462             :     {
     463           4 :         obj->nSrc = ER_PARAMS->n_sources;
     464             :     }
     465           4 :     move16();
     466             : 
     467           4 :     set32_fx( &obj->src_pos_fx[0], 0, 75U );
     468             : 
     469           4 :     obj->list_pos_fx[0] = list_pos_fx[0]; // Q22
     470           4 :     obj->list_pos_fx[1] = list_pos_fx[1]; // Q22
     471           4 :     obj->list_pos_fx[2] = list_pos_fx[2]; // Q22
     472           4 :     move32();
     473           4 :     move32();
     474           4 :     move32();
     475             :     /*  ---------- ADJUST LISTENER ------------- */
     476           4 :     IF( obj->isZHeight != 0 )
     477             :     {
     478           4 :         obj->list_pos_fx[2] = L_sub( list_pos_fx[2], L_shr( obj->cal.room_H_fx, 1 ) ); // Q22
     479           4 :         move32();
     480             :     }
     481           4 :     tmp_pos_fx[1] = obj->list_pos_fx[1]; // Q22
     482           4 :     tmp_pos_fx[2] = obj->list_pos_fx[2]; // Q22
     483           4 :     move32();
     484           4 :     move32();
     485             : 
     486           4 :     shoebox_bound_fx( obj, obj->list_pos_fx );
     487             : 
     488             : 
     489             :     /*  ---------- SOURCE LOOP ------------- */
     490           4 :     i = obj->nSrc;
     491           4 :     move32();
     492          42 :     FOR( j = 0; j < i; j++ )
     493             :     {
     494             :         Word32 fcnOutput_data_fx[3], scale_fx;
     495             :         Word32 rcoselev;
     496             :         Word32 coord;
     497             : 
     498             :         /* idx = single(i); */
     499          38 :         out_tmp = L_mult0( 3, j );
     500             :         /*   GET COORDINATE IN CARTESIAN ABSOLUTE FORMAT */
     501          38 :         k = out_tmp;
     502          38 :         move32();
     503          38 :         n = L_add( out_tmp, 3 );
     504          38 :         coord = L_add( out_tmp, 1 );
     505             : 
     506          38 :         loop_ub = L_sub( n, k );
     507             : 
     508         152 :         FOR( n = 0; n < loop_ub; n++ )
     509             :         {
     510         114 :             fcnOutput_data_fx[n] = src_pos_data[k + n];
     511         114 :             move32();
     512             :         }
     513             : 
     514          38 :         shoebox_get_coord_fx( obj, fcnOutput_data_fx, src_pos_data, tmp_pos_fx, out_tmp, coord, loop_ub, k, isRelative );
     515          38 :         shoebox_bound_fx( obj, tmp_pos_fx );
     516             : 
     517          38 :         scale_fx = ER_EUCLIDEAN_SCALE_FX; // Q22
     518          38 :         move32();
     519          38 :         out_tmp_fx = shoebox_get_euclidian_distance_internal_fx( obj, tmp_pos_fx, &scale_fx );
     520          38 :         q_format = Q31 - Q22;
     521          38 :         move16();
     522          38 :         out_tmp_fx = Sqrt32( out_tmp_fx, &q_format );
     523          38 :         out_tmp_fx = Mpy_32_32( scale_fx, out_tmp_fx );
     524          38 :         obj->src_dist_fx[j] = L_shl( out_tmp_fx, q_format ); // Q22
     525          38 :         move32();
     526             : 
     527             : 
     528             :         /*   COMPUTE PATTERNS */
     529             : 
     530             :         /*  SHOEBOX_COMPUTE: fills an input structure (4 array fields of length NxR ) with the */
     531             :         /*  Early reflection metadata (time of arrival, gain, az, el). */
     532             :         /*  */
     533             :         /*  Input: */
     534             :         /*  1. obj        : Module data holder */
     535             :         /*  2. ER_struct  : Early reflection structure */
     536             :         /*  3. src_num    : Index of source to compute patterns for */
     537             :         /*  ------ */
     538          38 :         out_tmp_fx = obj->src_dist_fx[j]; // Q22
     539          38 :         move32();
     540             : 
     541         266 :         FOR( loop_ub = 0; loop_ub < 6; loop_ub++ )
     542             :         {
     543             : 
     544             :             Word32 im_pos_fx[3];
     545             :             Word32 path_dist_fx;
     546             :             Word32 asin_val;
     547             :             Word32 sub_im_nd_list_pos_1, sub_im_nd_list_pos_0, atan_pos, az_angle_d;
     548             :             Word32 one_minus_abs_coeff, out_tmp_div_path_dist, product, pro_pd_air_coeff, result_gain;
     549             :             Word32 sub_im_nd_list_div_path, one_minus_sub_im_nd_list_div_path_sq, sub_im_nd_list_div_path_sq, one_minus_sub_im_nd_list_div_path_sq_rt, asin_val_deg;
     550             :             Word16 q_format_n;
     551             : 
     552             :             /*  Retrieve coordinate and surface sign */
     553         228 :             coord = L_shr( loop_ub, 1 ); // tbl
     554         228 :             rcoselev = L_add( L_add( loop_ub, 1 ), L_mult0( (Word16) ER_PARAMS->n_ref, j ) );
     555             : 
     556             :             /*  Initialize image position coordinates */
     557         228 :             im_pos_fx[0] = tmp_pos_fx[0]; // Q:22
     558         228 :             im_pos_fx[1] = tmp_pos_fx[1]; // Q:22
     559         228 :             im_pos_fx[2] = tmp_pos_fx[2]; // Q:22
     560         228 :             move32();
     561         228 :             move32();
     562         228 :             move32();
     563             : 
     564             :             /*  Calculate image projection coordinate based on current surface axis */
     565         228 :             IF( LT_32( L_add( loop_ub, 1 ), 3 ) )
     566             :             {
     567          76 :                 scale_fx = obj->cal.room_L_fx; // Q:22
     568          76 :                 move32();
     569             :             }
     570         152 :             ELSE IF( LT_32( L_add( loop_ub, 1 ), 5 ) )
     571             :             {
     572          76 :                 scale_fx = obj->cal.room_W_fx; // Q:22
     573          76 :                 move32();
     574             :             }
     575             :             ELSE
     576             :             {
     577          76 :                 scale_fx = obj->cal.room_H_fx; // Q:22
     578          76 :                 move32();
     579             :             }
     580             : 
     581             : 
     582         228 :             im_pos_fx[coord] =
     583         228 :                 L_add( tmp_pos_fx[coord],
     584             :                        L_shl( L_sub( L_shr( W_extract_l( W_mult0_32_32( ( L_negate( L_sub( 1, L_shl( L_and( L_add( loop_ub, 1 ), 1 ), 1 ) ) ) ), scale_fx ) ), 1 ), tmp_pos_fx[coord] ), 1 ) ); // Q:22
     585         228 :             move32();
     586             : 
     587             :             /*  0. Get euclidean distance from IMAGE SOURCE [N,W] to LIST */
     588         228 :             scale_fx = ER_EUCLIDEAN_SCALE_FX; // Q:22
     589         228 :             move32();
     590         228 :             path_dist_fx = shoebox_get_euclidian_distance_internal_fx( obj, im_pos_fx, &scale_fx ); // Uutput :Q:22
     591             : 
     592         228 :             q_format = Q31 - Q22;
     593         228 :             move16();
     594         228 :             path_dist_fx = Sqrt32( path_dist_fx, &q_format ); // Input: Q:22, Output : Q30
     595             : 
     596         228 :             path_dist_fx = Mpy_32_32( scale_fx, path_dist_fx ); // Q22 + (31 - q_format) - 31 = Q22 - q_format
     597         228 :             path_dist_fx = L_shl( path_dist_fx, q_format );     // Q22 - q_format + (q_format) = Q22
     598             : 
     599             : 
     600             :             /*  1. Compute time-of arrival (TOA) */
     601         228 :             ER_PARAMS->times.data_fx[rcoselev - 1] = Mpy_32_32( path_dist_fx, obj->soundspeed_fx ); // Q22
     602         228 :             move32();
     603             : 
     604             :             /*  2./3. DOA */
     605         228 :             sub_im_nd_list_pos_1 = L_sub( im_pos_fx[1], obj->list_pos_fx[1] ); // Q22
     606         228 :             sub_im_nd_list_pos_0 = L_sub( im_pos_fx[0], obj->list_pos_fx[0] ); // Q22
     607         228 :             q_format = Q22 - Q22;
     608         228 :             move16();
     609         228 :             atan_pos = BASOP_util_atan2( sub_im_nd_list_pos_1, sub_im_nd_list_pos_0, q_format ); // Q13
     610         228 :             az_angle_d = rad2deg_fx( atan_pos );                                                 // Q23
     611         228 :             ER_PARAMS->az_angle.data_fx[rcoselev - 1] = az_angle_d;
     612         228 :             move32();
     613             : 
     614             : 
     615         228 :             q_format = Q22;
     616         228 :             move16();
     617         228 :             sub_im_nd_list_div_path = BASOP_Util_Divide3232_Scale( ( L_sub( im_pos_fx[2], obj->list_pos_fx[2] ) ), path_dist_fx, &q_format );
     618         228 :             sub_im_nd_list_div_path = L_shl( sub_im_nd_list_div_path, q_format );
     619         228 :             sub_im_nd_list_div_path = L_deposit_h( (Word16) sub_im_nd_list_div_path );
     620         228 :             sub_im_nd_list_div_path_sq = Mpy_32_32( sub_im_nd_list_div_path, sub_im_nd_list_div_path );
     621         228 :             sub_im_nd_list_div_path_sq = L_shr( sub_im_nd_list_div_path_sq, 1 );
     622         228 :             one_minus_sub_im_nd_list_div_path_sq = L_sub( L_shl( 1, Q30 ), sub_im_nd_list_div_path_sq );
     623         228 :             q_format1 = Q31 - Q30;
     624         228 :             move16();
     625             : 
     626         228 :             one_minus_sub_im_nd_list_div_path_sq_rt = Sqrt32( one_minus_sub_im_nd_list_div_path_sq, &q_format1 );
     627         228 :             one_minus_sub_im_nd_list_div_path_sq_rt = L_shl( one_minus_sub_im_nd_list_div_path_sq_rt, q_format1 );
     628             : 
     629             : 
     630         228 :             q_format_n = Q31 - Q31;
     631         228 :             asin_val = BASOP_util_atan2( sub_im_nd_list_div_path, one_minus_sub_im_nd_list_div_path_sq_rt, q_format_n ); // Q13
     632             : 
     633         228 :             asin_val_deg = rad2deg_fx( asin_val ); // Q23
     634         228 :             ER_PARAMS->el_angle.data_fx[rcoselev - 1] = asin_val_deg;
     635         228 :             move32();
     636             : 
     637             : 
     638             :             /*  4. Compute gain taking into account air and surface absorption */
     639             :             /*  and propagation loss */
     640         228 :             if ( LT_32( path_dist_fx, out_tmp_fx ) )
     641             :             {
     642           0 :                 path_dist_fx = out_tmp_fx; // Q22
     643           0 :                 move32();
     644             :             }
     645             : 
     646         228 :             one_minus_abs_coeff = L_sub( ( ONE_IN_Q30 ), obj->cal.abs_coeff_fx[loop_ub] ); // Q30=Q30-Q30
     647         228 :             q_format_n = Q22;
     648         228 :             move16();
     649         228 :             out_tmp_div_path_dist = BASOP_Util_Divide3232_Scale( out_tmp_fx, path_dist_fx, &q_format_n ); // Q22/Q.22
     650         228 :             product = Mpy_32_32( one_minus_abs_coeff, out_tmp_div_path_dist );                            // Q.30 *Q.15
     651         228 :             product = L_shl( product, q_format_n );                                                       // Q14
     652         228 :             product = L_shl( product, Q8 );                                                               // Q22
     653             : 
     654         228 :             pro_pd_air_coeff = Mpy_32_32( path_dist_fx, obj->air_coeff_fx ); // Q.22 *Q.31 =Q.22
     655         228 :             result_gain = L_sub( product, pro_pd_air_coeff );
     656         228 :             ER_PARAMS->gains.data_fx[rcoselev - 1] = result_gain; // Q22
     657         228 :             move32();
     658             :         }
     659             :     }
     660           4 :     return;
     661             : }

Generated by: LCOV version 1.14