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

Generated by: LCOV version 1.14