LCOV - code coverage report
Current view: top level - lib_dec - ivas_ism_renderer_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ ca3146eb9de8185ed0247945c643267826a32a94 Lines: 258 265 97.4 %
Date: 2025-08-26 01:31:27 Functions: 7 7 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 "ivas_cnst.h"
      36             : #include "prot_fx.h"
      37             : #include "ivas_prot_fx.h"
      38             : #include "ivas_prot_rend_fx.h"
      39             : #include "ivas_stat_com.h"
      40             : #include "ivas_rom_com.h"
      41             : #include "rom_com.h"
      42             : #include "ivas_rom_dec.h"
      43             : #include <math.h>
      44             : #include "wmc_auto.h"
      45             : 
      46             : 
      47             : /*-------------------------------------------------------------------------*
      48             :  * ivas_ism_renderer_open()
      49             :  *
      50             :  * Open struct for object rendering, reserve memory, and init values.
      51             :  *-------------------------------------------------------------------------*/
      52             : 
      53             : #define SIN_NEG_30_DEGREES_Q15 ( (Word16) 0xC000 )
      54             : #define SIN_30_DEGREES_Q15     ( (Word16) 0x4000 )
      55             : 
      56         323 : ivas_error ivas_ism_renderer_open_fx(
      57             :     Decoder_Struct *st_ivas /* i/o: IVAS decoder structure      */
      58             : )
      59             : {
      60             :     Word16 i;
      61             :     UWord16 interpolator_length;
      62             :     UWord16 init_interpolator_length;
      63             :     ivas_error error;
      64             : 
      65         323 :     IF( ( st_ivas->hIsmRendererData = (ISM_RENDERER_HANDLE) malloc( sizeof( ISM_RENDERER_DATA ) ) ) == NULL )
      66             :     {
      67           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ISM renderer\n" ) );
      68             :     }
      69             : 
      70         323 :     test();
      71         323 :     test();
      72         323 :     test();
      73             : #ifdef FIX_1050_EFAP_ALLOC
      74         323 :     test();
      75         323 :     IF( st_ivas->hIntSetup.is_loudspeaker_setup &&
      76             :         st_ivas->hDecoderConfig->output_config != IVAS_AUDIO_CONFIG_STEREO &&
      77             :         st_ivas->hIntSetup.ls_azimuth_fx != NULL && st_ivas->hIntSetup.ls_elevation_fx != NULL &&
      78             :         st_ivas->hEFAPdata == NULL )
      79             : #else
      80             :     IF( st_ivas->hIntSetup.is_loudspeaker_setup && st_ivas->hIntSetup.ls_azimuth_fx != NULL && st_ivas->hIntSetup.ls_elevation_fx != NULL && st_ivas->hEFAPdata == NULL )
      81             : #endif
      82             :     {
      83         108 :         IF( NE_32( ( error = efap_init_data_fx( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth_fx, st_ivas->hIntSetup.ls_elevation_fx, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ), IVAS_ERR_OK ) )
      84             :         {
      85           0 :             return error;
      86             :         }
      87             :     }
      88             : 
      89        1615 :     FOR( i = 0; i < MAX_NUM_OBJECTS; i++ )
      90             :     {
      91        1292 :         set32_fx( st_ivas->hIsmRendererData->prev_gains_fx[i], 0, MAX_OUTPUT_CHANNELS );
      92        1292 :         set32_fx( st_ivas->hIsmRendererData->gains_fx[i], 0, MAX_OUTPUT_CHANNELS );
      93             :     }
      94             : 
      95         323 :     IF( st_ivas->hDecoderConfig->Opt_tsm )
      96             :     {
      97             :         Word32 res_dec, res_frac;
      98          99 :         init_interpolator_length = NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, MAX_JBM_CLDFB_TIMESLOTS * CLDFB_SLOT_NS );
      99          99 :         move16();
     100          99 :         iDiv_and_mod_32( st_ivas->hDecoderConfig->output_Fs, FRAMES_PER_SEC, &res_dec, &res_frac, 0 );
     101          99 :         interpolator_length = (UWord16) ( res_dec );
     102          99 :         move16();
     103             :     }
     104             :     ELSE
     105             :     {
     106             :         Word32 res_dec, res_frac;
     107         224 :         iDiv_and_mod_32( st_ivas->hDecoderConfig->output_Fs, FRAMES_PER_SEC, &res_dec, &res_frac, 0 );
     108         224 :         init_interpolator_length = (UWord16) ( res_dec );
     109         224 :         move16();
     110         224 :         interpolator_length = init_interpolator_length;
     111         224 :         move16();
     112             :     }
     113             : 
     114         323 :     IF( ( st_ivas->hIsmRendererData->interpolator_fx = (Word16 *) malloc( sizeof( Word16 ) * init_interpolator_length ) ) == NULL )
     115             :     {
     116           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ISM renderer interpolator\n" ) );
     117             :     }
     118             : 
     119         323 :     st_ivas->hIsmRendererData->interpolator_len = init_interpolator_length;
     120         323 :     move16();
     121             : 
     122      251200 :     FOR( i = 0; i < sub( interpolator_length, 1 ); i++ )
     123             :     {
     124      250877 :         st_ivas->hIsmRendererData->interpolator_fx[i] = div_s( i, sub( interpolator_length, 1 ) );
     125      250877 :         move16();
     126             :     }
     127         323 :     st_ivas->hIsmRendererData->interpolator_fx[interpolator_length - 1] = 32767; // (1.0f in Q15 )- 1
     128         323 :     move16();
     129             : 
     130         323 :     return IVAS_ERR_OK;
     131             : }
     132             : 
     133             : 
     134             : /*-------------------------------------------------------------------------*
     135             :  * ivas_ism_renderer_close()
     136             :  *
     137             :  * Close struct for object rendering.
     138             :  *-------------------------------------------------------------------------*/
     139        2962 : void ivas_ism_renderer_close(
     140             :     ISM_RENDERER_HANDLE *hIsmRendererData /* i/o: ISM renderer handle */
     141             : )
     142             : {
     143        2962 :     test();
     144        2962 :     IF( hIsmRendererData == NULL || *hIsmRendererData == NULL )
     145             :     {
     146        2127 :         return;
     147             :     }
     148             : 
     149         835 :     IF( ( *hIsmRendererData )->interpolator_fx != NULL )
     150             :     {
     151         835 :         free( ( *hIsmRendererData )->interpolator_fx );
     152         835 :         ( *hIsmRendererData )->interpolator_fx = NULL;
     153             :     }
     154             : 
     155         835 :     free( *hIsmRendererData );
     156         835 :     *hIsmRendererData = NULL;
     157             : 
     158         835 :     return;
     159             : }
     160             : 
     161             : 
     162             : /*-------------------------------------------------------------------------*
     163             :  * ivas_ism_render_sf()
     164             :  *
     165             :  * Object rendering process
     166             :  *-------------------------------------------------------------------------*/
     167       25218 : void ivas_ism_render_sf_fx(
     168             :     Decoder_Struct *st_ivas,           /* i/o: IVAS decoder structure                      */
     169             :     const RENDERER_TYPE renderer_type, /* i  : active renderer type                        */
     170             :     Word32 *output_fx[],               /* i/o: core-coder transport channels/object output  Q11*/
     171             :     const Word16 n_samples_to_render   /* i  : output frame length per channel             */
     172             : )
     173             : {
     174             :     Word16 i, j, k, j2;
     175             :     Word16 *g1_fx, g2_fx;
     176             :     Word32 *tc_fx;
     177             :     Word16 num_objects, nchan_out_woLFE, lfe_index;
     178             :     Word16 azimuth, elevation;
     179             :     Word16 tc_offset;
     180             :     Word16 interp_offset;
     181             :     Word32 gain_fx, prev_gain_fx;
     182             :     Word32 tc_local_fx[MAX_NUM_OBJECTS][L_FRAME48k];
     183             :     Word32 *p_tc_fx[MAX_NUM_OBJECTS];
     184             :     Word16 ism_md_subframe_update_jbm, slots_to_render, first_sf, last_sf, subframe_idx;
     185             :     Word16 n_samples_rendered_loop;
     186             : 
     187             :     /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */
     188       25218 :     slots_to_render = s_min( sub( st_ivas->hTcBuffer->num_slots, st_ivas->hTcBuffer->slots_rendered ), n_samples_to_render / st_ivas->hTcBuffer->n_samples_granularity );
     189       25218 :     first_sf = st_ivas->hTcBuffer->subframes_rendered;
     190       25218 :     move16();
     191       25218 :     last_sf = first_sf;
     192       25218 :     move16();
     193       25218 :     n_samples_rendered_loop = 0;
     194       25218 :     move16();
     195             : 
     196             : #ifdef DEBUGGING
     197             :     assert( slots_to_render == 0 );
     198             :     assert( last_sf <= st_ivas->hTcBuffer->nb_subframes );
     199             : #endif
     200             : 
     201      123427 :     WHILE( slots_to_render > 0 )
     202             :     {
     203       98209 :         slots_to_render = sub( slots_to_render, st_ivas->hTcBuffer->subframe_nbslots[last_sf] );
     204       98209 :         last_sf = add( last_sf, 1 );
     205             :     }
     206             : 
     207       25218 :     num_objects = st_ivas->nchan_ism;
     208             : 
     209       25218 :     nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE;
     210       25218 :     move16();
     211             : 
     212       25218 :     tc_offset = st_ivas->hTcBuffer->n_samples_rendered;
     213       25218 :     move16();
     214       25218 :     interp_offset = st_ivas->hTcBuffer->n_samples_rendered;
     215       25218 :     move16();
     216             : 
     217             :     /* Number of subframes to delay metadata to sync with audio */
     218       25218 :     IF( st_ivas->hDecoderConfig->Opt_delay_comp )
     219             :     {
     220       25218 :         ism_md_subframe_update_jbm = s_max( 0, sub( st_ivas->hTcBuffer->nb_subframes, 3 ) );
     221             :     }
     222             :     ELSE
     223             :     {
     224           0 :         ism_md_subframe_update_jbm = sub( st_ivas->hTcBuffer->nb_subframes, 2 );
     225             :     }
     226             : 
     227       25218 :     IF( st_ivas->hDecoderConfig->Opt_tsm )
     228             :     {
     229        5688 :         FOR( i = 0; i < num_objects; i++ )
     230             :         {
     231        4266 :             p_tc_fx[i] = &st_ivas->hTcBuffer->tc_fx[i][tc_offset]; // Q11
     232             :         }
     233             :     }
     234             :     ELSE
     235             :     {
     236       87380 :         FOR( i = 0; i < num_objects; i++ )
     237             :         {
     238       63584 :             Copy32( &output_fx[i][tc_offset], tc_local_fx[i], n_samples_to_render );
     239       63584 :             p_tc_fx[i] = tc_local_fx[i];
     240             :         }
     241             :     }
     242             : 
     243      260834 :     FOR( i = 0; i < nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; i++ )
     244             :     {
     245      235616 :         set32_fx( output_fx[i], 0, n_samples_to_render );
     246             :     }
     247             : 
     248             : 
     249      123427 :     FOR( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
     250             :     {
     251             :         int16_t n_samples_in_subframe;
     252             : 
     253       98209 :         n_samples_in_subframe = st_ivas->hTcBuffer->n_samples_granularity * st_ivas->hTcBuffer->subframe_nbslots[subframe_idx];
     254       98209 :         test();
     255       98209 :         IF( st_ivas->hCombinedOrientationData && EQ_16( st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx], 1 ) )
     256             :         {
     257       12000 :             ivas_jbm_dec_get_adapted_linear_interpolator_fx( n_samples_in_subframe, n_samples_in_subframe, st_ivas->hIsmRendererData->interpolator_fx );
     258       12000 :             interp_offset = 0;
     259       12000 :             move16();
     260             :         }
     261             : 
     262      361620 :         FOR( i = 0; i < num_objects; i++ )
     263             :         {
     264             :             /* Combined rotation: rotate the object positions depending the head and external orientations */
     265      263411 :             test();
     266      263411 :             IF( st_ivas->hCombinedOrientationData != NULL && EQ_16( st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx], 1 ) )
     267             :             {
     268       12000 :                 if ( GE_16( subframe_idx, ism_md_subframe_update_jbm ) )
     269             :                 {
     270        9000 :                     rotateAziEle_fx( extract_l( L_shr( st_ivas->hIsmMetaData[i]->azimuth_fx, 22 ) ), extract_l( L_shr( st_ivas->hIsmMetaData[i]->elevation_fx, 22 ) ), &azimuth, &elevation, st_ivas->hCombinedOrientationData->Rmat_fx[st_ivas->hCombinedOrientationData->subframe_idx], st_ivas->hIntSetup.is_planar_setup );
     271             :                 }
     272             :                 else
     273             :                 {
     274        3000 :                     rotateAziEle_fx( extract_l( L_shr( st_ivas->hIsmMetaData[i]->last_azimuth_fx, 22 ) ), extract_l( L_shr( st_ivas->hIsmMetaData[i]->last_elevation_fx, 22 ) ), &azimuth, &elevation, st_ivas->hCombinedOrientationData->Rmat_fx[st_ivas->hCombinedOrientationData->subframe_idx], st_ivas->hIntSetup.is_planar_setup );
     275             :                 }
     276             : 
     277       12000 :                 IF( st_ivas->hEFAPdata != NULL )
     278             :                 {
     279       12000 :                     efap_determine_gains_fx( st_ivas->hEFAPdata, st_ivas->hIsmRendererData->gains_fx[i], L_shl( azimuth, 22 ), L_shl( elevation, 22 ), EFAP_MODE_EFAP );
     280             :                 }
     281             :             }
     282             : 
     283      263411 :             lfe_index = 0;
     284      263411 :             move16();
     285     2482532 :             FOR( ( j = 0, j2 = 0 ); j < nchan_out_woLFE; ( j++, j2++ ) )
     286             :             {
     287     2219121 :                 test();
     288     2219121 :                 IF( ( st_ivas->hIntSetup.num_lfe > 0 ) && EQ_16( st_ivas->hIntSetup.index_lfe[lfe_index], j ) )
     289             :                 {
     290      165811 :                     IF( LT_16( lfe_index, sub( st_ivas->hIntSetup.num_lfe, 1 ) ) )
     291             :                     {
     292           0 :                         lfe_index = add( lfe_index, 1 );
     293           0 :                         j2 = add( j2, 1 );
     294             :                     }
     295             :                     ELSE
     296             :                     {
     297      165811 :                         j2 = add( j2, 1 );
     298             :                     }
     299             :                 }
     300             : 
     301     2219121 :                 gain_fx = st_ivas->hIsmRendererData->gains_fx[i][j];
     302     2219121 :                 move32();
     303     2219121 :                 prev_gain_fx = st_ivas->hIsmRendererData->prev_gains_fx[i][j];
     304     2219121 :                 move32();
     305             : 
     306     2219121 :                 test();
     307     2219121 :                 IF( ( L_abs( gain_fx ) > 0 ) || ( L_abs( prev_gain_fx ) > 0 ) )
     308             :                 {
     309     1091186 :                     g1_fx = &st_ivas->hIsmRendererData->interpolator_fx[interp_offset];
     310     1091186 :                     tc_fx = p_tc_fx[i];
     311   237817666 :                     FOR( k = 0; k < n_samples_in_subframe; k++ )
     312             :                     {
     313   236726480 :                         g2_fx = sub( 32767, *g1_fx );                                                                                                                                                                                               // 32767 = (1.0f in Q15) - 1
     314   236726480 :                         output_fx[j2][k + n_samples_rendered_loop] = L_add( output_fx[j2][k + n_samples_rendered_loop], L_shl( Mpy_32_32( L_add( Mpy_32_16_1( gain_fx, *( g1_fx++ ) ), Mpy_32_16_1( prev_gain_fx, g2_fx ) ), *( tc_fx++ ) ), 1 ) ); // Q11( (30+15+1-16) + 11 -31 +1)
     315   236726480 :                         move16();
     316             :                     }
     317             :                 }
     318             : 
     319             :                 /* update here only in case of head rotation */
     320     2219121 :                 test();
     321     2219121 :                 IF( st_ivas->hCombinedOrientationData != NULL && st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx] == 1 )
     322             :                 {
     323      132000 :                     st_ivas->hIsmRendererData->prev_gains_fx[i][j] = gain_fx; // Q30
     324      132000 :                     move32();
     325             :                 }
     326             :             }
     327      263411 :             p_tc_fx[i] += n_samples_in_subframe;
     328             :         }
     329             : 
     330             :         /* update combined orientation access index */
     331       98209 :         ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, n_samples_in_subframe );
     332             : 
     333       98209 :         n_samples_rendered_loop = add( n_samples_rendered_loop, n_samples_in_subframe );
     334             :         /* update rendered subframe and slots info for all cases apart from a following crend call, the update will
     335             :            then happen in the crend call*/
     336       98209 :         if ( NE_16( renderer_type, RENDERER_BINAURAL_MIXER_CONV_ROOM ) )
     337             :         {
     338       58000 :             st_ivas->hTcBuffer->subframes_rendered = add( st_ivas->hTcBuffer->subframes_rendered, 1 );
     339       58000 :             st_ivas->hTcBuffer->slots_rendered = add( st_ivas->hTcBuffer->slots_rendered, st_ivas->hTcBuffer->subframe_nbslots[subframe_idx] );
     340             :         }
     341       98209 :         tc_offset = add( tc_offset, n_samples_in_subframe );
     342       98209 :         interp_offset = add( interp_offset, n_samples_in_subframe );
     343             :     }
     344             : 
     345       25218 :     return;
     346             : }
     347             : 
     348             : 
     349             : /*-------------------------------------------------------------------------*
     350             :  * ivas_ism_get_stereo_gains()
     351             :  *
     352             :  *
     353             :  *-------------------------------------------------------------------------*/
     354             : 
     355      169000 : void ivas_ism_get_stereo_gains_fx(
     356             :     const Word16 aziDeg,  /* i  : object azimuth       Q0*/
     357             :     const Word16 eleDeg,  /* i  : object elevation     Q0*/
     358             :     Word16 *left_gain_fx, /* o  : left channel gain    Q15*/
     359             :     Word16 *right_gain_fx /* o  : right channel gain   Q15*/
     360             : )
     361             : {
     362             :     /* Convert azi and ele to an azi value of the cone of confusion */
     363      169000 :     Word16 azAddEl = add( aziDeg, eleDeg );
     364      169000 :     Word16 azSubEl = sub( aziDeg, eleDeg );
     365             :     Word16 gains[2];
     366             : 
     367      169000 :     const Word16 *ptr_sin_az = ivas_sin_az_fx;
     368             : 
     369      242127 :     WHILE( azAddEl > 180 )
     370             :     {
     371       73127 :         azAddEl = sub( azAddEl, 360 );
     372             :     }
     373      169581 :     WHILE( azAddEl < -180 )
     374             :     {
     375         581 :         azAddEl = add( azAddEl, 360 );
     376             :     }
     377      242673 :     WHILE( azSubEl > 180 )
     378             :     {
     379       73673 :         azSubEl = sub( azSubEl, 360 );
     380             :     }
     381      170075 :     WHILE( azSubEl < -180 )
     382             :     {
     383        1075 :         azSubEl = add( azSubEl, 360 );
     384             :     }
     385      169000 :     Word16 sin_az_cos_el = extract_l( L_shr( L_add( L_deposit_l( ptr_sin_az[azAddEl + 180] ), L_deposit_l( ptr_sin_az[azSubEl + 180] ) ), 1 ) );
     386             : 
     387      169000 :     IF( GE_16( sin_az_cos_el, SIN_30_DEGREES_Q15 ) )
     388             :     {                               /* Left side */
     389       34030 :         gains[0] = (Word16) 0x7fff; // 1.0f in Q15
     390       34030 :         move16();
     391       34030 :         gains[1] = 0;
     392       34030 :         move16();
     393             :     }
     394      134970 :     ELSE IF( LE_16( sin_az_cos_el, SIN_NEG_30_DEGREES_Q15 ) )
     395             :     { /* Right side */
     396       34304 :         gains[0] = 0;
     397       34304 :         move16();
     398       34304 :         gains[1] = (Word16) 0x7fff; // 1.0f in Q15
     399       34304 :         move16();
     400             :     }
     401             :     ELSE /* Tangent panning law */
     402             :     {
     403      100666 :         get_panning_gain_fx( sin_az_cos_el, gains );
     404             :     }
     405             : 
     406      169000 :     *left_gain_fx = gains[0];
     407      169000 :     move16();
     408      169000 :     *right_gain_fx = gains[1];
     409      169000 :     move16();
     410             : 
     411      169000 :     return;
     412             : }
     413             : 
     414             : /*-------------------------------------------------------------------------*
     415             :  * ivas_omasa_separate_object_renderer_open()
     416             :  *
     417             :  * Open structures, reserve memory, and init values.
     418             :  *-------------------------------------------------------------------------*/
     419             : 
     420         494 : ivas_error ivas_omasa_separate_object_renderer_open(
     421             :     Decoder_Struct *st_ivas /* i/o: IVAS decoder structure      */
     422             : )
     423             : {
     424             :     Word16 interpolator_length;
     425             :     Word16 i;
     426             :     Word16 init_interpolator_length;
     427             : 
     428         494 :     IF( ( st_ivas->hIsmRendererData = (ISM_RENDERER_HANDLE) malloc( sizeof( ISM_RENDERER_DATA ) ) ) == NULL )
     429             :     {
     430           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM renderer \n" ) );
     431             :     }
     432             : 
     433        2470 :     FOR( i = 0; i < MAX_NUM_OBJECTS; i++ )
     434             :     {
     435        1976 :         set32_fx( st_ivas->hIsmRendererData->prev_gains_fx[i], 0, MAX_OUTPUT_CHANNELS );
     436             :     }
     437             :     Word32 res_dec1, res_frac1;
     438             :     Word32 res_dec2, res_frac2;
     439         494 :     iDiv_and_mod_32( st_ivas->hDecoderConfig->output_Fs, FRAMES_PER_SEC, &res_dec1, &res_frac1, 0 );
     440         494 :     iDiv_and_mod_32( res_dec1, MAX_PARAM_SPATIAL_SUBFRAMES, &res_dec2, &res_frac2, 0 );
     441         494 :     init_interpolator_length = extract_l( res_dec2 );
     442         494 :     interpolator_length = init_interpolator_length;
     443         494 :     move16();
     444             : 
     445         494 :     st_ivas->hIsmRendererData->interpolator_fx = (Word16 *) malloc( sizeof( Word16 ) * init_interpolator_length );
     446         494 :     st_ivas->hIsmRendererData->interpolator_len = init_interpolator_length;
     447         494 :     move16();
     448      118814 :     FOR( i = 0; i < interpolator_length; i++ )
     449             :     {
     450      118320 :         st_ivas->hIsmRendererData->interpolator_fx[i] = div_s( i, interpolator_length );
     451      118320 :         move16();
     452             :     }
     453         494 :     st_ivas->hIsmRendererData->interpolator_len = interpolator_length;
     454         494 :     move16();
     455             : 
     456             : #ifndef FIX_1161_REDUCE_OMASA_HEAP
     457             :     st_ivas->hMasaIsmData->delayBuffer_size = extract_l( ( st_ivas->hDecoderConfig->output_Fs / 50 ) / MAX_PARAM_SPATIAL_SUBFRAMES );
     458             :     move16();
     459             : 
     460             :     test();
     461             :     IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
     462             :     {
     463             :         st_ivas->hMasaIsmData->delayBuffer_nchan = 1;
     464             :         move16();
     465             :     }
     466             :     ELSE
     467             :     {
     468             :         st_ivas->hMasaIsmData->delayBuffer_nchan = st_ivas->nchan_ism;
     469             :         move16();
     470             :     }
     471             : 
     472             :     IF( ( st_ivas->hMasaIsmData->delayBuffer_fx = (Word32 **) malloc( st_ivas->hMasaIsmData->delayBuffer_nchan * sizeof( Word32 * ) ) ) == NULL )
     473             :     {
     474             :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM delay buffer \n" ) );
     475             :     }
     476             : 
     477             :     FOR( i = 0; i < st_ivas->hMasaIsmData->delayBuffer_nchan; i++ )
     478             :     {
     479             :         IF( ( st_ivas->hMasaIsmData->delayBuffer_fx[i] = (Word32 *) malloc( st_ivas->hMasaIsmData->delayBuffer_size * sizeof( Word32 ) ) ) == NULL )
     480             :         {
     481             :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM delay buffer \n" ) );
     482             :         }
     483             :         set32_fx( st_ivas->hMasaIsmData->delayBuffer_fx[i], 0, st_ivas->hMasaIsmData->delayBuffer_size );
     484             :     }
     485             : #endif
     486             : 
     487         494 :     return IVAS_ERR_OK;
     488             : }
     489             : 
     490             : 
     491             : /*-------------------------------------------------------------------------*
     492             :  * ivas_omasa_separate_object_renderer_close()
     493             :  *
     494             :  * Close structures, free memory.
     495             :  *-------------------------------------------------------------------------*/
     496             : 
     497        1882 : void ivas_omasa_separate_object_renderer_close(
     498             :     Decoder_Struct *st_ivas /* i/o: IVAS decoder structure      */
     499             : )
     500             : {
     501             :     Word16 i;
     502             : 
     503        1882 :     IF( st_ivas->hMasaIsmData != NULL )
     504             :     {
     505        1882 :         IF( st_ivas->hMasaIsmData->delayBuffer_fx != NULL )
     506             :         {
     507        1653 :             FOR( i = 0; i < st_ivas->hMasaIsmData->delayBuffer_nchan; i++ )
     508             :             {
     509        1097 :                 IF( st_ivas->hMasaIsmData->delayBuffer_fx[i] != NULL )
     510             :                 {
     511        1097 :                     free( st_ivas->hMasaIsmData->delayBuffer_fx[i] );
     512        1097 :                     st_ivas->hMasaIsmData->delayBuffer_fx[i] = NULL;
     513             :                 }
     514             :             }
     515             : 
     516         556 :             free( st_ivas->hMasaIsmData->delayBuffer_fx );
     517         556 :             st_ivas->hMasaIsmData->delayBuffer_fx = NULL;
     518             :         }
     519             :     }
     520             : 
     521        1882 :     ivas_ism_renderer_close( &st_ivas->hIsmRendererData );
     522             : 
     523        1882 :     return;
     524             : }
     525             : 
     526             : 
     527             : /*-------------------------------------------------------------------------*
     528             :  * ivas_omasa_separate_object_render_jbm()
     529             :  *
     530             :  * Rendering separated objects and mixing them to the parametrically rendered signals for JBM
     531             :  *-------------------------------------------------------------------------*/
     532             : 
     533        2704 : void ivas_omasa_separate_object_render_jbm_fx(
     534             :     Decoder_Struct *st_ivas,          /* i/o: IVAS decoder structure                      */
     535             :     const UWord16 nSamplesRendered,   /* i  : number of samples rendered                  */
     536             :     Word32 input_fx_in[][L_FRAME48k], /* i  : separated object signal                     Q11*/
     537             :     Word32 *output_fx[],              /* o  : rendered time signal                        Q11*/
     538             :     const Word16 subframes_rendered,  /* i  : number of subframes rendered                */
     539             :     const Word16 slots_rendered       /* i  : number of CLDFB slots rendered              */
     540             : )
     541             : {
     542             :     VBAP_HANDLE hVBAPdata;
     543             :     DIRAC_REND_HANDLE hDirACRend;
     544             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
     545             :     Word16 nchan_out_woLFE, num_lfe;
     546             :     ISM_RENDERER_HANDLE hRendererData;
     547             :     Word16 j, k, j2;
     548             :     Word16 obj;
     549             :     Word32 gains_fx[MAX_OUTPUT_CHANNELS];
     550             :     Word16 g1_fx, g2_fx;
     551             :     Word16 lfe_index;
     552             :     Word16 azimuth, elevation;
     553             :     Word16 num_objects;
     554             :     UWord8 single_separated;
     555             :     Word32 *input_fx[MAX_TRANSPORT_CHANNELS];
     556             :     Word32 *output_fx_local[MAX_OUTPUT_CHANNELS];
     557             :     Word16 offsetSamples;
     558             :     Word16 n_samples_sf, md_idx;
     559             :     Word16 slots_to_render, first_sf, last_sf, subframe_idx;
     560             : 
     561        2704 :     hVBAPdata = st_ivas->hVBAPdata;
     562        2704 :     hDirACRend = st_ivas->hDirACRend;
     563        2704 :     hSpatParamRendCom = st_ivas->hSpatParamRendCom;
     564        2704 :     nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE;
     565        2704 :     move16();
     566        2704 :     num_lfe = st_ivas->hIntSetup.num_lfe;
     567        2704 :     move16();
     568        2704 :     hRendererData = st_ivas->hIsmRendererData;
     569        2704 :     lfe_index = hDirACRend->hOutSetup.index_lfe[0];
     570        2704 :     move16();
     571             : 
     572        2704 :     test();
     573        2704 :     IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
     574             :     {
     575        1633 :         single_separated = 1;
     576        1633 :         move16();
     577        1633 :         num_objects = 1;
     578        1633 :         move16();
     579             :     }
     580             :     ELSE
     581             :     {
     582        1071 :         single_separated = 0;
     583        1071 :         move16();
     584        1071 :         num_objects = st_ivas->nchan_ism;
     585        1071 :         move16();
     586             :     }
     587             : 
     588        2704 :     offsetSamples = i_mult( slots_rendered, hSpatParamRendCom->slot_size );
     589             : 
     590       27902 :     FOR( j = 0; j < nchan_out_woLFE + num_lfe; j++ )
     591             :     {
     592       25198 :         output_fx_local[j] = output_fx[j];
     593             :     }
     594             : 
     595        2704 :     IF( st_ivas->hDecoderConfig->Opt_tsm )
     596             :     {
     597        2515 :         FOR( obj = 0; obj < num_objects; obj++ )
     598             :         {
     599        1611 :             input_fx[obj] = &st_ivas->hTcBuffer->tc_fx[obj + 2][offsetSamples];
     600        1611 :             move32();
     601             :         }
     602             :     }
     603             :     ELSE
     604             :     {
     605        4574 :         FOR( obj = 0; obj < num_objects; obj++ )
     606             :         {
     607        2774 :             input_fx[obj] = input_fx_in[obj];
     608        2774 :             move32();
     609             :         }
     610             :     }
     611             : 
     612        2704 :     slots_to_render = idiv1616( nSamplesRendered, hSpatParamRendCom->slot_size );
     613        2704 :     first_sf = subframes_rendered;
     614        2704 :     move16();
     615        2704 :     last_sf = first_sf;
     616        2704 :     move16();
     617             : 
     618       12181 :     WHILE( slots_to_render > 0 )
     619             :     {
     620        9477 :         slots_to_render = sub( slots_to_render, hSpatParamRendCom->subframe_nbslots[last_sf] );
     621        9477 :         last_sf = add( last_sf, 1 );
     622             :     }
     623             : 
     624        7089 :     FOR( obj = 0; obj < num_objects; obj++ )
     625             :     {
     626             :         /* Delay the signal to match CLDFB delay. Delay the whole buffer with the first rendering call of the stretched buffer. */
     627        4385 :         offsetSamples = 0;
     628        4385 :         move16();
     629             : 
     630       19478 :         FOR( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
     631             :         {
     632       15093 :             n_samples_sf = i_mult( hSpatParamRendCom->subframe_nbslots[subframe_idx], hSpatParamRendCom->slot_size );
     633       15093 :             IF( n_samples_sf != hRendererData->interpolator_len )
     634             :             {
     635       11469 :                 FOR( k = 0; k < n_samples_sf; k++ )
     636             :                 {
     637       11400 :                     hRendererData->interpolator_fx[k] = div_s( k, n_samples_sf );
     638       11400 :                     move16();
     639             :                 }
     640          69 :                 hRendererData->interpolator_len = n_samples_sf;
     641          69 :                 move16();
     642             :             }
     643             : 
     644       15093 :             md_idx = hSpatParamRendCom->render_to_md_map[subframe_idx];
     645       15093 :             move16();
     646             : 
     647       15093 :             IF( single_separated )
     648             :             {
     649        5653 :                 azimuth = st_ivas->hMasaIsmData->azimuth_separated_ism[md_idx];
     650        5653 :                 move16();
     651        5653 :                 elevation = st_ivas->hMasaIsmData->elevation_separated_ism[md_idx];
     652        5653 :                 move16();
     653             :             }
     654             :             ELSE
     655             :             {
     656        9440 :                 azimuth = st_ivas->hMasaIsmData->azimuth_ism[obj][md_idx];
     657        9440 :                 move16();
     658        9440 :                 elevation = st_ivas->hMasaIsmData->elevation_ism[obj][md_idx];
     659        9440 :                 move16();
     660             :             }
     661             : 
     662       15093 :             if ( st_ivas->hOutSetup.is_planar_setup )
     663             :             {
     664             :                 /* If no elevation support in output format, then rendering should be done with zero elevation */
     665         665 :                 elevation = 0;
     666         665 :                 move16();
     667             :             }
     668             : 
     669       15093 :             IF( hVBAPdata != NULL )
     670             :             {
     671        6103 :                 vbap_determine_gains_fx( hVBAPdata, gains_fx, azimuth, elevation, 1 );
     672             :             }
     673             :             ELSE
     674             :             {
     675        8990 :                 ivas_dirac_dec_get_response_fx( azimuth, elevation, gains_fx, hDirACRend->hOutSetup.ambisonics_order, Q29 );
     676             :             }
     677             : 
     678      170486 :             FOR( j = 0; j < nchan_out_woLFE; j++ )
     679             :             {
     680      155393 :                 IF( hDirACRend->hOutSetup.num_lfe > 0 )
     681             :                 {
     682       51729 :                     j2 = add( j, extract_l( GE_16( j, lfe_index ) ) );
     683             :                 }
     684             :                 ELSE
     685             :                 {
     686      103664 :                     j2 = j;
     687      103664 :                     move16();
     688             :                 }
     689             : 
     690      155393 :                 test();
     691      155393 :                 IF( ( L_abs( gains_fx[j] ) > 0 ) || ( L_abs( hRendererData->prev_gains_fx[obj][j] ) > 0 ) )
     692             :                 {
     693    23938638 :                     FOR( k = 0; k < n_samples_sf; k++ )
     694             :                     {
     695    23819280 :                         g1_fx = hRendererData->interpolator_fx[k];
     696    23819280 :                         move16();
     697    23819280 :                         g2_fx = sub( 32767, g1_fx ); // 32767 = 1.0f in Q15
     698             : 
     699    23819280 :                         output_fx_local[j2][k + offsetSamples] = L_add( output_fx_local[j2][k + offsetSamples], L_add( L_shl( Mpy_32_32( Mpy_32_16_1( input_fx[obj][k + offsetSamples], g1_fx ), gains_fx[j] ), 2 ), L_shl( Mpy_32_32( Mpy_32_16_1( input_fx[obj][k + offsetSamples], g2_fx ), hRendererData->prev_gains_fx[obj][j] ), 2 ) ) ); // Q11( (30+15+1-16) + 11 -31 +1)
     700    23819280 :                         move32();
     701             :                     }
     702             :                 }
     703      155393 :                 hRendererData->prev_gains_fx[obj][j] = gains_fx[j];
     704      155393 :                 move32();
     705             :             }
     706             : 
     707       15093 :             offsetSamples = add( offsetSamples, n_samples_sf );
     708             :         }
     709             :     }
     710             : 
     711        2704 :     return;
     712             : }

Generated by: LCOV version 1.14