LCOV - code coverage report
Current view: top level - lib_rend - ivas_reflections.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 134 211 63.5 %
Date: 2025-05-23 08:37:30 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : #include "options.h"
      34             : #include <stdint.h>
      35             : #include <math.h>
      36             : #include "prot.h"
      37             : #include "rom_dec.h"
      38             : #include "lib_rend.h"
      39             : #include "ivas_prot_rend.h"
      40             : #include "ivas_stat_rend.h"
      41             : #include "ivas_cnst.h"
      42             : #include "ivas_prot.h"
      43             : #include "ivas_rom_com.h"
      44             : #include "wmc_auto.h"
      45             : #ifdef DEBUGGING
      46             : #include "debug.h"
      47             : #endif
      48             : 
      49             : 
      50             : /*-----------------------------------------------------------------------------------------*
      51             :  * Local constants/tabels
      52             :  *-----------------------------------------------------------------------------------------*/
      53             : 
      54             : #define ER_NUM_REF 6
      55             : 
      56             : static uint16_t LC_mixing_5_1[5] = { 0, 1, 2, 0, 1 };
      57             : 
      58             : static uint16_t LC_mixing_7_1[7] = { 0, 1, 2, 3, 4, 3, 4 };
      59             : 
      60             : static uint16_t LC_mixing_5_1_2[7] = { 0, 1, 2, 3, 4, 0, 1 };
      61             : 
      62             : static uint16_t LC_mixing_5_1_4[9] = { 0, 1, 2, 3, 4, 0, 1, 3, 4 };
      63             : 
      64             : static uint16_t LC_mixing_7_1_4[11] = { 0, 1, 2, 3, 4, 3, 4, 0, 1, 3, 4 };
      65             : 
      66             : /*-----------------------------------------------------------------------------------------*
      67             :  * Function ivas_er_init()
      68             :  *
      69             :  * Initializes the reflections data structure according to the requested input config.
      70             :  *-----------------------------------------------------------------------------------------*/
      71             : 
      72          12 : ivas_error ivas_er_init(
      73             :     er_struct_t *reflections,
      74             :     const AUDIO_CONFIG inConfig )
      75             : {
      76             :     ivas_error error;
      77             :     uint8_t i;
      78             : 
      79             :     /* Set to defaults for shoebox */
      80          12 :     reflections->is_ready = 0;
      81          12 :     reflections->audio_config = IVAS_AUDIO_CONFIG_INVALID;
      82          12 :     reflections->is_cartesian = 0;
      83          12 :     reflections->is_relative = 1;
      84          12 :     reflections->shoebox_data.n_ref = ER_NUM_REF;
      85          12 :     reflections->user_origin[0] = 0.0f;
      86          12 :     reflections->user_origin[1] = 0.0f;
      87          12 :     reflections->user_origin[2] = ER_LIST_HEIGHT;
      88             : 
      89             :     /* Store scene origin if present */
      90          48 :     for ( i = 0; i < 3; i++ )
      91             :     {
      92          36 :         reflections->user_origin[i] = reflections->shoebox_lib.cal.list_orig[i];
      93             :     }
      94             : 
      95             :     /* Init Shoebox */
      96          12 :     ivas_shoebox_init( &reflections->shoebox_lib, &reflections->shoebox_lib.cal );
      97             : 
      98             :     /* Set mode */
      99          12 :     if ( ( error = ivas_er_set_reflections_mode( reflections, inConfig ) ) != IVAS_ERR_OK )
     100             :     {
     101           0 :         return error;
     102             :     }
     103             : 
     104             :     /* Compute the static reflections (first frame) */
     105          12 :     if ( ( error = ivas_er_compute_reflections( reflections ) ) != IVAS_ERR_OK )
     106             :     {
     107           0 :         return error;
     108             :     }
     109             : 
     110          12 :     if ( ( reflections->closest_ch_idx = (uint16_t *) malloc( reflections->n_total_reflections * sizeof( uint16_t ) ) ) == NULL )
     111             :     {
     112           0 :         return IVAS_ERR_FAILED_ALLOC;
     113             :     }
     114          12 :     set_s( (int16_t *) reflections->closest_ch_idx, 0, reflections->n_total_reflections );
     115             : 
     116          12 :     if ( ( error = getAudioConfigNumChannels( reflections->audio_config, &( reflections->nchan_out ) ) ) != IVAS_ERR_OK )
     117             :     {
     118           0 :         return error;
     119             :     }
     120             : 
     121             :     /* Initialize Encoder */
     122          12 :     if ( ( error = ivas_er_encoder_init( reflections ) ) != IVAS_ERR_OK )
     123             :     {
     124           0 :         return error;
     125             :     }
     126             : 
     127             :     /* Update flag to indicate that reflection module is ready to process */
     128          12 :     reflections->is_ready = 1;
     129             : 
     130          12 :     return error;
     131             : }
     132             : 
     133             : 
     134             : /*-----------------------------------------------------------------------------------------*
     135             :  Function ivas_er_set_reflections_mode()
     136             : 
     137             :  Function sets the ER source positions based on the audio config
     138             :  *-----------------------------------------------------------------------------------------*/
     139             : 
     140          12 : ivas_error ivas_er_set_reflections_mode(
     141             :     er_struct_t *reflections,
     142             :     const AUDIO_CONFIG inConfig )
     143             : {
     144             :     ivas_error error;
     145             :     uint16_t ch;
     146          12 :     error = IVAS_ERR_OK;
     147             : 
     148          12 :     if ( reflections->audio_config == inConfig )
     149             :     {
     150           0 :         return error;
     151             :     }
     152             : 
     153          12 :     reflections->is_ready = 0;
     154          12 :     reflections->audio_config = inConfig;
     155             : 
     156          12 :     switch ( reflections->audio_config )
     157             :     {
     158           0 :         case IVAS_AUDIO_CONFIG_MONO:
     159           0 :             reflections->shoebox_data.n_sources = 1;
     160           0 :             reflections->n_LC_sources = 1;
     161           0 :             reflections->LC_mixing = LC_mixing_5_1;
     162           0 :             reflections->source_positions[0] = 0;
     163           0 :             reflections->source_positions[1] = 0;
     164           0 :             reflections->source_positions[2] = ER_RADIUS;
     165           0 :             break;
     166           0 :         case IVAS_AUDIO_CONFIG_STEREO:
     167           0 :             reflections->shoebox_data.n_sources = 2;
     168           0 :             reflections->n_LC_sources = 2;
     169           0 :             reflections->LC_mixing = LC_mixing_5_1;
     170           0 :             for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ )
     171             :             {
     172           0 :                 reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP2[ch] );
     173           0 :                 reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP2[ch] );
     174           0 :                 reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS;
     175             :             }
     176           0 :             break;
     177           3 :         case IVAS_AUDIO_CONFIG_5_1:
     178           3 :             reflections->shoebox_data.n_sources = 5;
     179           3 :             reflections->n_LC_sources = 3;
     180           3 :             reflections->LC_mixing = LC_mixing_5_1;
     181          18 :             for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ )
     182             :             {
     183          15 :                 reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP6[ch] );
     184          15 :                 reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP6[ch] );
     185          15 :                 reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS;
     186             :             }
     187           3 :             break;
     188           0 :         case IVAS_AUDIO_CONFIG_7_1:
     189           0 :             reflections->shoebox_data.n_sources = 7;
     190           0 :             reflections->n_LC_sources = 5;
     191           0 :             reflections->LC_mixing = LC_mixing_7_1;
     192           0 :             for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ )
     193             :             {
     194           0 :                 reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP12[ch] );
     195           0 :                 reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP12[ch] );
     196           0 :                 reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS;
     197             :             }
     198           0 :             break;
     199           0 :         case IVAS_AUDIO_CONFIG_5_1_2:
     200           0 :             reflections->shoebox_data.n_sources = 7;
     201           0 :             reflections->n_LC_sources = 5;
     202           0 :             reflections->LC_mixing = LC_mixing_5_1_2;
     203           0 :             for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ )
     204             :             {
     205           0 :                 reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP14[ch] );
     206           0 :                 reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP14[ch] );
     207           0 :                 reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS;
     208             :             }
     209           0 :             break;
     210           0 :         case IVAS_AUDIO_CONFIG_5_1_4:
     211           0 :             reflections->shoebox_data.n_sources = 9;
     212           0 :             reflections->n_LC_sources = 5;
     213           0 :             reflections->LC_mixing = LC_mixing_5_1_4;
     214           0 :             for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ )
     215             :             {
     216           0 :                 reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP16[ch] );
     217           0 :                 reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP16[ch] );
     218           0 :                 reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS;
     219             :             }
     220           0 :             break;
     221           9 :         case IVAS_AUDIO_CONFIG_7_1_4:
     222           9 :             reflections->shoebox_data.n_sources = 11;
     223           9 :             reflections->n_LC_sources = 5;
     224           9 :             reflections->LC_mixing = LC_mixing_7_1_4;
     225         108 :             for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ )
     226             :             {
     227          99 :                 reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP19[ch] );
     228          99 :                 reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP19[ch] );
     229          99 :                 reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS;
     230             :             }
     231           9 :             break;
     232           0 :         case IVAS_AUDIO_CONFIG_HOA3:
     233           0 :             reflections->use_er = 0;
     234           0 :             break;
     235           0 :         case IVAS_AUDIO_CONFIG_HOA2:
     236           0 :             reflections->use_er = 0;
     237           0 :             break;
     238           0 :         case IVAS_AUDIO_CONFIG_FOA:
     239           0 :             reflections->use_er = 0;
     240           0 :             break;
     241           0 :         default:
     242           0 :             reflections->audio_config = IVAS_AUDIO_CONFIG_INVALID;
     243           0 :             return IVAS_ERROR( IVAS_ERR_INVALID_ER_PARAM, "Unsupported reflections mode" );
     244             :     }
     245             : 
     246          12 :     return error;
     247             : }
     248             : 
     249             : 
     250             : /*-----------------------------------------------------------------------------------------*
     251             :  Function ivas_er_encoder_init()
     252             : 
     253             :  Function that initializes the er encoder
     254             :  *-----------------------------------------------------------------------------------------*/
     255             : 
     256          12 : ivas_error ivas_er_encoder_init(
     257             :     er_struct_t *reflections )
     258             : {
     259          12 :     ivas_error error = IVAS_ERR_OK;
     260             :     uint16_t i, j, src_idx;
     261          12 :     uint16_t min_index = 0;
     262             :     float p_x, p_y, p_z;
     263             :     float p_x_src, p_y_src, p_z_src;
     264             :     float tmp;
     265          12 :     float dist, min_dist = 0;
     266             : 
     267          12 :     if ( !reflections )
     268             :     {
     269           0 :         return IVAS_ERR_FAILED_ALLOC;
     270             :     }
     271             : 
     272          12 :     if ( getAudioConfigType( reflections->audio_config ) == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED )
     273             :     {
     274             :         /* Compute MC-snap location (closest channel position to reflection direction) */
     275         696 :         for ( i = 0; i < reflections->n_total_reflections; i++ )
     276             :         {
     277             :             /* Compute cartesian points for reflection (from degrees) */
     278         684 :             p_x = ER_RADIUS * ( cosf( deg2rad( reflections->shoebox_data.el_angle.data[i] ) ) * cosf( deg2rad( reflections->shoebox_data.az_angle.data[i] ) ) );
     279         684 :             p_y = ER_RADIUS * ( cosf( deg2rad( reflections->shoebox_data.el_angle.data[i] ) ) * sinf( deg2rad( reflections->shoebox_data.az_angle.data[i] ) ) );
     280         684 :             p_z = ER_RADIUS * ( sinf( deg2rad( reflections->shoebox_data.el_angle.data[i] ) ) );
     281             : 
     282             :             /* Calculate the euclidean distance to each point in the config ls setup */
     283        8352 :             for ( j = 0; j < reflections->nchan_out; j++ )
     284             :             {
     285             :                 /* Ignore LFE */
     286        7668 :                 if ( j != LFE_CHANNEL )
     287             :                 {
     288        6984 :                     src_idx = ( j > LFE_CHANNEL ) ? j - 1 : j;
     289             : 
     290        6984 :                     p_x_src = reflections->source_positions[src_idx * 3 + 2] * ( cosf( reflections->source_positions[src_idx * 3 + 1] ) * cosf( reflections->source_positions[src_idx * 3] ) );
     291        6984 :                     p_y_src = reflections->source_positions[src_idx * 3 + 2] * ( cosf( reflections->source_positions[src_idx * 3 + 1] ) * sinf( reflections->source_positions[src_idx * 3] ) );
     292        6984 :                     p_z_src = reflections->source_positions[src_idx * 3 + 2] * sinf( reflections->source_positions[src_idx * 3 + 1] );
     293             : 
     294        6984 :                     tmp = ( p_x_src - p_x ) * ( p_x_src - p_x );
     295        6984 :                     tmp += ( p_y_src - p_y ) * ( p_y_src - p_y );
     296        6984 :                     tmp += ( p_z_src - p_z ) * ( p_z_src - p_z );
     297        6984 :                     dist = sqrtf( tmp );
     298             : 
     299             :                     /* Save index of closest channel */
     300        6984 :                     if ( src_idx == 0 )
     301             :                     {
     302         684 :                         min_dist = dist;
     303         684 :                         min_index = j;
     304             :                     }
     305             :                     else
     306             :                     {
     307        6300 :                         if ( dist < min_dist )
     308             :                         {
     309        1356 :                             min_dist = dist;
     310        1356 :                             min_index = j;
     311             :                         }
     312             :                     }
     313             :                 }
     314             :             }
     315             : 
     316         684 :             reflections->closest_ch_idx[i] = (uint16_t) min_index;
     317             :         }
     318             :     }
     319             : 
     320          12 :     return error;
     321             : }
     322             : 
     323             : 
     324             : /*-----------------------------------------------------------------------------------------*
     325             :  Function ivas_er_compute_reflections()
     326             : 
     327             :  Function computes reflections using the shoebox library and sets up the circular buffers
     328             :  structure for the early reflections process
     329             :  *-----------------------------------------------------------------------------------------*/
     330             : 
     331          12 : ivas_error ivas_er_compute_reflections(
     332             :     er_struct_t *reflections )
     333             : {
     334          12 :     ivas_error error = IVAS_ERR_OK;
     335             :     uint16_t circ_len, i, j;
     336             :     float tmp;
     337             : 
     338          12 :     reflections->is_ready = 0;
     339             : 
     340             :     /* Disabled case */
     341          12 :     if ( reflections->audio_config == IVAS_AUDIO_CONFIG_INVALID )
     342             :     {
     343           0 :         return error;
     344             :     }
     345             : 
     346             :     /* Run shoebox with current reflection parameters */
     347          12 :     ivas_shoebox_set_scene( &( reflections->shoebox_lib ), &( reflections->shoebox_data ), reflections->shoebox_lib.cal.list_orig,
     348          12 :                             reflections->source_positions, reflections->is_cartesian, reflections->is_relative );
     349             : 
     350             :     /* Convert reflection times in seconds to samples and keep track of max */
     351          12 :     circ_len = 0;
     352         126 :     for ( i = 0; i < reflections->shoebox_data.n_sources; i++ )
     353             :     {
     354         798 :         for ( j = 0; j < reflections->shoebox_data.n_ref; j++ )
     355             :         {
     356         684 :             tmp = reflections->shoebox_data.times.data[j + ( i * reflections->shoebox_data.n_ref )];
     357         684 :             tmp = roundf( tmp * reflections->output_Fs );
     358         684 :             reflections->shoebox_data.times.data[j + ( i * reflections->shoebox_data.n_ref )] = tmp;
     359         684 :             circ_len = ( (uint16_t) tmp > circ_len ) ? (uint16_t) tmp : circ_len;
     360             :         }
     361             :     }
     362             : 
     363             :     /* If max delay is less than max frame size, use max frame size to compute circ buffer length */
     364          12 :     circ_len = ( circ_len > (uint16_t) reflections->max_frame_size ) ? circ_len : (uint16_t) reflections->max_frame_size;
     365          12 :     circ_len += (uint16_t) reflections->max_frame_size;
     366             : 
     367             :     /* If circ buffers exist and size is the same, reset memory to all zeros */
     368             :     /* If size is different, reallocate circ buffers */
     369             :     /* Otherwise allocate new circ buffers */
     370          12 :     if ( reflections->circ_buffers )
     371             :     {
     372           0 :         if ( reflections->circ_len == circ_len )
     373             :         {
     374             :             /* circ buffers exist and size is the same */
     375           0 :             set_f( reflections->circ_buffers, 0.0f, reflections->shoebox_data.n_sources * reflections->circ_len );
     376             :         }
     377             :         else
     378             :         {
     379             :             /* circ buffers exist but size is different */
     380           0 :             reflections->circ_len = circ_len;
     381           0 :             free( reflections->circ_buffers );
     382           0 :             if ( ( reflections->circ_buffers = (float *) malloc( reflections->shoebox_data.n_sources * reflections->circ_len * sizeof( float ) ) ) == NULL )
     383             :             {
     384           0 :                 return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Early Reflections buffers" );
     385             :             }
     386           0 :             set_f( reflections->circ_buffers, 0.0f, reflections->shoebox_data.n_sources * reflections->circ_len );
     387             :         }
     388             :     }
     389             :     else
     390             :     {
     391             :         /* circ buffers do not exist */
     392          12 :         reflections->circ_len = circ_len;
     393          12 :         if ( ( reflections->circ_buffers = (float *) malloc( reflections->shoebox_data.n_sources * reflections->circ_len * sizeof( float ) ) ) == NULL )
     394             :         {
     395           0 :             return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Early Reflections buffers" );
     396             :         }
     397          12 :         set_f( reflections->circ_buffers, 0.0f, reflections->shoebox_data.n_sources * reflections->circ_len );
     398             :     }
     399             : 
     400             : 
     401             :     /* Initialize circular buffer insertion point */
     402          12 :     reflections->circ_insert = reflections->circ_len - (uint16_t) reflections->max_frame_size;
     403             : 
     404             :     /* Get total reflections number */
     405          12 :     reflections->n_total_reflections = reflections->shoebox_data.n_sources * reflections->shoebox_data.n_ref;
     406             : 
     407             :     /* Check that reflection buffers were allocated */
     408          12 :     if ( error != IVAS_ERR_OK )
     409             :     {
     410           0 :         return error;
     411             :     }
     412             : 
     413          12 :     return error;
     414             : }
     415             : 
     416             : 
     417             : /*-----------------------------------------------------------------------------------------*
     418             : Function ivas_er_process()
     419             : 
     420             : Takes a buffer of N channels, returns a buffer of N*6 channels containing the early
     421             : reflections (one per wall). The process is a delay line architecture
     422             : *-----------------------------------------------------------------------------------------*/
     423             : 
     424             : 
     425       17400 : ivas_error ivas_er_process(
     426             :     er_struct_t *reflections,
     427             :     const int16_t subframe_size,
     428             :     const int16_t subframe_idx,
     429             :     float **io,
     430             :     const AUDIO_CONFIG inConfig )
     431             : {
     432       17400 :     ivas_error error = IVAS_ERR_OK;
     433             :     uint16_t i, j, k, subframe_offset;
     434             :     uint16_t ref_no, ref_delay;
     435             :     uint16_t n_ref_sources, n_ref;
     436             :     int16_t samp_idx, in_ch_idx, buf_ch_idx, ref_out_idx;
     437             :     float ref_gain;
     438             :     float *buffer_ch;
     439             : 
     440       17400 :     if ( !reflections )
     441             :     {
     442           0 :         return IVAS_ERR_INIT_ERROR;
     443             :     }
     444             : 
     445             :     /* should not arrive here if reflections are disabled but in case it does just do nothing */
     446       17400 :     if ( reflections->use_er != 1 )
     447             :     {
     448           0 :         return error;
     449             :     }
     450             : 
     451             :     /* Ensure all reflection memory is allocated */
     452       17400 :     if ( !reflections->circ_buffers || !reflections->is_ready )
     453             :     {
     454           0 :         return IVAS_ERR_INIT_ERROR;
     455             :     }
     456             : 
     457       17400 :     subframe_offset = subframe_idx * subframe_size;
     458       17400 :     n_ref = reflections->shoebox_data.n_ref;
     459             : 
     460             :     /* If low complexity ER are requested only compute ER for n_LC_sources */
     461       17400 :     if ( reflections->lowComplexity )
     462             :     {
     463       13800 :         n_ref_sources = reflections->n_LC_sources;
     464             :     }
     465             :     else
     466             :     {
     467        3600 :         n_ref_sources = reflections->shoebox_data.n_sources;
     468             :     }
     469             : 
     470             :     /* Channel case, copy input into buffers panning for LC mode and skipping LFE */
     471       17400 :     if ( getAudioConfigType( inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED )
     472             :     {
     473             :         /* Loop through all input sources filling circular buffers */
     474      136800 :         for ( i = 0; i < reflections->shoebox_data.n_sources; i++ )
     475             :         {
     476             :             /* Pull correct circular buffer depending on complexity mode */
     477      119400 :             buf_ch_idx = ( reflections->lowComplexity == 1 ) ? reflections->LC_mixing[i] : i;
     478      119400 :             buffer_ch = &( reflections->circ_buffers[buf_ch_idx * reflections->circ_len] );
     479             : 
     480             :             /* Skip LFE from input buffer */
     481      119400 :             in_ch_idx = ( i >= LFE_CHANNEL ) ? i + 1 : i;
     482      119400 :             samp_idx = reflections->circ_insert;
     483             : 
     484             :             /* If less than number of reflection sources, overwrite buffer */
     485      119400 :             if ( i == buf_ch_idx )
     486             :             {
     487    20388600 :                 for ( j = 0; j < subframe_size; j++ )
     488             :                 {
     489    20304000 :                     buffer_ch[samp_idx++] = io[in_ch_idx][j + subframe_offset];
     490    20304000 :                     samp_idx = samp_idx % reflections->circ_len;
     491             :                 }
     492             :             }
     493             :             /* Accumulate with buffer for low complexity mixed sources */
     494             :             else
     495             :             {
     496     8386800 :                 for ( j = 0; j < subframe_size; j++ )
     497             :                 {
     498     8352000 :                     buffer_ch[samp_idx++] += io[in_ch_idx][j + subframe_offset];
     499     8352000 :                     samp_idx = samp_idx % reflections->circ_len;
     500             :                 }
     501             :             }
     502             :         }
     503             :     }
     504             :     else
     505             :     {
     506           0 :         return IVAS_ERR_INVALID_INPUT_FORMAT;
     507             :     }
     508             : 
     509             :     /* Loop through sources retrieve reflections from circ buffers */
     510      102000 :     for ( i = 0; i < n_ref_sources; i++ )
     511             :     {
     512             :         /* Access correct row of input circ buffer */
     513       84600 :         buffer_ch = &( reflections->circ_buffers[i * reflections->circ_len] );
     514             : 
     515             :         /* Loop through reflections */
     516      592200 :         for ( j = 0; j < n_ref; j++ )
     517             :         {
     518      507600 :             ref_no = j + ( i * n_ref );
     519      507600 :             ref_gain = reflections->shoebox_data.gains.data[ref_no];
     520      507600 :             ref_delay = (uint16_t) reflections->shoebox_data.times.data[ref_no];
     521      507600 :             ref_out_idx = reflections->closest_ch_idx[ref_no];
     522             : 
     523             :             /* Determine start idx of reflection in circ buffer based on
     524             :             current insert idx and reflection delay */
     525      507600 :             samp_idx = (int16_t) reflections->circ_insert - ref_delay;
     526      507600 :             if ( samp_idx < 0 )
     527             :             {
     528      159609 :                 samp_idx = (int16_t) reflections->circ_len + samp_idx;
     529             :             }
     530             : 
     531             :             /* Pull reflection from circ buffer and apply gain */
     532   122331600 :             for ( k = 0; k < subframe_size; k++ )
     533             :             {
     534   121824000 :                 io[ref_out_idx][k + subframe_offset] += buffer_ch[samp_idx++] * ref_gain;
     535   121824000 :                 samp_idx = samp_idx % reflections->circ_len;
     536             :             }
     537             :         }
     538             :     }
     539             : 
     540             :     /* Increment circular buffer start index */
     541       17400 :     reflections->circ_insert = ( reflections->circ_insert + subframe_size ) % reflections->circ_len;
     542             : 
     543       17400 :     return error;
     544             : }

Generated by: LCOV version 1.14