LCOV - code coverage report
Current view: top level - lib_rend - ivas_sba_rendering_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 125 125 100.0 %
Date: 2025-05-03 01:55:50 Functions: 1 1 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 "prot_fx.h"
      36             : #include "ivas_prot_rend_fx.h"
      37             : #include "ivas_stat_dec.h"
      38             : #include "ivas_cnst.h"
      39             : #include <math.h>
      40             : #include "wmc_auto.h"
      41             : #include "ivas_prot_fx.h"
      42             : 
      43             : /*-------------------------------------------------------------------*
      44             :  * ivas_sba_prototype_renderer()
      45             :  *
      46             :  * Render prototype audio signals using SBA mixing matrices
      47             :  *-------------------------------------------------------------------*/
      48      149650 : void ivas_sba_prototype_renderer_fx(
      49             :     Decoder_Struct *st_ivas,                                           /* i/o: IVAS decoder struct               */
      50             :     Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i  : Input audio in CLDFB domain, real Q(q_cldfb[][])*/
      51             :     Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i  : Input audio in CLDFB domain, imag Q(q_cldfb[][])*/
      52             :     Word16 q_cldfb[6][CLDFB_SLOTS_PER_SUBFRAME],
      53             :     const Word16 subframe /* i  : Subframe to render                */
      54             : )
      55             : {
      56             :     Word32 mixer_mat_fx[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS];
      57             :     SPAR_DEC_HANDLE hSpar;
      58             :     DECODER_CONFIG_HANDLE hDecoderConfig;
      59             :     Word16 num_spar_bands, spar_band;
      60             :     Word16 b, ts;
      61             :     Word16 num_cldfb_bands, numch_in, numch_out;
      62             :     Word16 cldfb_band;
      63             :     Word16 out_ch, in_ch;
      64             :     Word16 firstInCh, inChEnd, firstOutCh, outChEnd;
      65             :     Word16 slot_idx_start, md_idx;
      66             :     Word16 num_md_sub_frames;
      67             : 
      68      149650 :     num_md_sub_frames = ivas_get_spar_dec_md_num_subframes( st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->last_active_ivas_total_brate );
      69             : 
      70      149650 :     push_wmops( "ivas_sba_prototype_renderer" );
      71             : 
      72      149650 :     hSpar = st_ivas->hSpar;
      73      149650 :     hDecoderConfig = st_ivas->hDecoderConfig;
      74      149650 :     num_spar_bands = hSpar->hFbMixer->pFb->filterbank_num_bands;
      75      149650 :     move16();
      76             : 
      77      149650 :     num_cldfb_bands = hSpar->hFbMixer->pFb->fb_bin_to_band.num_cldfb_bands;
      78      149650 :     move16();
      79      149650 :     numch_in = hSpar->hFbMixer->fb_cfg->num_in_chans;
      80      149650 :     move16();
      81      149650 :     numch_out = hSpar->hFbMixer->fb_cfg->num_out_chans;
      82      149650 :     move16();
      83      149650 :     slot_idx_start = hSpar->slots_rendered;
      84      149650 :     move16();
      85             : 
      86             :     /* Scaling up the real and imaginary buffers */
      87      149650 :     Word16 norm_q = 31; // to handle overflow
      88      149650 :     move16();
      89             : 
      90     1047550 :     FOR( Word16 i = 0; i < 6; i++ )
      91             :     {
      92     4489500 :         FOR( Word16 j = 0; j < CLDFB_SLOTS_PER_SUBFRAME; j++ )
      93             :         {
      94     3591600 :             norm_q = s_min( q_cldfb[i][j], norm_q );
      95             :         }
      96             :     }
      97      149650 :     norm_q = sub( sub( 31, norm_q ), 2 ); // to handle overflow
      98             :     Word16 q_inp[6][CLDFB_SLOTS_PER_SUBFRAME];
      99     1047550 :     FOR( Word16 i = 0; i < 6; i++ )
     100             :     {
     101     4489500 :         FOR( Word16 j = 0; j < CLDFB_SLOTS_PER_SUBFRAME; j++ )
     102             :         {
     103     3591600 :             q_inp[i][j] = s_min( L_norm_arr( inRe_fx[i][j], CLDFB_NO_CHANNELS_MAX ), L_norm_arr( inIm_fx[i][j], CLDFB_NO_CHANNELS_MAX ) );
     104     3591600 :             move16();
     105     3591600 :             norm_q = s_min( q_inp[i][j], norm_q );
     106             :         }
     107             :     }
     108     1047550 :     FOR( Word16 i = 0; i < 6; i++ )
     109             :     {
     110     4489500 :         FOR( Word16 j = 0; j < CLDFB_SLOTS_PER_SUBFRAME; j++ )
     111             :         {
     112     3591600 :             scale_sig32( inRe_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( norm_q, 2 ) ); // q_cldfb -> q_cldfb + 2 -norm_q
     113     3591600 :             scale_sig32( inIm_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( norm_q, 2 ) ); // q_cldfb -> q_cldfb + 2 -norm_q
     114     3591600 :             q_cldfb[i][j] = sub( add( q_cldfb[i][j], norm_q ), 2 );
     115     3591600 :             move16();
     116             :         }
     117             :     }
     118             : 
     119      149650 :     IF( EQ_16( st_ivas->nchan_transport, 1 ) )
     120             :     {
     121       64406 :         firstInCh = 0;
     122       64406 :         inChEnd = 1;
     123       64406 :         firstOutCh = 0;
     124       64406 :         outChEnd = 1;
     125       64406 :         move16();
     126       64406 :         move16();
     127       64406 :         move16();
     128       64406 :         move16();
     129             :     }
     130             :     ELSE /* 2 TC */
     131             :     {
     132       85244 :         firstInCh = 0;
     133       85244 :         inChEnd = 2;
     134       85244 :         firstOutCh = 1;
     135       85244 :         outChEnd = 2;
     136       85244 :         move16();
     137       85244 :         move16();
     138       85244 :         move16();
     139       85244 :         move16();
     140             :     }
     141             : 
     142             :     /* Apply mixing matrix */
     143      742498 :     FOR( ts = 0; ts < hSpar->subframe_nbslots[hSpar->subframes_rendered]; ts++ )
     144             :     {
     145             :         /* determine SPAR parameters FOR this time slot */
     146      592848 :         md_idx = hSpar->render_to_md_map[ts + slot_idx_start];
     147      592848 :         move16();
     148             : 
     149      592848 :         ivas_spar_get_parameters_fx( hSpar, hDecoderConfig, md_idx, numch_out, numch_in, num_spar_bands, mixer_mat_fx );
     150             : 
     151    26394128 :         FOR( cldfb_band = 0; cldfb_band < num_cldfb_bands; cldfb_band++ )
     152             :         {
     153             :             Word32 out_re_fx[IVAS_SPAR_MAX_CH];
     154             :             Word32 out_im_fx[IVAS_SPAR_MAX_CH];
     155             :             Word32 cldfb_par_fx;
     156    25801280 :             ivas_fb_bin_to_band_data_t *bin2band = &hSpar->hFbMixer->pFb->fb_bin_to_band;
     157             : 
     158    51602560 :             FOR( out_ch = firstOutCh; out_ch < outChEnd; out_ch++ )
     159             :             {
     160    25801280 :                 out_re_fx[out_ch] = 0;
     161    25801280 :                 move32();
     162    25801280 :                 out_im_fx[out_ch] = 0;
     163    25801280 :                 move32();
     164             : 
     165    66267440 :                 FOR( in_ch = firstInCh; in_ch < inChEnd; in_ch++ )
     166             :                 {
     167    40466160 :                     IF( LT_16( cldfb_band, CLDFB_PAR_WEIGHT_START_BAND ) ) /* tuning parameter, depends on how much SPAR Filters overlap FOR the CLDFB bands */
     168             :                     {
     169     6529852 :                         spar_band = bin2band->p_cldfb_map_to_spar_band[cldfb_band];
     170     6529852 :                         move16();
     171     6529852 :                         cldfb_par_fx = mixer_mat_fx[out_ch][in_ch][spar_band]; // hMdDec->Q_mixer_matrix
     172     6529852 :                         move32();
     173             :                     }
     174             :                     ELSE
     175             :                     {
     176    33936308 :                         cldfb_par_fx = 0;
     177    33936308 :                         move32();
     178   196184524 :                         FOR( spar_band = bin2band->p_spar_start_bands[cldfb_band]; spar_band < num_spar_bands; spar_band++ )
     179             :                         {
     180             :                             /* accumulate contributions from all SPAR bands */
     181   162248216 :                             cldfb_par_fx = L_add( cldfb_par_fx, Mpy_32_32( mixer_mat_fx[out_ch][in_ch][spar_band], bin2band->pp_cldfb_weights_per_spar_band_fx[cldfb_band][spar_band] ) ); // hMdDec->Q_mixer_matrix
     182             :                         }
     183             :                     }
     184             : 
     185    40466160 :                     out_re_fx[out_ch] = L_add( out_re_fx[out_ch], Mpy_32_32( inRe_fx[in_ch][ts][cldfb_band], cldfb_par_fx ) ); // hMdDec->Q_mixer_matrix+q_cldfb[i][j] -31
     186    40466160 :                     out_im_fx[out_ch] = L_add( out_im_fx[out_ch], Mpy_32_32( inIm_fx[in_ch][ts][cldfb_band], cldfb_par_fx ) ); // hMdDec->Q_mixer_matrix+q_cldfb[i][j] -31
     187    40466160 :                     move32();
     188    40466160 :                     move32();
     189             :                 }
     190             :             }
     191             : 
     192             :             /*update CLDFB data with the parameter-modified data*/
     193    51602560 :             FOR( out_ch = firstOutCh; out_ch < outChEnd; out_ch++ )
     194             :             {
     195    25801280 :                 inRe_fx[out_ch][ts][cldfb_band] = L_shl( out_re_fx[out_ch], 1 ); //  hMdDec->Q_mixer_matrix+q_cldfb[i][j] -31 +1; + q1 //to keep constat q to entire buffer
     196    25801280 :                 inIm_fx[out_ch][ts][cldfb_band] = L_shl( out_im_fx[out_ch], 1 ); //  hMdDec->Q_mixer_matrix+q_cldfb[i][j] -31 +1; + q1 //to keep constat q to entire buffer
     197    25801280 :                 move32();
     198    25801280 :                 move32();
     199             :             }
     200             :         }
     201             : 
     202             :         /* Update mixing matrices */
     203      592848 :         test();
     204      592848 :         IF( EQ_16( add( add( slot_idx_start, ts ), 1 ), hSpar->num_slots ) || NE_16( shr( md_idx, 2 ), shr( hSpar->render_to_md_map[add( add( ts, slot_idx_start ), 1 )], 2 ) ) ) // shr is used in place of division by JBM_CLDFB_SLOTS_IN_SUBFRAME,  ( ( md_idx / JBM_CLDFB_SLOTS_IN_SUBFRAME ) != ( hSpar->render_to_md_map[ts + slot_idx_start + 1] / JBM_CLDFB_SLOTS_IN_SUBFRAME ) )
     205             :         {
     206             :             /* we have crossed an unadapted parameter sf border, update previous mixing matrices */
     207      148214 :             Word16 md_sf = shr( md_idx, 2 ); // md_idx / JBM_CLDFB_SLOTS_IN_SUBFRAME
     208      148214 :             if ( NE_16( num_md_sub_frames, MAX_PARAM_SPATIAL_SUBFRAMES ) )
     209             :             {
     210       15731 :                 md_sf = 0;
     211       15731 :                 move16();
     212             :             }
     213      148214 :             hSpar->i_subframe = add( hSpar->i_subframe, 1 );
     214      148214 :             move16();
     215      148214 :             hSpar->i_subframe = s_min( hSpar->i_subframe, MAX_PARAM_SPATIAL_SUBFRAMES );
     216      148214 :             move16();
     217      148214 :             Copy32( hSpar->hMdDec->mixer_mat_prev_fx[1][0][0], hSpar->hMdDec->mixer_mat_prev_fx[0][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); // Q_mixer_mat
     218      148214 :             Copy32( hSpar->hMdDec->mixer_mat_prev_fx[2][0][0], hSpar->hMdDec->mixer_mat_prev_fx[1][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); // Q_mixer_mat
     219      148214 :             Copy32( hSpar->hMdDec->mixer_mat_prev_fx[3][0][0], hSpar->hMdDec->mixer_mat_prev_fx[2][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); // Q_mixer_mat
     220      148214 :             Copy32( hSpar->hMdDec->mixer_mat_prev_fx[4][0][0], hSpar->hMdDec->mixer_mat_prev_fx[3][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); // Q_mixer_mat
     221             : 
     222      741070 :             FOR( out_ch = 0; out_ch < numch_out; out_ch++ )
     223             :             {
     224     2964280 :                 FOR( in_ch = 0; in_ch < numch_in; in_ch++ )
     225             :                 {
     226    30572512 :                     FOR( b = 0; b < num_spar_bands; b++ )
     227             :                     {
     228    28201088 :                         hSpar->hMdDec->mixer_mat_prev_fx[4][out_ch][in_ch][b] = hSpar->hMdDec->mixer_mat_fx[out_ch][in_ch][b + ( md_sf * IVAS_MAX_NUM_BANDS )];
     229    28201088 :                         move32();
     230             :                     }
     231             :                 }
     232             :             }
     233             :         }
     234             :     }
     235             : 
     236             : 
     237             :     /* Create prototypes */
     238      149650 :     test();
     239      149650 :     IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) )
     240             :     {
     241      742498 :         FOR( ts = 0; ts < hSpar->subframe_nbslots[subframe]; ts++ )
     242             :         {
     243      592848 :             IF( EQ_16( st_ivas->nchan_transport, 1 ) ) /* Dual mono */
     244             :             {
     245      252860 :                 Copy32( inRe_fx[0][ts], inRe_fx[1][ts], CLDFB_NO_CHANNELS_MAX );
     246      252860 :                 Copy32( inIm_fx[0][ts], inIm_fx[1][ts], CLDFB_NO_CHANNELS_MAX );
     247             :             }
     248      339988 :             ELSE IF( EQ_16( st_ivas->nchan_transport, 2 ) ) /* Opposing cardioids */
     249             :             {
     250             :                 Word32 temp_signal_fx[CLDFB_NO_CHANNELS_MAX];
     251    20739268 :                 FOR( Word16 idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ )
     252             :                 {
     253    20399280 :                     temp_signal_fx[idx] = L_add( L_shr( inRe_fx[0][ts][idx], 1 ), L_shr( inRe_fx[1][ts][idx], 1 ) ); // q_cldfb[][]-1
     254    20399280 :                     move32();
     255    20399280 :                     inRe_fx[1][ts][idx] = L_sub( L_shr( inRe_fx[0][ts][idx], 1 ), L_shr( inRe_fx[1][ts][idx], 1 ) ); // q_cldfb[][]-1
     256    20399280 :                     move32();
     257    20399280 :                     inRe_fx[0][ts][idx] = temp_signal_fx[idx];
     258    20399280 :                     move32();
     259             :                 }
     260             : 
     261    20739268 :                 FOR( Word16 idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ )
     262             :                 {
     263    20399280 :                     temp_signal_fx[idx] = L_add( L_shr( inIm_fx[0][ts][idx], 1 ), L_shr( inIm_fx[1][ts][idx], 1 ) ); // q_cldfb[][]-1
     264    20399280 :                     move32();
     265    20399280 :                     inIm_fx[1][ts][idx] = L_sub( L_shr( inIm_fx[0][ts][idx], 1 ), L_shr( inIm_fx[1][ts][idx], 1 ) ); // q_cldfb[][]-1
     266    20399280 :                     move32();
     267    20399280 :                     inIm_fx[0][ts][idx] = temp_signal_fx[idx];
     268    20399280 :                     move32();
     269             :                 }
     270             :             }
     271             :         }
     272             :     }
     273             : 
     274      149650 :     hSpar->subframes_rendered = add( hSpar->subframes_rendered, 1 );
     275      149650 :     move16();
     276      149650 :     hSpar->slots_rendered = add( hSpar->slots_rendered, hSpar->subframe_nbslots[subframe] );
     277      149650 :     move16();
     278      149650 :     pop_wmops();
     279             : 
     280      149650 :     return;
     281             : }

Generated by: LCOV version 1.14