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

Generated by: LCOV version 1.14