LCOV - code coverage report
Current view: top level - lib_dec - ivas_objectRenderer_internal_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 107 126 84.9 %
Date: 2025-05-03 01:55:50 Functions: 2 3 66.7 %

          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 "prot_fx.h"
      36             : #include "ivas_prot_rend_fx.h"
      37             : #include <math.h>
      38             : #include "ivas_rom_com.h"
      39             : #include "wmc_auto.h"
      40             : #include "ivas_prot_fx.h"
      41             : #include "debug.h"
      42             : 
      43             : 
      44             : /*---------------------------------------------------------------------*
      45             :  * ivas_td_binaural_open()
      46             :  *
      47             :  * Open and initialize TD Object binaural renderer
      48             :  *---------------------------------------------------------------------*/
      49         108 : ivas_error ivas_td_binaural_open_fx(
      50             :     Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure  */
      51             :     Word16 *SrcInd,          /*Temporarily used to store the updated value of SrcInd*/
      52             :     Word16 *num_src )
      53             : {
      54         108 :     *num_src = st_ivas->nchan_transport;
      55         108 :     move16();
      56         108 :     test();
      57         108 :     if ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) )
      58             :     {
      59          84 :         *num_src = st_ivas->nchan_ism;
      60          84 :         move16();
      61             :     }
      62         108 :     return ivas_td_binaural_open_unwrap_fx( &st_ivas->hHrtfTD, st_ivas->hDecoderConfig->output_Fs, *num_src, st_ivas->ivas_format, st_ivas->transport_config, st_ivas->hRenderConfig->directivity_fx, st_ivas->hTransSetup, &st_ivas->hBinRendererTd, &st_ivas->binaural_latency_ns, SrcInd );
      63             : }
      64             : 
      65             : 
      66             : /*---------------------------------------------------------------------*
      67             :  * ivas_td_binaural_renderer()
      68             :  *
      69             :  * Receives the current frames for the object streams, updates metadata
      70             :  * and renders the current frame.
      71             :  *---------------------------------------------------------------------*/
      72             : 
      73           0 : ivas_error ivas_td_binaural_renderer_fx(
      74             :     Decoder_Struct *st_ivas,  /* i/o: IVAS decoder structure            */
      75             :     Word32 *output[],         /* i/o: SCE channels / Binaural synthesis Q11*/
      76             :     const Word16 output_frame /* i  : output frame length               */
      77             : )
      78             : {
      79             :     Word16 ism_md_subframe_update;
      80             :     Word16 nchan_transport;
      81           0 :     test();
      82           0 :     IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) )
      83             :     {
      84           0 :         nchan_transport = st_ivas->nchan_ism;
      85             :     }
      86             :     ELSE
      87             :     {
      88           0 :         nchan_transport = st_ivas->nchan_transport;
      89             :     }
      90           0 :     move16();
      91             : 
      92           0 :     IF( st_ivas->hDecoderConfig->Opt_delay_comp )
      93             :     {
      94           0 :         ism_md_subframe_update = 1;
      95             :     }
      96             :     ELSE
      97             :     {
      98           0 :         ism_md_subframe_update = 2;
      99             :     }
     100           0 :     move16();
     101             : 
     102           0 :     if ( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
     103             :     {
     104           0 :         ism_md_subframe_update = 2;
     105           0 :         move16();
     106             :     }
     107           0 :     return ivas_td_binaural_renderer_unwrap_fx( st_ivas->hReverb, st_ivas->transport_config, st_ivas->hBinRendererTd, nchan_transport, LFE_CHANNEL, st_ivas->ivas_format, st_ivas->hIsmMetaData, st_ivas->hCombinedOrientationData, ism_md_subframe_update, output, output_frame, MAX_PARAM_SPATIAL_SUBFRAMES );
     108             : }
     109             : 
     110             : 
     111             : /*---------------------------------------------------------------------*
     112             :  * ivas_td_binaural_renderer_sf()
     113             :  *
     114             :  * Receives the current frames for the object streams, updates metadata
     115             :  * and renders the current frame.
     116             :  *---------------------------------------------------------------------*/
     117             : 
     118       36345 : ivas_error ivas_td_binaural_renderer_sf_fx(
     119             :     Decoder_Struct *st_ivas,           /* i/o: IVAS decoder structure              */
     120             :     Word32 *output_fx[],               /* i/o: SCE channels / Binaural synthesis   Q11*/
     121             :     const Word16 n_samples_granularity /* i  : granularity of the renderer/buffer  */
     122             : )
     123             : {
     124             :     Word16 first_sf, last_sf, subframe_idx;
     125             :     Word32 *output_fx_local[BINAURAL_CHANNELS];
     126             :     Word32 reverb_signal_fx[BINAURAL_CHANNELS][L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES];
     127             :     Word32 *p_reverb_signal_fx[BINAURAL_CHANNELS];
     128             :     Word32 *tc_local_fx[MAX_TRANSPORT_CHANNELS];
     129             :     Word16 ch, slot_size, slots_to_render, output_frame, tmp;
     130             :     ivas_error error;
     131             : 
     132             :     Word16 ism_md_subframe_update_jbm;
     133             :     Word16 c_indx, nS, i;
     134             :     Word16 nchan_ism_internal, nchan_ism, ch_offset;
     135             : 
     136             :     IVAS_QUATERNION *tmp_Quaternion_fx;
     137             :     IVAS_VECTOR3 *tmp_vector_fx;
     138             :     Word16 enableCombinedOrientation;
     139             : 
     140             :     /* Set the number of ISMs */
     141       36345 :     IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
     142             :     {
     143         126 :         nchan_ism_internal = st_ivas->nchan_ism;
     144         126 :         move16();
     145         126 :         nchan_ism = st_ivas->nchan_ism;
     146         126 :         move16();
     147         126 :         ch_offset = 2;
     148         126 :         move16();
     149             :     }
     150       36219 :     ELSE IF( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) )
     151             :     {
     152        4689 :         nchan_ism_internal = st_ivas->nchan_ism;
     153        4689 :         move16();
     154        4689 :         nchan_ism = st_ivas->nchan_ism;
     155        4689 :         move16();
     156        4689 :         ch_offset = 0;
     157        4689 :         move16();
     158             :     }
     159             :     ELSE
     160             :     {
     161       31530 :         nchan_ism_internal = st_ivas->hTcBuffer->nchan_transport_internal;
     162       31530 :         move16();
     163       31530 :         nchan_ism = st_ivas->nchan_transport;
     164       31530 :         move16();
     165       31530 :         ch_offset = 0;
     166       31530 :         move16();
     167             :     }
     168             : 
     169             :     /* Number of subframes to delay metadata to sync with audio */
     170       36345 :     IF( st_ivas->hDecoderConfig->Opt_delay_comp )
     171             :     {
     172       36345 :         ism_md_subframe_update_jbm = s_max( 0, sub( st_ivas->hTcBuffer->nb_subframes, 3 ) );
     173             :     }
     174             :     ELSE
     175             :     {
     176           0 :         ism_md_subframe_update_jbm = sub( st_ivas->hTcBuffer->nb_subframes, 2 );
     177             :     }
     178             : 
     179       36345 :     IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
     180             :     {
     181         126 :         ism_md_subframe_update_jbm = s_max( 0, sub( st_ivas->hTcBuffer->nb_subframes, 2 ) );
     182             :     }
     183             : 
     184      109035 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
     185             :     {
     186       72690 :         p_reverb_signal_fx[ch] = reverb_signal_fx[ch];
     187             :     }
     188      151607 :     FOR( ch = 0; ch < nchan_ism_internal; ch++ )
     189             :     {
     190      115262 :         tc_local_fx[ch] = st_ivas->hTcBuffer->tc_fx[ch + ch_offset] + st_ivas->hTcBuffer->n_samples_rendered;
     191             :     }
     192             : 
     193      109035 :     FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ )
     194             :     {
     195       72690 :         output_fx_local[ch] = output_fx[ch]; // Q11
     196             :     }
     197             : 
     198       36345 :     slot_size = st_ivas->hTcBuffer->n_samples_granularity;
     199       36345 :     move16();
     200             : 
     201             :     /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */
     202       36345 :     tmp = 0;
     203       36345 :     move16();
     204       36345 :     IF( n_samples_granularity != 0 )
     205             :     {
     206       36345 :         tmp = idiv1616( n_samples_granularity, slot_size );
     207             :     }
     208       36345 :     slots_to_render = s_min( sub( st_ivas->hTcBuffer->num_slots, st_ivas->hTcBuffer->slots_rendered ), tmp );
     209       36345 :     first_sf = st_ivas->hTcBuffer->subframes_rendered;
     210       36345 :     move16();
     211       36345 :     last_sf = first_sf;
     212       36345 :     move16();
     213       36345 :     st_ivas->hTcBuffer->slots_rendered = add( st_ivas->hTcBuffer->slots_rendered, slots_to_render );
     214       36345 :     move16();
     215             : 
     216      181630 :     WHILE( slots_to_render > 0 )
     217             :     {
     218      145285 :         slots_to_render = sub( slots_to_render, st_ivas->hTcBuffer->subframe_nbslots[last_sf] );
     219      145285 :         last_sf = add( last_sf, 1 );
     220             :     }
     221             : 
     222      181630 :     FOR( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
     223             :     {
     224      145285 :         output_frame = i_mult( st_ivas->hTcBuffer->subframe_nbslots[subframe_idx], st_ivas->hTcBuffer->n_samples_granularity );
     225             : 
     226             :         /* Update object position(s) */
     227      145285 :         c_indx = 0;
     228      145285 :         move16();
     229             : 
     230      606007 :         FOR( nS = 0; nS < nchan_ism; nS++ )
     231             :         {
     232      460722 :             test();
     233      460722 :             IF( !( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_16( nS, LFE_CHANNEL ) ) ) /* Skip LFE for MC */
     234             :             {
     235      448482 :                 st_ivas->hBinRendererTd->Sources[c_indx]->InputFrame_p_fx = tc_local_fx[nS]; /* Q11 */
     236      448482 :                 st_ivas->hBinRendererTd->Sources[c_indx]->SrcRend_p->InputAvailable = TRUE;
     237      448482 :                 move16();
     238      448482 :                 c_indx = add( c_indx, 1 );
     239             :             }
     240             :         }
     241             : 
     242      145285 :         IF( EQ_16( subframe_idx, ism_md_subframe_update_jbm ) )
     243             :         {
     244       36331 :             IF( ( error = TDREND_Update_object_positions_fx( st_ivas->hBinRendererTd, nchan_ism, st_ivas->ivas_format, st_ivas->hIsmMetaData ) ) != IVAS_ERR_OK )
     245             :             {
     246           0 :                 return error;
     247             :             }
     248             :         }
     249             : 
     250             :         /* Update the listener's location/orientation */
     251      145285 :         IF( st_ivas->hCombinedOrientationData != NULL )
     252             :         {
     253       84840 :             tmp_Quaternion_fx = &st_ivas->hCombinedOrientationData->Quaternions[st_ivas->hCombinedOrientationData->subframe_idx];
     254       84840 :             tmp_vector_fx = &st_ivas->hCombinedOrientationData->listenerPos[st_ivas->hCombinedOrientationData->subframe_idx];
     255       84840 :             enableCombinedOrientation = st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx];
     256       84840 :             move16();
     257             : 
     258             :             /* Shifting x_fx, y_fx, z_fx to the same Q-factor as Listener_p->Pos_q (usually Q25) */
     259       84840 :             Word16 pos_q = st_ivas->hBinRendererTd->Listener_p->Pos_q;
     260       84840 :             move16();
     261       84840 :             tmp_vector_fx->x_fx = L_shr( tmp_vector_fx->x_fx, sub( tmp_vector_fx->q_fact, pos_q ) );
     262       84840 :             tmp_vector_fx->y_fx = L_shr( tmp_vector_fx->y_fx, sub( tmp_vector_fx->q_fact, pos_q ) );
     263       84840 :             tmp_vector_fx->z_fx = L_shr( tmp_vector_fx->z_fx, sub( tmp_vector_fx->q_fact, pos_q ) );
     264       84840 :             tmp_vector_fx->q_fact = pos_q;
     265       84840 :             move16();
     266             :         }
     267             :         ELSE
     268             :         {
     269       60445 :             tmp_Quaternion_fx = NULL;
     270       60445 :             tmp_vector_fx = NULL;
     271       60445 :             enableCombinedOrientation = 0;
     272       60445 :             move16();
     273             :         }
     274             : 
     275      145285 :         IF( NE_32( ( error = TDREND_Update_listener_orientation_fx( st_ivas->hBinRendererTd,
     276             :                                                                     enableCombinedOrientation,
     277             :                                                                     tmp_Quaternion_fx,
     278             :                                                                     tmp_vector_fx ) ),
     279             :                    IVAS_ERR_OK ) )
     280             :         {
     281           0 :             return error;
     282             :         }
     283             : 
     284      145285 :         test();
     285      145285 :         IF( st_ivas->hRenderConfig != NULL && EQ_32( st_ivas->hIntSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
     286             :         {
     287       20000 :             FOR( i = 0; i < nchan_ism_internal; ++i )
     288             :             {
     289       16000 :                 scale_sig32( tc_local_fx[i], st_ivas->hReverb->full_block_size, -4 ); // Q11 - 4 = Q7
     290             :             }
     291             : 
     292        4000 :             IF( NE_32( ( error = ivas_reverb_process_fx( st_ivas->hReverb, st_ivas->transport_config, 0, tc_local_fx, p_reverb_signal_fx, 0 ) ), IVAS_ERR_OK ) ) // Q(p_reverb_signal_fx) = 11
     293             :             {
     294           0 :                 return error;
     295             :             }
     296             : 
     297       20000 :             FOR( i = 0; i < nchan_ism_internal; ++i )
     298             :             {
     299       16000 :                 scale_sig32( tc_local_fx[i], st_ivas->hReverb->full_block_size, 4 ); // Q7 + 4 = Q11
     300             :             }
     301             : 
     302       12000 :             FOR( i = 0; i < BINAURAL_CHANNELS; ++i )
     303             :             {
     304        8000 :                 scale_sig32( p_reverb_signal_fx[i], st_ivas->hReverb->full_block_size, 2 + 4 ); // Q5 + 6 = Q11
     305             :             }
     306             :         }
     307             : 
     308             :         /* Render subframe */
     309             :         /* ism_md_subframe_update_jbm != subframe_idx: trigger update only for ism_md_subframe_update_jbm == subframe_idx,
     310             :            where then the two TDREND_GetMix()-arguments subframe_idx and ism_md_subframe_update are equal, and we want to enforce the update inside TDREND_GetMix to use subframe_idx == 0 */
     311      145285 :         IF( NE_32( ( error = TDREND_GetMix_fx( st_ivas->hBinRendererTd, output_fx_local, output_frame, 0, ism_md_subframe_update_jbm != subframe_idx ) ), IVAS_ERR_OK ) )
     312             :         {
     313           0 :             return error;
     314             :         }
     315             : 
     316      145285 :         test();
     317      145285 :         IF( st_ivas->hRenderConfig != NULL && EQ_32( st_ivas->hIntSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
     318             :         {
     319             :             /* add reverb to rendered signals */
     320        4000 :             v_add_32( reverb_signal_fx[0], output_fx_local[0], output_fx_local[0], output_frame ); // Q11
     321        4000 :             v_add_32( reverb_signal_fx[1], output_fx_local[1], output_fx_local[1], output_frame );
     322             :         }
     323             : 
     324      606007 :         FOR( ch = 0; ch < nchan_ism_internal; ch++ )
     325             :         {
     326      460722 :             tc_local_fx[ch] += output_frame;
     327             :         }
     328             : 
     329      435855 :         FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ )
     330             :         {
     331      290570 :             output_fx_local[ch] += output_frame;
     332             :         }
     333             : 
     334             :         /* update combined orientation access index */
     335      145285 :         ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, output_frame );
     336             :     }
     337             : 
     338       36345 :     st_ivas->hTcBuffer->subframes_rendered = last_sf;
     339       36345 :     move16();
     340             : 
     341       36345 :     return IVAS_ERR_OK;
     342             : }

Generated by: LCOV version 1.14