LCOV - code coverage report
Current view: top level - lib_rend - ivas_reverb.c (source / functions) Hit Total Coverage
Test: Coverage on main -- merged total coverage @ 0c62f5312a76f89f3e6d6ab9a8d50516c9ab4059 Lines: 567 641 88.5 %
Date: 2025-12-17 10:49:08 Functions: 34 34 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.h"
      36             : #include "ivas_prot_rend.h"
      37             : #include "ivas_cnst.h"
      38             : #ifdef DEBUGGING
      39             : #include "debug.h"
      40             : #endif
      41             : #include "math.h"
      42             : #include "ivas_rom_rend.h"
      43             : #include <assert.h>
      44             : #include "wmc_auto.h"
      45             : 
      46             : 
      47             : /* The reverberator structure implemented here is described in detail in:
      48             :  * Vilkamo, J., Neugebauer, B., & Plogsties, J. (2012). Sparse frequency-domain reverberator.
      49             :  * Journal of the Audio Engineering Society, 59(12), 936-943. */
      50             : 
      51             : /*-------------------------------------------------------------------------
      52             :  * Local constants
      53             :  *------------------------------------------------------------------------*/
      54             : 
      55             : #define BIN_REND_RANDOM_SEED 1 /* random seed for generating reverb decorrelators */
      56             : 
      57             : #define CLDFB_SLOTS_PER_SECOND 800 /* Used for initializing reverb */
      58             : 
      59             : #define REV_TIME_THRESHOLD ( 0.2f )
      60             : 
      61             : #define INNER_BLK_SIZE 80 /* size of data blocks used for more efficient delay line and IIR filter processing */
      62             : /* should be a divisor of the frame length at any sampling rate and an even number*/
      63             : #define FFT_FILTER_WND_FLAT_REGION  ( 0.40f ) /* flat section (==1) length of FFT filter window, in proportion to overlap */
      64             : #define FFT_FILTER_WND_TRANS_REGION ( 0.15f ) /* transition (1->0) length of FFT filter window, in proportion to overlap */
      65             : #define REF_LF_MIN                  ( 100.0f )
      66             : #define REF_LF_MAX                  ( 250.0f )
      67             : #define REF_HF_MIN                  ( 5000.0f )
      68             : #define REF_HF_MAX                  ( 7950.0f )
      69             : #define LF_BIAS                     ( 0.5f )
      70             : 
      71             : #define DEFAULT_SRC_DIST ( 1.5f ) /* default source distance [m] for reverb dmx factor computing */
      72             : 
      73             : #define IVAS_REVERB_FFT_SIZE_48K        ( 512 )
      74             : #define IVAS_REVERB_FFT_SIZE_32K        ( 512 )
      75             : #define IVAS_REVERB_FFT_SIZE_16K        ( 256 )
      76             : #define IVAS_REVERB_FFT_N_SUBBLOCKS_48K ( 1 )
      77             : #define IVAS_REVERB_FFT_N_SUBBLOCKS_32K ( 1 )
      78             : #define IVAS_REVERB_FFT_N_SUBBLOCKS_16K ( 1 )
      79             : 
      80             : #define MAX_NR_OUTPUTS ( 2 )
      81             : 
      82             : static const int16_t init_loop_delay[IVAS_REV_MAX_NR_BRANCHES] = { 37, 31, 29, 23, 19, 17, 13, 11 };
      83             : static const int16_t default_loop_delay_48k[IVAS_REV_MAX_NR_BRANCHES] = { 2309, 1861, 1523, 1259, 1069, 919, 809, 719 };
      84             : static const int16_t default_loop_delay_32k[IVAS_REV_MAX_NR_BRANCHES] = { 1531, 1237, 1013, 839, 709, 613, 541, 479 };
      85             : static const int16_t default_loop_delay_16k[IVAS_REV_MAX_NR_BRANCHES] = { 769, 619, 509, 421, 353, 307, 269, 239 };
      86             : 
      87             : /*------------------------------------------------------------------------------------------*
      88             :  * Local Struct definition
      89             :  *------------------------------------------------------------------------------------------*/
      90             : 
      91             : typedef struct ivas_reverb_params_t
      92             : {
      93             :     int16_t pre_delay;                                                                                   /* Delay of the FDC reverb, first peak after pre_delay samples. Note that               */
      94             :                                                                                                          /*       there may be non-zero samples earlier due to the filters being                 */
      95             :                                                                                                          /*       linear-phase.                                                                  */
      96             :     int16_t nr_loops;                                                                                    /* Number of feedback loops (= L)                                                       */
      97             :     int16_t pLoop_delays[IVAS_REV_MAX_NR_BRANCHES];                                                      /* Delay for each feedback loop in samples.                                             */
      98             :     float pLoop_feedback_matrix[IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_NR_BRANCHES];                    /* Feedback [L][L] matrix that mixes the signals of the loops.                          */
      99             :     int16_t nr_outputs;                                                                                  /* Nr of signals extracted from the loops (= S).                                        */
     100             :                                                                                                          /*       Currently this is fixed to 2.                                                  */
     101             :     float pLoop_extract_matrix[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES];                               /* Mix [S][L] matrix from feedback loops to outputs.                                    */
     102             :                                                                                                          /* In Matlab: [S x L] - Currently S=2, later may be more than 2 for speaker playback.   */
     103             :     int16_t t60_filter_order;                                                                            /* Filter order (length of vector)                                                      */
     104             :     float pT60_filter_coeff[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_IIR_FILTER_LENGTH]; /* Filters [][] in feedback loops, controlling T60.                                    */
     105             :                                                                                                          /* In Matlab: IIR: [(2 * L) x (<order> + 1)] (odd: b-vector, even: a-vector)            */
     106             :                                                                                                          /* In Matlab: FIR: [L       x <order>]                                                  */
     107             :     float *pFc;                                                                                          /* Center frequencies for FFT filter design                                             */
     108             :     float *pRt60;                                                                                        /* RT60 values at these frequencies                                                     */
     109             :     float *pDsr;                                                                                         /* DSR values at these frequencies                                                      */
     110             :     const float *pHrtf_avg_pwr_response_l_const;                                                         /* The HRTF set's average left  ear power response                                      */
     111             :     const float *pHrtf_avg_pwr_response_r_const;                                                         /* The HRTF set's average right ear power response                                      */
     112             :     const float *pHrtf_inter_aural_coherence_const;                                                      /* The HRTF set's inter-aural coherence for diffuse sound                               */
     113             : 
     114             :     int16_t do_corr_filter; /* Flag indicating whether correlation filters should be used.                          */
     115             :                             /*        Correlation only supported and needed for binaural playback (i.e.             */
     116             :                             /*        when nr_outputs != 2 correlation filtering is never supported).               */
     117             : } ivas_reverb_params_t;
     118             : 
     119             : 
     120             : /*------------------------------------------------------------------------------------------*
     121             :  * Static functions declarations
     122             :  *------------------------------------------------------------------------------------------*/
     123             : 
     124             : static ivas_error calc_jot_t60_coeffs( float *pH_dB, const uint16_t nrFrequencies, float *pFrequencies, float *pCoeffA, float *pCoeffB, const float fNyquist );
     125             : 
     126             : 
     127             : /*-------------------------------------------------------------------------
     128             :  * binRend_rand()
     129             :  *
     130             :  *
     131             :  *------------------------------------------------------------------------*/
     132             : 
     133   176227065 : static uint16_t binRend_rand(
     134             :     REVERB_STRUCT_HANDLE hReverb /* i/o: binaural reverb handle          */
     135             : )
     136             : {
     137   176227065 :     hReverb->binRend_RandNext = hReverb->binRend_RandNext * 1103515245 + 12345;
     138             : 
     139   176227065 :     return (uint16_t) ( hReverb->binRend_RandNext / 65536 ) % 32768;
     140             : }
     141             : 
     142             : 
     143             : /*-------------------------------------------------------------------------
     144             :  * ivas_binaural_reverb_setPreDelay()
     145             :  *
     146             :  *
     147             :  *------------------------------------------------------------------------*/
     148             : 
     149       32899 : static void ivas_binaural_reverb_setPreDelay(
     150             :     REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle          */
     151             :     const int16_t delaySamples    /* i  : reverb pre-delay in CLDFB slots */
     152             : )
     153             : {
     154       32899 :     if ( delaySamples < 1 )
     155             :     {
     156           0 :         hReverb->preDelayBufferLength = 1;
     157             : 
     158           0 :         return;
     159             :     }
     160             : 
     161       32899 :     if ( delaySamples > IVAS_REVERB_PREDELAY_MAX )
     162             :     {
     163          25 :         hReverb->preDelayBufferLength = IVAS_REVERB_PREDELAY_MAX;
     164             : 
     165          25 :         return;
     166             :     }
     167             : 
     168       32874 :     hReverb->preDelayBufferLength = delaySamples;
     169             : 
     170       32874 :     return;
     171             : }
     172             : 
     173             : 
     174             : /*-------------------------------------------------------------------------
     175             :  * ivas_binaural_reverb_setReverbTimes()
     176             :  *
     177             :  *
     178             :  *------------------------------------------------------------------------*/
     179             : 
     180       32899 : static void ivas_binaural_reverb_setReverbTimes(
     181             :     REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle                                  */
     182             :     const int32_t output_Fs,      /* i  : sampling_rate                                           */
     183             :     const float *revTimes,        /* i  : reverberation times T60 for each CLDFB bin in seconds   */
     184             :     const float *revEnes          /* i  : spectrum for reverberated sound at each CLDFB bin       */
     185             : )
     186             : {
     187             :     int16_t bin, ch, tap, sample;
     188             :     float binCenterFreq, diffuseFieldICC, tmpVal, attenuationFactorPerSample;
     189             :     float intendedEnergy, actualizedEnergy, energyBuildup, currentEnergy, attenuationFactorPerSampleSq;
     190             : 
     191       32899 :     hReverb->binRend_RandNext = (uint16_t) BIN_REND_RANDOM_SEED;
     192       32899 :     hReverb->highestBinauralCoherenceBin = 0;
     193     1362609 :     for ( bin = 0; bin < hReverb->numBins; bin++ )
     194             :     {
     195             :         /* Determine the diffuse field binaural coherence */
     196     1329710 :         binCenterFreq = ( (float) bin + 0.5f ) / ( (float) hReverb->numBins ) * ( (float) output_Fs ) / 2.0f;
     197     1329710 :         if ( bin == 0 )
     198             :         {
     199       32899 :             diffuseFieldICC = 1.0f;
     200             :         }
     201     1296811 :         else if ( binCenterFreq < 2700.0f )
     202             :         {
     203      193595 :             diffuseFieldICC = sinf( EVS_PI * binCenterFreq / 550.0f + 1e-20f ) / ( EVS_PI * binCenterFreq / 550.0f + 1e-20f ) * ( 1.0f - binCenterFreq / 2700.0f );
     204      193595 :             hReverb->highestBinauralCoherenceBin = bin;
     205             :         }
     206             :         else
     207             :         {
     208     1103216 :             diffuseFieldICC = 0.0f;
     209             :         }
     210             : 
     211             :         /* Mixing gains to generate a diffuse-binaural sound based on incoherent sound */
     212     1329710 :         tmpVal = ( 1.0f - sqrtf( 1.0f - powf( diffuseFieldICC, 2.0 ) ) ) / 2.0f;
     213     1329710 :         if ( diffuseFieldICC > 0 )
     214             :         {
     215      127797 :             hReverb->binauralCoherenceCrossmixGains[bin] = sqrtf( fabsf( tmpVal ) );
     216             :         }
     217             :         else
     218             :         {
     219     1201913 :             hReverb->binauralCoherenceCrossmixGains[bin] = -sqrtf( fabsf( tmpVal ) );
     220             :         }
     221     1329710 :         hReverb->binauralCoherenceDirectGains[bin] = sqrtf( 1.0f - fabsf( tmpVal ) );
     222             : 
     223             :         /* Determine attenuation factor that generates the appropriate energy decay according to reverberation time */
     224     1329710 :         attenuationFactorPerSample = powf( 10.0f, -3.0f * ( 1.0f / ( (float) CLDFB_SLOTS_PER_SECOND * revTimes[bin] ) ) );
     225     1329710 :         hReverb->loopAttenuationFactor[bin] = powf( attenuationFactorPerSample, hReverb->loopBufLength[bin] );
     226     1329710 :         attenuationFactorPerSampleSq = attenuationFactorPerSample * attenuationFactorPerSample;
     227             : 
     228             :         /* Design sparse decorrelation filters. The decorrelation filters, due to random procedures involved,
     229             :          * may affect the spectrum of the output. The spectral effect is therefore monitored and compensated for. */
     230     1329710 :         intendedEnergy = 0.0f;
     231     1329710 :         actualizedEnergy = 0.0f;
     232             : 
     233     3989130 :         for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
     234             :         {
     235     2659420 :             energyBuildup = 0.0f;
     236     2659420 :             currentEnergy = 1.0f;
     237     2659420 :             tap = 0;
     238             : 
     239   138893508 :             for ( sample = 0; sample < hReverb->loopBufLength[bin]; sample++ )
     240             :             {
     241   136234088 :                 intendedEnergy += currentEnergy;
     242             : 
     243             :                 /* The randomization at the energy build up affects where the sparse taps are located */
     244   136234088 :                 energyBuildup += currentEnergy + 0.1f * ( (float) binRend_rand( hReverb ) / PCM16_TO_FLT_FAC - 0.5f );
     245             : 
     246   136234088 :                 if ( energyBuildup >= 1.0f ) /* A new filter tap is added at this condition */
     247             :                 {
     248             :                     /* Four efficient phase operations: n*pi/2, n=0,1,2,3 */
     249    39992977 :                     hReverb->tapPhaseShiftType[bin][ch][tap] = (int16_t) ( binRend_rand( hReverb ) % 4 );
     250             :                     /* Set the tapPointer to point to the determined sample at the loop buffer */
     251    39992977 :                     hReverb->tapPointersReal[bin][ch][tap] = &( hReverb->loopBufReal[bin][sample] );
     252    39992977 :                     hReverb->tapPointersImag[bin][ch][tap] = &( hReverb->loopBufImag[bin][sample] );
     253    39992977 :                     energyBuildup -= 1.0f; /* A tap is added, thus remove its energy from the buildup */
     254    39992977 :                     tap++;
     255    39992977 :                     actualizedEnergy += 1.0f;
     256             :                 }
     257   136234088 :                 currentEnergy *= attenuationFactorPerSampleSq;
     258             :             }
     259             :             /* In some configurations with small T60s it is possible the number of taps randomizes to zero.
     260             :                Ensure at least 1 filter tap. */
     261     2659420 :             if ( tap == 0 )
     262             :             {
     263           0 :                 hReverb->tapPhaseShiftType[bin][ch][0] = (int16_t) ( binRend_rand( hReverb ) % 4 );
     264           0 :                 hReverb->tapPointersReal[bin][ch][0] = &( hReverb->loopBufReal[bin][0] );
     265           0 :                 hReverb->tapPointersImag[bin][ch][0] = &( hReverb->loopBufImag[bin][0] );
     266           0 :                 tap = 1;
     267           0 :                 actualizedEnergy = 1;
     268             :             }
     269             : 
     270     2659420 :             hReverb->taps[bin][ch] = tap; /* Number of taps determined at the above random procedure */
     271             :         }
     272             : 
     273             :         /* The decorrelator design and IIR attenuation rate affects the energy of reverb, which is compensated here */
     274     1329710 :         hReverb->reverbEqGains[bin] = sqrtf( revEnes[bin] );                                    /* Determined reverb spectrum */
     275     1329710 :         hReverb->reverbEqGains[bin] *= sqrtf( intendedEnergy / actualizedEnergy );              /* Correction of random effects at the decorrelator design */
     276     1329710 :         hReverb->reverbEqGains[bin] *= sqrtf( 0.5f * ( 1.0f - attenuationFactorPerSampleSq ) ); /* Correction of IIR decay rate */
     277             :     }
     278             : 
     279       32899 :     return;
     280             : }
     281             : 
     282             : 
     283             : /*-----------------------------------------------------------------------------------------*
     284             :  * Function compute_feedback_matrix()
     285             :  *
     286             :  * Compute the N x N matrix for the mixing the N feedback loop outputs into the N inputs again
     287             :  *-----------------------------------------------------------------------------------------*/
     288             : 
     289       52608 : static ivas_error compute_feedback_matrix(
     290             :     float *pFeedbackMatrix,
     291             :     const int16_t n )
     292             : {
     293             :     float u, v;
     294             :     int16_t i, j, x;
     295             : 
     296       52608 :     if ( n == 6 )
     297             :     {
     298             :         /* special case (there is no 6 x 6 Hadamard matrix in set R) */
     299           0 :         u = -1.0f / 3;
     300           0 :         v = 1.0f + u;
     301           0 :         for ( i = 0; i < n; i++ )
     302             :         {
     303           0 :             for ( j = 0; j < n; j++ )
     304             :             {
     305           0 :                 if ( i == j )
     306             :                 {
     307           0 :                     pFeedbackMatrix[i * n + j] = v;
     308             :                 }
     309             :                 else
     310             :                 {
     311           0 :                     pFeedbackMatrix[i * n + j] = u;
     312             :                 }
     313             :             }
     314             :         }
     315             :     }
     316             :     else
     317             :     {
     318       52608 :         if ( !( n == 4 || n == 8 || n == 16 ) )
     319             :         {
     320           0 :             return IVAS_ERR_INTERNAL; /* n must be 4, 6, 8 or 16, else ERROR */
     321             :         }
     322             : 
     323       52608 :         u = inv_sqrt( n );
     324             : 
     325       52608 :         if ( n == 4 )
     326             :         {
     327           0 :             u = -u;
     328             :         }
     329             : 
     330       52608 :         pFeedbackMatrix[0] = u;
     331      210432 :         for ( x = 1; x < n; x += x )
     332             :         {
     333      526080 :             for ( i = 0; i < x; i++ )
     334             :             {
     335     1473024 :                 for ( j = 0; j < x; j++ )
     336             :                 {
     337     1104768 :                     pFeedbackMatrix[( i + x ) * n + j] = pFeedbackMatrix[i * n + j];
     338     1104768 :                     pFeedbackMatrix[i * n + j + x] = pFeedbackMatrix[i * n + j];
     339     1104768 :                     pFeedbackMatrix[( i + x ) * n + j + x] = -pFeedbackMatrix[i * n + j];
     340             :                 }
     341             :             }
     342             :         }
     343             : 
     344       52608 :         if ( n == 4 )
     345             :         {
     346             :             /* special case */
     347           0 :             for ( j = 12; j < 16; j++ )
     348             :             {
     349           0 :                 pFeedbackMatrix[j] = -pFeedbackMatrix[j];
     350             :             }
     351             :         }
     352             :     }
     353             : 
     354       52608 :     return IVAS_ERR_OK;
     355             : }
     356             : 
     357             : 
     358             : /*-----------------------------------------------------------------------------------------*
     359             :  * Function compute_2_out_extract_matrix()
     360             :  *
     361             :  * Compute the N x 2 matrix for mixing the N Jot feedback loops to 2 outputs
     362             :  *-----------------------------------------------------------------------------------------*/
     363             : 
     364       52608 : static void compute_2_out_extract_matrix(
     365             :     float *pExtractMatrix,
     366             :     const int16_t n )
     367             : {
     368             :     float ff;
     369             :     int16_t i;
     370             : 
     371       52608 :     ff = 1.0;
     372      473472 :     for ( i = 0; i < n; i++ )
     373             :     {
     374      420864 :         pExtractMatrix[i] = 1.0;
     375      420864 :         pExtractMatrix[i + n] = ff;
     376      420864 :         ff = -ff;
     377             :     }
     378             : 
     379       52608 :     return;
     380             : }
     381             : 
     382             : 
     383             : /*-----------------------------------------------------------------------------------------*
     384             :  * Function set_base_config()
     385             :  *
     386             :  * Set all jot reverb parameters that are independent of the input reverb configuration
     387             :  *-----------------------------------------------------------------------------------------*/
     388             : 
     389       52608 : static ivas_error set_base_config(
     390             :     ivas_reverb_params_t *pParams,
     391             :     const int32_t output_Fs )
     392             : {
     393             :     ivas_error error;
     394             :     int16_t loop_idx;
     395       52608 :     const int16_t *selected_loop_delay = NULL;
     396             : 
     397       52608 :     if ( pParams == NULL )
     398             :     {
     399           0 :         return IVAS_ERR_INTERNAL;
     400             :     }
     401             : 
     402       52608 :     pParams->pre_delay = 0;
     403       52608 :     pParams->nr_outputs = BINAURAL_CHANNELS;
     404       52608 :     pParams->nr_loops = IVAS_REV_MAX_NR_BRANCHES;
     405             : 
     406             :     /* set loop delays to default */
     407       52608 :     if ( output_Fs == 48000 )
     408             :     {
     409       17215 :         selected_loop_delay = default_loop_delay_48k;
     410             :     }
     411       35393 :     else if ( output_Fs == 32000 )
     412             :     {
     413       17534 :         selected_loop_delay = default_loop_delay_32k;
     414             :     }
     415       17859 :     else if ( output_Fs == 16000 )
     416             :     {
     417       17859 :         selected_loop_delay = default_loop_delay_16k;
     418             :     }
     419             : 
     420      473472 :     for ( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ )
     421             :     {
     422      420864 :         pParams->pLoop_delays[loop_idx] = selected_loop_delay[loop_idx];
     423             :     }
     424             : 
     425             :     /* set feedback and output matrices */
     426       52608 :     if ( ( error = compute_feedback_matrix( pParams->pLoop_feedback_matrix, pParams->nr_loops ) ) != IVAS_ERR_OK )
     427             :     {
     428           0 :         return error;
     429             :     }
     430             : 
     431       52608 :     compute_2_out_extract_matrix( pParams->pLoop_extract_matrix, pParams->nr_loops );
     432             : 
     433             :     /* pre-set the various filters; they will be set later based on reverb configuration */
     434       52608 :     pParams->t60_filter_order = 1; /* set to 1 in base config. */
     435             : 
     436       52608 :     if ( pParams->nr_outputs == 2 )
     437             :     {
     438       52608 :         pParams->do_corr_filter = 1;
     439             :     }
     440             :     else
     441             :     {
     442           0 :         pParams->do_corr_filter = 0;
     443             :     }
     444             : 
     445       52608 :     return IVAS_ERR_OK;
     446             : }
     447             : 
     448             : 
     449             : /*-----------------------------------------------------------------------------------------*
     450             :  * Function calc_dmx_gain()
     451             :  *
     452             :  * Computes the downmix gain
     453             :  *-----------------------------------------------------------------------------------------*/
     454             : 
     455       12692 : static float calc_dmx_gain( void )
     456             : {
     457       12692 :     const float dist = DEFAULT_SRC_DIST;
     458       12692 :     return sqrtf( 4.0f * EVS_PI * dist * dist / 0.001f );
     459             : }
     460             : 
     461             : 
     462             : /*-----------------------------------------------------------------------------------------*
     463             :  * Function calc_predelay()
     464             :  *
     465             :  * Calculate the predelay, taking shortest jot loop delay into account
     466             :  *-----------------------------------------------------------------------------------------*/
     467             : 
     468       52608 : static void calc_predelay(
     469             :     ivas_reverb_params_t *pParams,
     470             :     float acoustic_predelay_sec,
     471             :     const int32_t output_Fs )
     472             : {
     473             :     int16_t predelay, fbdelay, output_frame;
     474             : 
     475       52608 :     predelay = (int16_t) roundf( acoustic_predelay_sec * (float) output_Fs );
     476       52608 :     output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC );
     477       52608 :     fbdelay = pParams->pLoop_delays[pParams->nr_loops - 1];
     478       52608 :     predelay -= fbdelay;
     479             : 
     480       52608 :     if ( predelay < 0 )
     481             :     {
     482        5432 :         predelay = 0;
     483             :     }
     484             : 
     485       52608 :     if ( output_frame < predelay )
     486             :     {
     487           0 :         predelay = output_frame;
     488             :     }
     489             : 
     490       52608 :     pParams->pre_delay = predelay;
     491             : 
     492       52608 :     return;
     493             : }
     494             : 
     495             : 
     496             : /*-----------------------------------------------------------------------------------------*
     497             :  * Function compute_t60_coeffs()
     498             :  *
     499             :  * Calculate Jot reverb's T60 filter coefficients
     500             :  *-----------------------------------------------------------------------------------------*/
     501             : 
     502       52608 : static ivas_error compute_t60_coeffs(
     503             :     ivas_reverb_params_t *pParams,
     504             :     const int16_t nr_fc_fft_filter,
     505             :     const int32_t output_Fs )
     506             : {
     507             :     int16_t bin_idx, loop_idx, tf_T60_len, len;
     508             :     float loop_delay_sec, freq_Nyquist, inv_hfs;
     509             :     float target_gains_db[RV_LENGTH_NR_FC];
     510             :     float norm_f[RV_LENGTH_NR_FC];
     511             :     float *pCoeffs_a, *pCoeffs_b;
     512             :     float *targetT60, *freqT60;
     513             :     ivas_error error;
     514             : 
     515       52608 :     targetT60 = pParams->pRt60;
     516       52608 :     freqT60 = pParams->pFc;
     517             : 
     518       52608 :     error = IVAS_ERR_OK;
     519       52608 :     tf_T60_len = nr_fc_fft_filter;
     520       52608 :     len = pParams->t60_filter_order + 1;
     521       52608 :     freq_Nyquist = 0.5f * (float) output_Fs;
     522             : 
     523             :     /* normalize pFrequencies: 0 .. 1/2 output_Fs --> 0.0 .. 1.0 */
     524       52608 :     inv_hfs = 1.0f / freq_Nyquist;
     525    11286912 :     for ( bin_idx = 0; bin_idx < tf_T60_len; bin_idx++ )
     526             :     {
     527    11234304 :         norm_f[bin_idx] = freqT60[bin_idx] * inv_hfs;
     528             :     }
     529             : 
     530      473472 :     for ( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ )
     531             :     {
     532      420864 :         loop_delay_sec = (float) pParams->pLoop_delays[loop_idx] / (float) output_Fs;
     533    90295296 :         for ( bin_idx = 0; bin_idx < tf_T60_len; bin_idx++ )
     534             :         {
     535    89874432 :             target_gains_db[bin_idx] = -60.0f * loop_delay_sec / targetT60[bin_idx];
     536    89874432 :             target_gains_db[bin_idx] = max( target_gains_db[bin_idx], -120.0f );
     537             :         }
     538             : 
     539      420864 :         pCoeffs_a = &pParams->pT60_filter_coeff[2 * len * loop_idx + len];
     540      420864 :         pCoeffs_b = &pParams->pT60_filter_coeff[2 * len * loop_idx];
     541      420864 :         if ( ( error = calc_jot_t60_coeffs( target_gains_db, tf_T60_len, norm_f, pCoeffs_a, pCoeffs_b, freq_Nyquist ) ) != IVAS_ERR_OK )
     542             :         {
     543           0 :             return error;
     544             :         }
     545             :     }
     546             : 
     547       52608 :     len = ( pParams->t60_filter_order + 1 ) >> 1; /* == floor( (order+1) / 2) */
     548      473472 :     for ( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ )
     549             :     {
     550      420864 :         pParams->pLoop_delays[loop_idx] -= len;
     551             :     }
     552             : 
     553       52608 :     return error;
     554             : }
     555             : 
     556             : 
     557             : /*-----------------------------------------------------------------------------------------*
     558             :  * Function calc_low_shelf_first_order_filter()
     559             :  *
     560             :  * Calculate 1st order low shelf filter
     561             :  *-----------------------------------------------------------------------------------------*/
     562             : 
     563      420864 : static void calc_low_shelf_first_order_filter(
     564             :     float *pNum,
     565             :     float *pDen,
     566             :     const float f0,
     567             :     const float lin_gain_lf,
     568             :     const float lin_gain_hf )
     569             : {
     570             :     float w0, gain;
     571             : 
     572      420864 :     w0 = tanf( EVS_PI * f0 / 2.0f );
     573      420864 :     gain = lin_gain_lf / lin_gain_hf;
     574             : 
     575      420864 :     if ( gain < 1.0f )
     576             :     {
     577           0 :         pNum[0] = 1 + w0 * gain;
     578           0 :         pNum[1] = w0 * gain - 1;
     579           0 :         pDen[0] = 1 + w0;
     580           0 :         pDen[1] = w0 - 1;
     581             :     }
     582             :     else
     583             :     {
     584      420864 :         pNum[0] = 1 + w0;
     585      420864 :         pNum[1] = w0 - 1;
     586      420864 :         pDen[0] = 1 + w0 / gain;
     587      420864 :         pDen[1] = w0 / gain - 1;
     588             :     }
     589             : 
     590             :     /* Normalize and adjust gain to match target amplitudes */
     591      420864 :     pNum[0] = ( pNum[0] / pDen[0] ) * lin_gain_hf;
     592      420864 :     pNum[1] = ( pNum[1] / pDen[0] ) * lin_gain_hf;
     593      420864 :     pDen[1] = pDen[1] / pDen[0];
     594      420864 :     pDen[0] = 1.0f;
     595             : 
     596      420864 :     return;
     597             : }
     598             : 
     599             : 
     600             : /*-----------------------------------------------------------------------------------------*
     601             :  * Function calc_jot_t60_coeffs()
     602             :  *
     603             :  * Calculate Jot reverb's T60 filters
     604             :  *-----------------------------------------------------------------------------------------*/
     605             : 
     606      420864 : static ivas_error calc_jot_t60_coeffs(
     607             :     float *pH_dB,
     608             :     const uint16_t nrFrequencies,
     609             :     float *pFrequencies,
     610             :     float *pCoeffA,
     611             :     float *pCoeffB,
     612             :     const float fNyquist )
     613             : {
     614      420864 :     const float ref_lf_min_norm = REF_LF_MIN / fNyquist;
     615      420864 :     const float ref_lf_max_norm = REF_LF_MAX / fNyquist;
     616      420864 :     const float ref_hf_min_norm = REF_HF_MIN / fNyquist;
     617      420864 :     const float ref_hf_max_norm = REF_HF_MAX / fNyquist;
     618             :     int16_t f_idx, minidx;
     619             :     float f0, tmp, minval, lf_target_gain_dB, hf_target_gain_dB, mid_crossing_gain_dB;
     620             :     uint16_t n_points_lf, n_points_hf;
     621             :     float lin_gain_lf, lin_gain_hf;
     622             : 
     623      420864 :     minidx = nrFrequencies - 1;
     624      420864 :     minval = 1e+20f;
     625      420864 :     lf_target_gain_dB = 0.0f;
     626      420864 :     hf_target_gain_dB = 0.0f;
     627      420864 :     n_points_lf = 0;
     628      420864 :     n_points_hf = 0;
     629             : 
     630    90295296 :     for ( f_idx = 0; f_idx < nrFrequencies; f_idx++ )
     631             :     {
     632    89874432 :         if ( ( pFrequencies[f_idx] >= ref_lf_min_norm ) && ( pFrequencies[f_idx] <= ref_lf_max_norm ) )
     633             :         {
     634      987152 :             lf_target_gain_dB += pH_dB[f_idx];
     635      987152 :             n_points_lf++;
     636             :         }
     637    89874432 :         if ( ( pFrequencies[f_idx] >= ref_hf_min_norm ) && ( pFrequencies[f_idx] <= ref_hf_max_norm ) )
     638             :         {
     639    17860232 :             hf_target_gain_dB += pH_dB[f_idx];
     640    17860232 :             n_points_hf++;
     641             :         }
     642             :     }
     643             : 
     644      420864 :     if ( ( n_points_lf == 0 ) || ( n_points_hf == 0 ) )
     645             :     {
     646           0 :         return IVAS_ERR_INTERNAL;
     647             :     }
     648             : 
     649      420864 :     lf_target_gain_dB = lf_target_gain_dB / (float) n_points_lf;
     650      420864 :     hf_target_gain_dB = hf_target_gain_dB / (float) n_points_hf;
     651      420864 :     mid_crossing_gain_dB = hf_target_gain_dB + LF_BIAS * ( lf_target_gain_dB - hf_target_gain_dB );
     652             : 
     653    89453568 :     for ( f_idx = 1; f_idx < nrFrequencies - 1; f_idx++ )
     654             :     {
     655    89032704 :         tmp = fabsf( pH_dB[f_idx] - mid_crossing_gain_dB );
     656    89032704 :         if ( tmp < minval )
     657             :         {
     658     5724352 :             minval = tmp;
     659     5724352 :             minidx = f_idx;
     660             :         }
     661             :     }
     662             : 
     663      420864 :     f0 = pFrequencies[minidx];
     664      420864 :     lin_gain_lf = powf( 10.0f, lf_target_gain_dB * 0.05f );
     665      420864 :     lin_gain_hf = powf( 10.0f, hf_target_gain_dB * 0.05f );
     666             : 
     667             :     /* call low-pass iir shelf */
     668      420864 :     calc_low_shelf_first_order_filter( pCoeffB, pCoeffA, f0, lin_gain_lf, lin_gain_hf );
     669             : 
     670      420864 :     return IVAS_ERR_OK;
     671             : }
     672             : 
     673             : 
     674             : /*-----------------------------------------------------------------------------------------*
     675             :  * Function initialize_reverb_filters()
     676             :  *
     677             :  * Set the number of branches (feedback loops) and Initializes the memory structure (pointers to data)
     678             :  *-----------------------------------------------------------------------------------------*/
     679             : 
     680       12692 : static ivas_error initialize_reverb_filters(
     681             :     REVERB_HANDLE hReverb )
     682             : {
     683             :     ivas_error error;
     684             : 
     685             :     /* init correlation and coloration filters */
     686       12692 :     if ( ( error = ivas_reverb_t2f_f2t_init( &hReverb->fft_filter_ols, hReverb->fft_size, hReverb->fft_subblock_size ) ) != IVAS_ERR_OK )
     687             :     {
     688           0 :         return error;
     689             :     }
     690             : 
     691       12692 :     if ( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_correl_0, hReverb->fft_size ) ) != IVAS_ERR_OK )
     692             :     {
     693           0 :         return error;
     694             :     }
     695             : 
     696       12692 :     if ( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_correl_1, hReverb->fft_size ) ) != IVAS_ERR_OK )
     697             :     {
     698           0 :         return error;
     699             :     }
     700             : 
     701       12692 :     if ( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_color_0, hReverb->fft_size ) ) != IVAS_ERR_OK )
     702             :     {
     703           0 :         return error;
     704             :     }
     705             : 
     706       12692 :     if ( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_color_1, hReverb->fft_size ) ) != IVAS_ERR_OK )
     707             :     {
     708           0 :         return error;
     709             :     }
     710             : 
     711       12692 :     return IVAS_ERR_OK;
     712             : }
     713             : 
     714             : 
     715             : /*-----------------------------------------------------------------------------------------*
     716             :  * Function set_t60_filter()
     717             :  *
     718             :  * Sets t60 number of taps and coefficients A and B
     719             :  *-----------------------------------------------------------------------------------------*/
     720             : 
     721      420864 : static ivas_error set_t60_filter(
     722             :     REVERB_HANDLE hReverb,
     723             :     const uint16_t branch,
     724             :     const uint16_t nr_taps,
     725             :     const float coefA[],
     726             :     const float coefB[] )
     727             : {
     728      420864 :     if ( branch >= hReverb->nr_of_branches )
     729             :     {
     730           0 :         return IVAS_ERR_INTERNAL;
     731             :     }
     732             : 
     733      420864 :     if ( nr_taps > IVAS_REV_MAX_IIR_FILTER_LENGTH )
     734             :     {
     735           0 :         return IVAS_ERR_INTERNAL;
     736             :     }
     737             : 
     738      420864 :     ivas_reverb_iir_filt_set( &( hReverb->t60[branch] ), nr_taps, coefA, coefB );
     739             : 
     740      420864 :     return IVAS_ERR_OK;
     741             : }
     742             : 
     743             : 
     744             : /*-----------------------------------------------------------------------------------------*
     745             :  * Function set_feedback_delay()
     746             :  *
     747             :  * Sets Delay of feedback branch in number of samples
     748             :  *-----------------------------------------------------------------------------------------*/
     749             : 
     750      101536 : static ivas_error set_feedback_delay(
     751             :     REVERB_HANDLE hReverb,
     752             :     const uint16_t branch,
     753             :     const int16_t fb_delay )
     754             : {
     755      101536 :     if ( branch >= hReverb->nr_of_branches )
     756             :     {
     757           0 :         return IVAS_ERR_INTERNAL;
     758             :     }
     759             : 
     760      101536 :     hReverb->delay_line[branch].Delay = fb_delay;
     761             : 
     762      101536 :     return IVAS_ERR_OK;
     763             : }
     764             : 
     765             : 
     766             : /*-----------------------------------------------------------------------------------------*
     767             :  * Function set_feedback_gain()
     768             :  *
     769             :  * Sets nr_of_branches feedback gain values in feedback matrix
     770             :  *-----------------------------------------------------------------------------------------*/
     771             : 
     772      101536 : static ivas_error set_feedback_gain(
     773             :     REVERB_HANDLE hReverb,
     774             :     const uint16_t branch,
     775             :     const float *pGain )
     776             : {
     777             :     uint16_t gain_idx;
     778      101536 :     if ( branch >= hReverb->nr_of_branches )
     779             :     {
     780           0 :         return IVAS_ERR_INTERNAL;
     781             :     }
     782             : 
     783      913824 :     for ( gain_idx = 0; gain_idx < hReverb->nr_of_branches; gain_idx++ )
     784             :     {
     785      812288 :         hReverb->gain_matrix[branch][gain_idx] = pGain[gain_idx];
     786             :     }
     787             : 
     788      101536 :     return IVAS_ERR_OK;
     789             : }
     790             : 
     791             : 
     792             : /*-----------------------------------------------------------------------------------------*
     793             :  * Function set_correl_fft_filter()
     794             :  *
     795             :  * Sets correlation filter complex gains
     796             :  *-----------------------------------------------------------------------------------------*/
     797             : 
     798      105216 : static ivas_error set_correl_fft_filter(
     799             :     REVERB_HANDLE hReverb,
     800             :     const uint16_t channel,
     801             :     rv_fftwf_type_complex *pSpectrum )
     802             : {
     803      105216 :     if ( channel > 1 )
     804             :     {
     805           0 :         return IVAS_ERR_INTERNAL;
     806             :     }
     807             : 
     808      105216 :     if ( channel == 0 )
     809             :     {
     810       52608 :         ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, hReverb->fft_filter_correl_0.fft_spectrum, hReverb->fft_filter_correl_0.fft_size );
     811             :     }
     812             :     else
     813             :     {
     814       52608 :         ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, hReverb->fft_filter_correl_1.fft_spectrum, hReverb->fft_filter_correl_1.fft_size );
     815             :     }
     816             : 
     817      105216 :     return IVAS_ERR_OK;
     818             : }
     819             : 
     820             : 
     821             : /*-----------------------------------------------------------------------------------------*
     822             :  * Function set_color_fft_filter()
     823             :  *
     824             :  * Sets coloration filter complex gains
     825             :  *-----------------------------------------------------------------------------------------*/
     826             : 
     827      105216 : static ivas_error set_color_fft_filter(
     828             :     REVERB_HANDLE hReverb,
     829             :     const uint16_t channel,
     830             :     rv_fftwf_type_complex *pSpectrum )
     831             : {
     832      105216 :     if ( channel > 1 )
     833             :     {
     834           0 :         return IVAS_ERR_INTERNAL;
     835             :     }
     836             : 
     837      105216 :     if ( channel == 0 )
     838             :     {
     839       52608 :         ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, hReverb->fft_filter_color_0.fft_spectrum, hReverb->fft_filter_color_0.fft_size );
     840             :     }
     841             :     else
     842             :     {
     843       52608 :         ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, hReverb->fft_filter_color_1.fft_spectrum, hReverb->fft_filter_color_1.fft_size );
     844             :     }
     845             : 
     846      105216 :     return IVAS_ERR_OK;
     847             : }
     848             : 
     849             : 
     850             : /*-----------------------------------------------------------------------------------------*
     851             :  * Function set_mixer_level()
     852             :  *
     853             :  * Sets Mixer level: to mix 2 output channels from 8 feedback branches
     854             :  *-----------------------------------------------------------------------------------------*/
     855             : 
     856       25384 : static ivas_error set_mixer_level(
     857             :     REVERB_HANDLE hReverb,
     858             :     const uint16_t channel,
     859             :     const float level[] )
     860             : {
     861             :     uint16_t branch_idx;
     862       25384 :     if ( channel >= BINAURAL_CHANNELS )
     863             :     {
     864           0 :         return IVAS_ERR_INTERNAL;
     865             :     }
     866             : 
     867      228456 :     for ( branch_idx = 0; branch_idx < hReverb->nr_of_branches; branch_idx++ )
     868             :     {
     869      203072 :         hReverb->mixer[channel][branch_idx] = level[branch_idx];
     870             :     }
     871             : 
     872       25384 :     return IVAS_ERR_OK;
     873             : }
     874             : 
     875             : 
     876             : /*-----------------------------------------------------------------------------------------*
     877             :  * Function clear_buffers()
     878             :  *
     879             :  * Clears buffers of delay lines and filters
     880             :  *-----------------------------------------------------------------------------------------*/
     881             : 
     882       12692 : static void clear_buffers(
     883             :     REVERB_HANDLE hReverb )
     884             : {
     885             :     int16_t branch_idx;
     886             :     ivas_rev_iir_filter_t *iirFilter;
     887             :     ivas_rev_delay_line_t *delay_line;
     888             : 
     889      114228 :     for ( branch_idx = 0; branch_idx < IVAS_REV_MAX_NR_BRANCHES; branch_idx++ )
     890             :     {
     891      101536 :         delay_line = &( hReverb->delay_line[branch_idx] );
     892      101536 :         set_f( delay_line->pBuffer, 0, delay_line->MaxDelay );
     893      101536 :         delay_line->BufferPos = 0;
     894             : 
     895      101536 :         iirFilter = &( hReverb->t60[branch_idx] );
     896      101536 :         set_f( iirFilter->pBuffer, 0, iirFilter->MaxTaps );
     897             :     }
     898             : 
     899       12692 :     ivas_reverb_t2f_f2t_ClearHistory( &hReverb->fft_filter_ols );
     900             : 
     901       12692 :     return;
     902             : }
     903             : 
     904             : 
     905             : /*-----------------------------------------------------------------------------------------*
     906             :  * Function set_fft_and_datablock_sizes()
     907             :  *
     908             :  * Sets frame size and fft-filter related sizes
     909             :  *-----------------------------------------------------------------------------------------*/
     910             : 
     911       52608 : static void set_fft_and_datablock_sizes(
     912             :     REVERB_HANDLE hReverb,
     913             :     const int16_t subframe_len )
     914             : {
     915       52608 :     hReverb->full_block_size = subframe_len;
     916       52608 :     if ( subframe_len == L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES )
     917             :     {
     918       17215 :         hReverb->fft_size = IVAS_REVERB_FFT_SIZE_48K;
     919       17215 :         hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_48K;
     920             :     }
     921       35393 :     else if ( subframe_len == L_FRAME32k / MAX_PARAM_SPATIAL_SUBFRAMES )
     922             :     {
     923       17534 :         hReverb->fft_size = IVAS_REVERB_FFT_SIZE_32K;
     924       17534 :         hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_32K;
     925             :     }
     926       17859 :     else if ( subframe_len == L_FRAME16k / MAX_PARAM_SPATIAL_SUBFRAMES )
     927             :     {
     928       17859 :         hReverb->fft_size = IVAS_REVERB_FFT_SIZE_16K;
     929       17859 :         hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_16K;
     930             :     }
     931             :     else
     932             :     {
     933           0 :         assert( 0 ); /* unsupported block size */
     934             :     }
     935             : 
     936       52608 :     hReverb->fft_subblock_size = subframe_len / hReverb->num_fft_subblocks;
     937             : 
     938       52608 :     return;
     939             : }
     940             : 
     941             : 
     942             : /*-----------------------------------------------------------------------------------------*
     943             :  * Function set_reverb_acoustic_data()
     944             :  *
     945             :  * Sets reverb acoustic data (room acoustics and HRTF), interpolating it to the filter grid
     946             :  *-----------------------------------------------------------------------------------------*/
     947             : 
     948       52608 : static void set_reverb_acoustic_data(
     949             :     ivas_reverb_params_t *pParams,
     950             :     IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pRoomAcoustics,
     951             :     const int16_t nr_fc_input,
     952             :     const int16_t nr_fc_fft_filter )
     953             : {
     954             :     int16_t bin_idx;
     955             :     float ln_1e6_inverted, delay_diff, exp_argument;
     956             :     /* interpolate input table data for T60 and DSR to the FFT filter grid */
     957       52608 :     ivas_reverb_interpolate_acoustic_data( nr_fc_input, pRoomAcoustics->pFc_input, pRoomAcoustics->pAcoustic_rt60, pRoomAcoustics->pAcoustic_dsr,
     958       52608 :                                            nr_fc_fft_filter, pParams->pFc, pParams->pRt60, pParams->pDsr );
     959             : 
     960             :     /* adjust DSR for the delay difference */
     961       52608 :     delay_diff = pRoomAcoustics->inputPreDelay - pRoomAcoustics->acousticPreDelay;
     962       52608 :     ln_1e6_inverted = 1.0f / logf( 1e06f );
     963    11286912 :     for ( bin_idx = 0; bin_idx < nr_fc_fft_filter; bin_idx++ )
     964             :     {
     965    11234304 :         exp_argument = delay_diff / ( pParams->pRt60[bin_idx] * ln_1e6_inverted );
     966             :         /* Limit exponent to approx +/-100 dB in case of incoherent value of delay_diff, to prevent overflow */
     967    11234304 :         exp_argument = min( exp_argument, 23.0f );
     968    11234304 :         exp_argument = max( exp_argument, -23.0f );
     969    11234304 :         pParams->pDsr[bin_idx] *= expf( exp_argument );
     970             :     }
     971             : 
     972       52608 :     return;
     973             : }
     974             : 
     975             : 
     976             : /*-----------------------------------------------------------------------------------------*
     977             :  * Function setup_FDN_branches()
     978             :  *
     979             :  * Sets up feedback delay network system
     980             :  *-----------------------------------------------------------------------------------------*/
     981             : 
     982       12692 : static ivas_error setup_FDN_branches(
     983             :     REVERB_HANDLE hReverb,
     984             :     ivas_reverb_params_t *pParams )
     985             : {
     986             :     int16_t nr_coefs, branch_idx, channel_idx;
     987             :     ivas_error error;
     988       12692 :     error = IVAS_ERR_OK;
     989             : 
     990             :     /* initialize feedback branches */
     991      114228 :     for ( branch_idx = 0; branch_idx < IVAS_REV_MAX_NR_BRANCHES; branch_idx++ )
     992             :     {
     993      101536 :         ivas_rev_delay_line_init( &( hReverb->delay_line[branch_idx] ), hReverb->loop_delay_buffer[branch_idx], init_loop_delay[branch_idx], pParams->pLoop_delays[branch_idx] );
     994      101536 :         ivas_reverb_iir_filt_init( &( hReverb->t60[branch_idx] ), IVAS_REV_MAX_IIR_FILTER_LENGTH );
     995      101536 :         hReverb->mixer[0][branch_idx] = 0.0f;
     996      101536 :         hReverb->mixer[1][branch_idx] = 0.0f;
     997             :     }
     998       12692 :     clear_buffers( hReverb );
     999       12692 :     nr_coefs = pParams->t60_filter_order + 1;
    1000             : 
    1001       12692 :     if ( IVAS_REV_MAX_IIR_FILTER_LENGTH < nr_coefs )
    1002             :     {
    1003           0 :         return IVAS_ERR_INTERNAL;
    1004             :     }
    1005             :     else
    1006             :     {
    1007      114228 :         for ( branch_idx = 0; branch_idx < pParams->nr_loops; branch_idx++ )
    1008             :         {
    1009      101536 :             if ( ( error = set_feedback_delay( hReverb, branch_idx, pParams->pLoop_delays[branch_idx] ) ) != IVAS_ERR_OK )
    1010             :             {
    1011           0 :                 return error;
    1012             :             }
    1013             : 
    1014      101536 :             if ( ( error = set_feedback_gain( hReverb, branch_idx, &( pParams->pLoop_feedback_matrix[branch_idx * pParams->nr_loops] ) ) ) != IVAS_ERR_OK )
    1015             :             {
    1016           0 :                 return error;
    1017             :             }
    1018             :         }
    1019             :     }
    1020             : 
    1021       38076 :     for ( channel_idx = 0; channel_idx < pParams->nr_outputs; channel_idx++ )
    1022             :     {
    1023       25384 :         if ( ( error = set_mixer_level( hReverb, channel_idx, &( pParams->pLoop_extract_matrix[channel_idx * pParams->nr_loops] ) ) ) != IVAS_ERR_OK )
    1024             :         {
    1025           0 :             return error;
    1026             :         }
    1027             :     }
    1028             : 
    1029       12692 :     return error;
    1030             : }
    1031             : 
    1032             : 
    1033             : /*-------------------------------------------------------------------------
    1034             :  * ivas_reverb_open()
    1035             :  *
    1036             :  * Allocate and initialize FDN reverberation handle
    1037             :  *------------------------------------------------------------------------*/
    1038             : 
    1039       52608 : ivas_error ivas_reverb_open(
    1040             :     REVERB_HANDLE *hReverb,                        /* i/o: Reverberator handle               */
    1041             :     const HRTFS_STATISTICS_HANDLE hHrtfStatistics, /* i  : HRTF statistics handle            */
    1042             :     RENDER_CONFIG_HANDLE hRenderConfig,            /* i  : Renderer configuration handle     */
    1043             :     const int32_t output_Fs                        /* i  : output sampling rate              */
    1044             : )
    1045             : {
    1046             :     ivas_error error;
    1047       52608 :     REVERB_HANDLE pState = *hReverb;
    1048             :     int16_t nr_coefs, branch_idx;
    1049             :     float *pCoef_a, *pCoef_b;
    1050             :     int16_t bin_idx, subframe_len, output_frame, predelay_bf_len, loop_idx;
    1051             :     ivas_reverb_params_t params;
    1052             :     rv_fftwf_type_complex pFft_wf_filter_ch0[RV_LENGTH_NR_FC];
    1053             :     rv_fftwf_type_complex pFft_wf_filter_ch1[RV_LENGTH_NR_FC];
    1054             :     float pColor_target_l[RV_LENGTH_NR_FC];
    1055             :     float pColor_target_r[RV_LENGTH_NR_FC];
    1056             :     float pTime_window[RV_FILTER_MAX_FFT_SIZE];
    1057             :     float freq_step;
    1058             :     int16_t fft_hist_size, transition_start, transition_length;
    1059             :     int16_t nr_fc_input, nr_fc_fft_filter;
    1060             : 
    1061       52608 :     output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC );
    1062       52608 :     subframe_len = output_frame / MAX_PARAM_SPATIAL_SUBFRAMES;
    1063       52608 :     predelay_bf_len = output_frame;
    1064       52608 :     nr_fc_input = hRenderConfig->roomAcoustics.nBands;
    1065             : 
    1066       52608 :     if ( *hReverb == NULL )
    1067             :     {
    1068             :         /* Allocate main reverb. handle */
    1069       12692 :         if ( ( pState = (REVERB_HANDLE) malloc( sizeof( REVERB_DATA ) ) ) == NULL )
    1070             :         {
    1071           0 :             return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for FDN Reverberator " );
    1072             :         }
    1073             :     }
    1074             : 
    1075       52608 :     if ( ( error = set_base_config( &params, output_Fs ) ) != IVAS_ERR_OK )
    1076             :     {
    1077           0 :         return error;
    1078             :     }
    1079             : 
    1080       52608 :     if ( *hReverb == NULL )
    1081             :     {
    1082             :         /* Allocate memory for feedback delay lines */
    1083      114228 :         for ( loop_idx = 0; loop_idx < IVAS_REV_MAX_NR_BRANCHES; loop_idx++ )
    1084             :         {
    1085      101536 :             if ( ( pState->loop_delay_buffer[loop_idx] = (float *) malloc( params.pLoop_delays[loop_idx] * sizeof( float ) ) ) == NULL )
    1086             :             {
    1087           0 :                 return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for FDN Reverberator" );
    1088             :             }
    1089             :         }
    1090             : 
    1091             :         /* Allocate memory for the pre-delay delay line */
    1092       12692 :         if ( ( pState->pPredelay_buffer = (float *) malloc( output_frame * sizeof( float ) ) ) == NULL )
    1093             :         {
    1094           0 :             return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for FDN Reverberator" );
    1095             :         }
    1096             :     }
    1097             : 
    1098       52608 :     pState->nr_of_branches = IVAS_REV_MAX_NR_BRANCHES;
    1099       52608 :     set_fft_and_datablock_sizes( pState, subframe_len );
    1100             : 
    1101       52608 :     nr_fc_fft_filter = ( pState->fft_size >> 1 ) + 1;
    1102             : 
    1103             :     /* === 'Control logic': compute the reverb processing parameters from the              === */
    1104             :     /* === room, source and listener acoustic information provided in the reverb config    === */
    1105             :     /* Setting up shared temporary buffers for fc, RT60, DSR, etc.                             */
    1106       52608 :     params.pRt60 = &pFft_wf_filter_ch1[0][0];
    1107       52608 :     params.pDsr = params.pRt60 + nr_fc_fft_filter;
    1108       52608 :     params.pFc = &pState->fft_filter_color_0.fft_spectrum[0];
    1109             : 
    1110             :     /* Note: these temp buffers can only be used before the final step of the FFT filter design :     */
    1111             :     /* before calls to ivas_reverb_calc_correl_filters(...) or to ivas_reverb_calc_color_filters(...) */
    1112             : 
    1113             :     /* set the uniform frequency grid for FFT filtering                                               */
    1114       52608 :     freq_step = 0.5f * output_Fs / ( nr_fc_fft_filter - 1 );
    1115    11286912 :     for ( bin_idx = 0; bin_idx < nr_fc_fft_filter; bin_idx++ )
    1116             :     {
    1117    11234304 :         params.pFc[bin_idx] = freq_step * bin_idx;
    1118             :     }
    1119             : 
    1120       52608 :     set_reverb_acoustic_data( &params, &hRenderConfig->roomAcoustics, nr_fc_input, nr_fc_fft_filter );
    1121       52608 :     params.pHrtf_avg_pwr_response_l_const = hHrtfStatistics->average_energy_l;
    1122       52608 :     params.pHrtf_avg_pwr_response_r_const = hHrtfStatistics->average_energy_r;
    1123       52608 :     params.pHrtf_inter_aural_coherence_const = hHrtfStatistics->inter_aural_coherence;
    1124             : 
    1125             :     /* set reverb acoustic configuration based on renderer config  */
    1126       52608 :     pState->pConfig.roomAcoustics.nBands = hRenderConfig->roomAcoustics.nBands;
    1127             : 
    1128       52608 :     if ( hRenderConfig->roomAcoustics.use_er == 1 )
    1129             :     {
    1130       26030 :         pState->pConfig.roomAcoustics.use_er = hRenderConfig->roomAcoustics.use_er;
    1131       26030 :         pState->pConfig.roomAcoustics.lowComplexity = hRenderConfig->roomAcoustics.lowComplexity;
    1132             :     }
    1133             : 
    1134             :     /*  set up input downmix  */
    1135       52608 :     if ( *hReverb == NULL )
    1136             :     {
    1137       12692 :         pState->dmx_gain = calc_dmx_gain();
    1138             :     }
    1139             : 
    1140             :     /*  set up predelay - must be after set_base_config() and before compute_t60_coeffs() */
    1141       52608 :     calc_predelay( &params, hRenderConfig->roomAcoustics.acousticPreDelay, output_Fs );
    1142             : 
    1143             :     /*  set up jot reverb 60 filters - must be set up after set_reverb_acoustic_data() */
    1144       52608 :     if ( ( error = compute_t60_coeffs( &params, nr_fc_fft_filter, output_Fs ) ) != IVAS_ERR_OK )
    1145             :     {
    1146           0 :         return error;
    1147             :     }
    1148             : 
    1149             :     /* Compute target levels (gains) for the coloration filters */
    1150       52608 :     ivas_reverb_calc_color_levels( output_Fs, nr_fc_fft_filter, params.nr_loops, params.pFc, params.pDsr, params.pHrtf_avg_pwr_response_l_const, params.pHrtf_avg_pwr_response_r_const,
    1151             :                                    params.pLoop_delays, params.pT60_filter_coeff, pColor_target_l, pColor_target_r );
    1152             : 
    1153             :     /* Defining appropriate windowing parameters for FFT filters to prevent aliasing */
    1154       52608 :     fft_hist_size = pState->fft_size - pState->fft_subblock_size;
    1155             : 
    1156       52608 :     transition_start = (int16_t) roundf( FFT_FILTER_WND_FLAT_REGION * fft_hist_size );
    1157       52608 :     transition_length = (int16_t) roundf( FFT_FILTER_WND_TRANS_REGION * fft_hist_size );
    1158             : 
    1159             :     /* Compute the window used for FFT filters */
    1160       52608 :     ivas_reverb_define_window_fft( pTime_window, transition_start, transition_length, nr_fc_fft_filter );
    1161             : 
    1162             :     /* === Copy parameters from ivas_reverb_params_t into DSP blocks   === */
    1163             :     /* === to be used for subsequent audio signal processing           === */
    1164       52608 :     if ( *hReverb == NULL )
    1165             :     {
    1166       12692 :         pState->do_corr_filter = params.do_corr_filter;
    1167             : 
    1168             :         /* clear & init jot reverb fft filters */
    1169       12692 :         if ( ( error = initialize_reverb_filters( pState ) ) != IVAS_ERR_OK )
    1170             :         {
    1171           0 :             return error;
    1172             :         }
    1173             :     }
    1174             : 
    1175       52608 :     if ( pState->do_corr_filter )
    1176             :     {
    1177             :         /* Computing correlation filters on the basis of target IA coherence */
    1178       52608 :         ivas_reverb_calc_correl_filters( params.pHrtf_inter_aural_coherence_const, pTime_window, pState->fft_size, 0.0f, pFft_wf_filter_ch0, pFft_wf_filter_ch1 );
    1179             : 
    1180             :         /* Copying the computed FFT correlation filters to the fft_filter components */
    1181       52608 :         if ( ( error = set_correl_fft_filter( pState, 0, pFft_wf_filter_ch0 ) ) != IVAS_ERR_OK )
    1182             :         {
    1183           0 :             return error;
    1184             :         }
    1185             : 
    1186       52608 :         if ( ( error = set_correl_fft_filter( pState, 1, pFft_wf_filter_ch1 ) ) != IVAS_ERR_OK )
    1187             :         {
    1188           0 :             return error;
    1189             :         }
    1190             :     }
    1191             : 
    1192             :     /* Computing coloration filters on the basis of target responses */
    1193       52608 :     ivas_reverb_calc_color_filters( pColor_target_l, pColor_target_r, pTime_window, pState->fft_size, 0.0f, pFft_wf_filter_ch0, pFft_wf_filter_ch1 );
    1194             : 
    1195             :     /* Copying the computed FFT colorations filters to the fft_filter components */
    1196       52608 :     if ( ( error = set_color_fft_filter( pState, 0, pFft_wf_filter_ch0 ) ) != IVAS_ERR_OK )
    1197             :     {
    1198           0 :         return error;
    1199             :     }
    1200             : 
    1201       52608 :     if ( ( error = set_color_fft_filter( pState, 1, pFft_wf_filter_ch1 ) ) != IVAS_ERR_OK )
    1202             :     {
    1203           0 :         return error;
    1204             :     }
    1205             : 
    1206       52608 :     if ( *hReverb == NULL )
    1207             :     {
    1208             :         /* init predelay */
    1209       12692 :         ivas_rev_delay_line_init( &( pState->predelay_line ), pState->pPredelay_buffer, params.pre_delay, predelay_bf_len );
    1210             : 
    1211             :         /* set up feedback delay network */
    1212       12692 :         if ( ( error = setup_FDN_branches( pState, &params ) ) != IVAS_ERR_OK )
    1213             :         {
    1214           0 :             return error;
    1215             :         }
    1216             :     }
    1217             :     else
    1218             :     {
    1219       39916 :         pState->predelay_line.Delay = params.pre_delay;
    1220             :     }
    1221             : 
    1222       52608 :     nr_coefs = params.t60_filter_order + 1;
    1223             : 
    1224      473472 :     for ( branch_idx = 0; branch_idx < params.nr_loops; branch_idx++ )
    1225             :     {
    1226      420864 :         pCoef_a = &params.pT60_filter_coeff[2 * nr_coefs * branch_idx + nr_coefs];
    1227      420864 :         pCoef_b = &params.pT60_filter_coeff[2 * nr_coefs * branch_idx];
    1228             : 
    1229      420864 :         if ( ( error = set_t60_filter( pState, branch_idx, nr_coefs, pCoef_a, pCoef_b ) ) != IVAS_ERR_OK )
    1230             :         {
    1231           0 :             return error;
    1232             :         }
    1233             :     }
    1234             : 
    1235       52608 :     *hReverb = pState;
    1236             : 
    1237       52608 :     return IVAS_ERR_OK;
    1238             : }
    1239             : 
    1240             : 
    1241             : /*-------------------------------------------------------------------------
    1242             :  * ivas_reverb_close()
    1243             :  *
    1244             :  * Deallocate Crend reverberation handle
    1245             :  *------------------------------------------------------------------------*/
    1246             : 
    1247      193614 : void ivas_reverb_close(
    1248             :     REVERB_HANDLE *hReverb_in /* i/o: Reverberator handle       */
    1249             : )
    1250             : {
    1251             :     REVERB_HANDLE hReverb;
    1252             :     int16_t loop_idx;
    1253             : 
    1254      193614 :     hReverb = *hReverb_in;
    1255             : 
    1256      193614 :     if ( hReverb_in == NULL || *hReverb_in == NULL )
    1257             :     {
    1258      180922 :         return;
    1259             :     }
    1260             : 
    1261      114228 :     for ( loop_idx = 0; loop_idx < IVAS_REV_MAX_NR_BRANCHES; loop_idx++ )
    1262             :     {
    1263      101536 :         if ( hReverb->loop_delay_buffer[loop_idx] != NULL )
    1264             :         {
    1265      101536 :             free( hReverb->loop_delay_buffer[loop_idx] );
    1266      101536 :             hReverb->loop_delay_buffer[loop_idx] = NULL;
    1267             :         }
    1268             :     }
    1269             : 
    1270       12692 :     free( hReverb->pPredelay_buffer );
    1271       12692 :     hReverb->pPredelay_buffer = NULL;
    1272             : 
    1273       12692 :     free( *hReverb_in );
    1274       12692 :     *hReverb_in = NULL;
    1275             : 
    1276       12692 :     return;
    1277             : }
    1278             : 
    1279             : 
    1280             : /*-----------------------------------------------------------------------------------------*
    1281             :  * Function post_fft_filter()
    1282             :  *
    1283             :  *
    1284             :  *-----------------------------------------------------------------------------------------*/
    1285             : 
    1286    87962834 : static void post_fft_filter(
    1287             :     REVERB_HANDLE hReverb,
    1288             :     float *p0,
    1289             :     float *p1,
    1290             :     float *pBuffer_0,
    1291             :     float *pBuffer_1 )
    1292             : {
    1293    87962834 :     if ( hReverb->do_corr_filter )
    1294             :     {
    1295    87962834 :         ivas_reverb_t2f_f2t_in( &hReverb->fft_filter_ols, p0, p1, pBuffer_0, pBuffer_1 );
    1296    87962834 :         ivas_reverb_fft_filter_ComplexMul( &hReverb->fft_filter_correl_0, pBuffer_0 );
    1297    87962834 :         ivas_reverb_fft_filter_ComplexMul( &hReverb->fft_filter_correl_1, pBuffer_1 );
    1298    87962834 :         ivas_reverb_fft_filter_CrossMix( pBuffer_0, pBuffer_1, hReverb->fft_filter_correl_0.fft_size );
    1299             :     }
    1300             :     else
    1301             :     {
    1302           0 :         ivas_reverb_t2f_f2t_in( &hReverb->fft_filter_ols, p0, p1, pBuffer_0, pBuffer_1 );
    1303             :     }
    1304             : 
    1305    87962834 :     ivas_reverb_fft_filter_ComplexMul( &hReverb->fft_filter_color_0, pBuffer_0 );
    1306    87962834 :     ivas_reverb_fft_filter_ComplexMul( &hReverb->fft_filter_color_1, pBuffer_1 );
    1307    87962834 :     ivas_reverb_t2f_f2t_out( &hReverb->fft_filter_ols, pBuffer_0, pBuffer_1, p0, p1 );
    1308             : 
    1309    87962834 :     return;
    1310             : }
    1311             : 
    1312             : 
    1313             : /*-----------------------------------------------------------------------------------------*
    1314             :  * Function reverb_block()
    1315             :  *
    1316             :  * Input a block (mono) and calculate the 2 output blocks.
    1317             :  *-----------------------------------------------------------------------------------------*/
    1318             : 
    1319    87962834 : static void reverb_block(
    1320             :     REVERB_HANDLE hReverb,
    1321             :     float *pInput,
    1322             :     float *pOut0,
    1323             :     float *pOut1 )
    1324             : 
    1325             : {
    1326    87962834 :     uint16_t nr_branches = hReverb->nr_of_branches;
    1327    87962834 :     uint16_t bsize = hReverb->full_block_size;
    1328    87962834 :     uint16_t inner_bsize = INNER_BLK_SIZE;
    1329             :     uint16_t i, j, k, ns, branch_idx, blk_idx, start_sample_idx;
    1330             : 
    1331             :     float *pFFT_buf[2], FFT_buf_1[RV_FILTER_MAX_FFT_SIZE], FFT_buf_2[RV_FILTER_MAX_FFT_SIZE];
    1332             :     float pFeedback_input[INNER_BLK_SIZE];
    1333             :     float pTemp[INNER_BLK_SIZE];
    1334             :     float *ppOutput[IVAS_REV_MAX_NR_BRANCHES];
    1335             :     float Output[IVAS_REV_MAX_NR_BRANCHES][INNER_BLK_SIZE];
    1336             : 
    1337    87962834 :     pFFT_buf[0] = &FFT_buf_1[0];
    1338    87962834 :     pFFT_buf[1] = &FFT_buf_2[0];
    1339             : 
    1340   791665506 :     for ( branch_idx = 0; branch_idx < nr_branches; branch_idx++ )
    1341             :     {
    1342   703702672 :         ppOutput[branch_idx] = (float *) Output + branch_idx * inner_bsize;
    1343             :     }
    1344             : 
    1345   268094773 :     for ( k = 0; k < bsize; k += inner_bsize )
    1346             :     {
    1347   180131939 :         float *pO0 = &pOut0[k];
    1348   180131939 :         float *pO1 = &pOut1[k];
    1349 14590687059 :         for ( i = 0; i < inner_bsize; i++ )
    1350             :         {
    1351 14410555120 :             pO0[i] = 0.0f;
    1352 14410555120 :             pO1[i] = 0.0f;
    1353             :         }
    1354             : 
    1355             :         /* feedback network: */
    1356  1621187451 :         for ( i = 0; i < nr_branches; i++ )
    1357             :         {
    1358  1441055512 :             float *pOutput_i = &ppOutput[i][0];
    1359  1441055512 :             float mixer_0_i = hReverb->mixer[0][i];
    1360  1441055512 :             float mixer_1_i = hReverb->mixer[1][i];
    1361             : 
    1362             :             /* output and feedback are same, get sample from delay line ... */
    1363  1441055512 :             ivas_rev_delay_line_get_sample_blk( &( hReverb->delay_line[i] ), inner_bsize, pTemp );
    1364  1441055512 :             ivas_reverb_iir_filt_2taps_feed_blk( &( hReverb->t60[i] ), inner_bsize, pTemp, ppOutput[i] );
    1365 >11672*10^7 :             for ( ns = 0; ns < inner_bsize; ns++ )
    1366             :             {
    1367 >11528*10^7 :                 pO0[ns] += pOutput_i[ns] * mixer_0_i; /* mixer ch 0 */
    1368 >11528*10^7 :                 pO1[ns] += pOutput_i[ns] * mixer_1_i; /* mixer ch 1 */
    1369             :             }
    1370             :         }
    1371             : 
    1372  1621187451 :         for ( i = 0; i < nr_branches; i++ )
    1373             :         {
    1374  1441055512 :             float *pIn = &pInput[k];
    1375             : 
    1376 >11672*10^7 :             for ( ns = 0; ns < inner_bsize; ns++ )
    1377             :             {
    1378 >11528*10^7 :                 pFeedback_input[ns] = pIn[ns];
    1379             :             }
    1380             : 
    1381 12969499608 :             for ( j = 0; j < nr_branches; j++ )
    1382             :             {
    1383 11528444096 :                 float gain_matrix_j_i = hReverb->gain_matrix[j][i];
    1384 11528444096 :                 float *pOutput = &ppOutput[j][0];
    1385 >93380*10^7 :                 for ( ns = 0; ns < inner_bsize; ns++ )
    1386             :                 {
    1387 >92227*10^7 :                     pFeedback_input[ns] += gain_matrix_j_i * pOutput[ns];
    1388             :                 }
    1389             :             }
    1390             : 
    1391  1441055512 :             ivas_rev_delay_line_feed_sample_blk( &( hReverb->delay_line[i] ), inner_bsize, pFeedback_input );
    1392             :         }
    1393             :     }
    1394             : 
    1395             :     /* Applying FFT filter to each sub-frame */
    1396   175925668 :     for ( blk_idx = 0; blk_idx < hReverb->num_fft_subblocks; blk_idx++ )
    1397             :     {
    1398    87962834 :         start_sample_idx = blk_idx * hReverb->fft_subblock_size;
    1399    87962834 :         post_fft_filter( hReverb, pOut0 + start_sample_idx, pOut1 + start_sample_idx, pFFT_buf[0], pFFT_buf[1] );
    1400             :     }
    1401             : 
    1402    87962834 :     return;
    1403             : }
    1404             : 
    1405             : 
    1406             : /*-----------------------------------------------------------------------------------------*
    1407             :  * Function downmix_input_block()
    1408             :  *
    1409             :  * Downmix input to mono, taking also DSR gain into account
    1410             :  *-----------------------------------------------------------------------------------------*/
    1411             : 
    1412    87962834 : static ivas_error downmix_input_block(
    1413             :     const REVERB_HANDLE hReverb,
    1414             :     float *pcm_in[],
    1415             :     const AUDIO_CONFIG input_audio_config,
    1416             :     float *pPcm_out,
    1417             :     const int16_t input_offset )
    1418             : {
    1419             :     int16_t i, s, nchan_transport;
    1420    87962834 :     float dmx_gain = hReverb->dmx_gain;
    1421             : 
    1422    87962834 :     switch ( input_audio_config )
    1423             :     {
    1424    69661313 :         case IVAS_AUDIO_CONFIG_STEREO:
    1425             :         case IVAS_AUDIO_CONFIG_5_1:
    1426             :         case IVAS_AUDIO_CONFIG_7_1:
    1427             :         case IVAS_AUDIO_CONFIG_5_1_2:
    1428             :         case IVAS_AUDIO_CONFIG_5_1_4:
    1429             :         case IVAS_AUDIO_CONFIG_7_1_4:
    1430             :         case IVAS_AUDIO_CONFIG_ISM1:
    1431             :         case IVAS_AUDIO_CONFIG_ISM2:
    1432             :         case IVAS_AUDIO_CONFIG_ISM3:
    1433             :         case IVAS_AUDIO_CONFIG_ISM4:
    1434             :         {
    1435    69661313 :             nchan_transport = audioCfg2channels( input_audio_config );
    1436 11416654913 :             for ( s = 0; s < hReverb->full_block_size; s++ )
    1437             :             {
    1438 11346993600 :                 float temp = pcm_in[0][input_offset + s];
    1439 23429713120 :                 for ( i = 1; i < nchan_transport; i++ )
    1440             :                 {
    1441 12082719520 :                     temp += pcm_in[i][input_offset + s];
    1442             :                 }
    1443 11346993600 :                 pPcm_out[s] = dmx_gain * temp;
    1444             :             }
    1445    69661313 :             break;
    1446             :         }
    1447    18301521 :         case IVAS_AUDIO_CONFIG_MONO: /* ~'ZOA_1' */
    1448             :         case IVAS_AUDIO_CONFIG_FOA:
    1449             :         case IVAS_AUDIO_CONFIG_HOA2:
    1450             :         case IVAS_AUDIO_CONFIG_HOA3:
    1451             :         {
    1452  3081863041 :             for ( s = 0; s < hReverb->full_block_size; s++ )
    1453             :             {
    1454  3063561520 :                 pPcm_out[s] = dmx_gain * pcm_in[0][input_offset + s];
    1455             :             }
    1456    18301521 :             break;
    1457             :         }
    1458           0 :         default:
    1459           0 :             return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unsupported input format for reverb" );
    1460             :             break;
    1461             :     }
    1462             : 
    1463    87962834 :     return IVAS_ERR_OK;
    1464             : }
    1465             : 
    1466             : 
    1467             : /*-----------------------------------------------------------------------------------------*
    1468             :  * Function predelay_block()
    1469             :  *
    1470             :  * Perform a predelay
    1471             :  *-----------------------------------------------------------------------------------------*/
    1472             : 
    1473    87962834 : static void predelay_block(
    1474             :     const REVERB_HANDLE hReverb,
    1475             :     float *pInput,
    1476             :     float *pOutput )
    1477             : {
    1478             :     uint16_t i, idx, n_samples, blk_size;
    1479    87962834 :     uint16_t max_blk_size = (uint16_t) hReverb->predelay_line.Delay;
    1480             : 
    1481    87962834 :     if ( max_blk_size < 2 )
    1482             :     {
    1483      939323 :         if ( max_blk_size == 0 ) /* zero-length delay line: just copy the data from input to output */
    1484             :         {
    1485   185452683 :             for ( i = 0; i < hReverb->full_block_size; i++ )
    1486             :             {
    1487   184513360 :                 pOutput[i] = pInput[i];
    1488             :             }
    1489             :         }
    1490             :         else /* 1-sample length delay line: feed the data sample-by-sample */
    1491             :         {
    1492           0 :             for ( i = 0; i < hReverb->full_block_size; i++ )
    1493             :             {
    1494           0 :                 pOutput[i] = ivas_rev_delay_line_get_sample( &( hReverb->predelay_line ) );
    1495           0 :                 ivas_rev_delay_line_feed_sample( &( hReverb->predelay_line ), pInput[i] );
    1496             :             }
    1497             :         }
    1498             :     }
    1499             :     else /* multiple-sample length delay line: use block processing */
    1500             :     {
    1501    87023511 :         idx = 0;
    1502    87023511 :         n_samples = hReverb->full_block_size;
    1503   521750634 :         while ( n_samples > 0 )
    1504             :         {
    1505   434727123 :             blk_size = n_samples;
    1506   434727123 :             if ( blk_size > max_blk_size )
    1507             :             {
    1508   347703612 :                 blk_size = max_blk_size;
    1509             :             }
    1510   434727123 :             ivas_rev_delay_line_get_sample_blk( &( hReverb->predelay_line ), blk_size, &pOutput[idx] );
    1511   434727123 :             ivas_rev_delay_line_feed_sample_blk( &( hReverb->predelay_line ), blk_size, &pInput[idx] );
    1512   434727123 :             idx += blk_size;
    1513   434727123 :             n_samples -= blk_size;
    1514             :         }
    1515             :     }
    1516             : 
    1517    87962834 :     return;
    1518             : }
    1519             : 
    1520             : 
    1521             : /*-----------------------------------------------------------------------------------------*
    1522             :  * Function mix_output_block()
    1523             :  *
    1524             :  * mix one block of *pInL and *pInR samples into *pOutL and *pOutL respectively
    1525             :  *-----------------------------------------------------------------------------------------*/
    1526             : 
    1527    25144598 : static void mix_output_block(
    1528             :     const REVERB_HANDLE hReverb,
    1529             :     const float *pInL,
    1530             :     const float *pInR,
    1531             :     float *pOutL,
    1532             :     float *pOutR )
    1533             : {
    1534             :     uint16_t i;
    1535             : 
    1536  4247705558 :     for ( i = 0; i < hReverb->full_block_size; i++ )
    1537             :     {
    1538  4222560960 :         pOutL[i] += pInL[i];
    1539  4222560960 :         pOutR[i] += pInR[i];
    1540             :     }
    1541             : 
    1542    25144598 :     return;
    1543             : }
    1544             : 
    1545             : 
    1546             : /*-----------------------------------------------------------------------------------------*
    1547             :  * ivas_reverb_process()
    1548             :  *
    1549             :  * Process the input PCM audio into output PCM audio, applying reverb
    1550             :  *-----------------------------------------------------------------------------------------*/
    1551             : 
    1552    87962834 : ivas_error ivas_reverb_process(
    1553             :     const REVERB_HANDLE hReverb,           /* i  : Reverberator handle                */
    1554             :     const AUDIO_CONFIG input_audio_config, /* i  : reverb. input audio configuration  */
    1555             :     const int16_t mix_signals,             /* i  : add reverb to output signal        */
    1556             :     float *pcm_in[],                       /* i  : the PCM audio to apply reverb on   */
    1557             :     float *pcm_out[],                      /* o  : the PCM audio with reverb applied  */
    1558             :     const int16_t i_ts                     /* i  : subframe index                     */
    1559             : )
    1560             : {
    1561             :     float tmp0[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp1[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp2[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES];
    1562             :     ivas_error error;
    1563             : 
    1564    87962834 :     if ( ( error = downmix_input_block( hReverb, pcm_in, input_audio_config, tmp1, i_ts * hReverb->full_block_size ) ) != IVAS_ERR_OK )
    1565             :     {
    1566           0 :         return error;
    1567             :     }
    1568             : 
    1569    87962834 :     predelay_block( hReverb, tmp1, tmp0 );
    1570             : 
    1571    87962834 :     reverb_block( hReverb, tmp0, tmp1, tmp2 );
    1572             : 
    1573    87962834 :     if ( mix_signals )
    1574             :     {
    1575    25144598 :         mix_output_block( hReverb, tmp1, tmp2, &pcm_out[0][i_ts * hReverb->full_block_size], &pcm_out[1][i_ts * hReverb->full_block_size] );
    1576             :     }
    1577             :     else
    1578             :     {
    1579    62818236 :         mvr2r( tmp1, &pcm_out[0][i_ts * hReverb->full_block_size], hReverb->full_block_size );
    1580    62818236 :         mvr2r( tmp2, &pcm_out[1][i_ts * hReverb->full_block_size], hReverb->full_block_size );
    1581             :     }
    1582             : 
    1583    87962834 :     return IVAS_ERR_OK;
    1584             : }
    1585             : 
    1586             : 
    1587             : /*-------------------------------------------------------------------------
    1588             :  * ivas_binaural_reverb_processSubFrame()
    1589             :  *
    1590             :  * Compute the reverberation - room effect
    1591             :  *------------------------------------------------------------------------*/
    1592             : 
    1593    21747994 : void ivas_binaural_reverb_processSubframe(
    1594             :     REVERB_STRUCT_HANDLE hReverb,                                     /* i/o: binaural reverb handle      */
    1595             :     const int16_t numInChannels,                                      /* i  : num inputs to be processed  */
    1596             :     const int16_t numSlots,                                           /* i  : number of slots to be processed    */
    1597             :     float inReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],  /* i  : input CLDFB data real, Comment: This change swaps two first dimensions as first dimension is not constant. */
    1598             :     float inImag[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],  /* i  : input CLDFB data imag       */
    1599             :     float outReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o  : output CLDFB data real      */
    1600             :     float outImag[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]  /* o  : output CLDFB data imag      */
    1601             : )
    1602             : {
    1603             :     /* Declare the required variables */
    1604             :     int16_t idx, bin, ch, sample, invertSampleIndex, tapIdx, *phaseShiftTypePr;
    1605             :     float **tapRealPr, **tapImagPr;
    1606    21747994 :     push_wmops( "binaural_reverb" );
    1607             : 
    1608             :     /* 1) Rotate the data in the loop buffer of the reverberator.
    1609             :      * Notice that the audio at the loop buffers is at time-inverted order
    1610             :      * for convolution purposes later on. */
    1611   959171864 :     for ( bin = 0; bin < hReverb->numBins; bin++ )
    1612             :     {
    1613             :         /* Move the data forwards by blockSize (i.e. by the frame size of 16 CLDFB slots) */
    1614   937423870 :         mvr2r( hReverb->loopBufReal[bin], hReverb->loopBufReal[bin] + numSlots, hReverb->loopBufLength[bin] );
    1615   937423870 :         mvr2r( hReverb->loopBufImag[bin], hReverb->loopBufImag[bin] + numSlots, hReverb->loopBufLength[bin] );
    1616             : 
    1617             :         /* Add the data from the end of the loop to the beginning, with an attenuation factor
    1618             :          * according to RT60. This procedure generates an IIR decaying response. The response
    1619             :          * is decorrelated later on. */
    1620   937423870 :         v_multc( hReverb->loopBufReal[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor[bin], hReverb->loopBufReal[bin], numSlots );
    1621   937423870 :         v_multc( hReverb->loopBufImag[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor[bin], hReverb->loopBufImag[bin], numSlots );
    1622             :     }
    1623             : 
    1624             :     /* 2) Apply the determined pre-delay to the input audio, and add the delayed audio to the loop. */
    1625    21747994 :     idx = hReverb->preDelayBufferIndex;
    1626   108551903 :     for ( sample = 0; sample < numSlots; sample++ )
    1627             :     {
    1628    86803909 :         invertSampleIndex = numSlots - sample - 1;
    1629             : 
    1630  3827231689 :         for ( bin = 0; bin < hReverb->numBins; bin++ )
    1631             :         {
    1632             :             /* Add from pre-delay buffer a sample to the loop buffer, in a time-inverted order.
    1633             :              * Also apply the spectral gains determined for the reverberation */
    1634  3740427780 :             hReverb->loopBufReal[bin][invertSampleIndex] += hReverb->preDelayBufferReal[idx][bin] * hReverb->reverbEqGains[bin];
    1635  3740427780 :             hReverb->loopBufImag[bin][invertSampleIndex] += hReverb->preDelayBufferImag[idx][bin] * hReverb->reverbEqGains[bin];
    1636  3740427780 :             hReverb->preDelayBufferReal[idx][bin] = 0.0f;
    1637  3740427780 :             hReverb->preDelayBufferImag[idx][bin] = 0.0f;
    1638             :         }
    1639             : 
    1640             :         /* Add every second input channel as is to the pre-delay buffer, and every second input channel with
    1641             :          * 90 degrees phase shift to reduce energy imbalances between coherent and incoherent sounds */
    1642   265326099 :         for ( ch = 0; ch < numInChannels; ch++ )
    1643             :         {
    1644   178522190 :             if ( ch % 2 )
    1645             :             {
    1646    88116997 :                 v_add( hReverb->preDelayBufferReal[idx], inReal[ch][sample], hReverb->preDelayBufferReal[idx], hReverb->numBins );
    1647    88116997 :                 v_add( hReverb->preDelayBufferImag[idx], inImag[ch][sample], hReverb->preDelayBufferImag[idx], hReverb->numBins );
    1648             :             }
    1649             :             else
    1650             :             {
    1651    90405193 :                 v_sub( hReverb->preDelayBufferReal[idx], inImag[ch][sample], hReverb->preDelayBufferReal[idx], hReverb->numBins );
    1652    90405193 :                 v_add( hReverb->preDelayBufferImag[idx], inReal[ch][sample], hReverb->preDelayBufferImag[idx], hReverb->numBins );
    1653             :             }
    1654             :         }
    1655    86803909 :         idx = ( idx + 1 ) % hReverb->preDelayBufferLength;
    1656             :     }
    1657    21747994 :     hReverb->preDelayBufferIndex = idx;
    1658             : 
    1659             :     /* 3) Perform the filtering/decorrelating, using complex and sparse FIR filtering */
    1660   959171864 :     for ( bin = 0; bin < hReverb->numBins; bin++ )
    1661             :     {
    1662  2812271610 :         for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1663             :         {
    1664             :             /* These tap pointers have been determined to point to the loop buffer at sparse locations */
    1665  1874847740 :             tapRealPr = hReverb->tapPointersReal[bin][ch];
    1666  1874847740 :             tapImagPr = hReverb->tapPointersImag[bin][ch];
    1667             : 
    1668  1874847740 :             phaseShiftTypePr = hReverb->tapPhaseShiftType[bin][ch];
    1669             : 
    1670             :             /* Flush output */
    1671  1874847740 :             set_f( hReverb->outputBufferReal[bin][ch], 0.0f, numSlots );
    1672  1874847740 :             set_f( hReverb->outputBufferImag[bin][ch], 0.0f, numSlots );
    1673             : 
    1674             :             /* Add from temporally decaying sparse tap locations the audio to the output. */
    1675 41746244548 :             for ( tapIdx = 0; tapIdx < hReverb->taps[bin][ch]; tapIdx++ )
    1676             :             {
    1677 39871396808 :                 switch ( phaseShiftTypePr[tapIdx] )
    1678             :                 {
    1679  9750652268 :                     case 0: /* 0 degrees phase */
    1680  9750652268 :                         v_add( hReverb->outputBufferReal[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferReal[bin][ch], numSlots );
    1681  9750652268 :                         v_add( hReverb->outputBufferImag[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferImag[bin][ch], numSlots );
    1682  9750652268 :                         break;
    1683 10451484932 :                     case 1: /* 90 degrees phase */
    1684 10451484932 :                         v_sub( hReverb->outputBufferReal[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferReal[bin][ch], numSlots );
    1685 10451484932 :                         v_add( hReverb->outputBufferImag[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferImag[bin][ch], numSlots );
    1686 10451484932 :                         break;
    1687 10030681420 :                     case 2: /* 180 degrees phase */
    1688 10030681420 :                         v_sub( hReverb->outputBufferReal[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferReal[bin][ch], numSlots );
    1689 10030681420 :                         v_sub( hReverb->outputBufferImag[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferImag[bin][ch], numSlots );
    1690 10030681420 :                         break;
    1691  9638578188 :                     default: /* 270 degrees phase */
    1692  9638578188 :                         v_add( hReverb->outputBufferReal[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferReal[bin][ch], numSlots );
    1693  9638578188 :                         v_sub( hReverb->outputBufferImag[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferImag[bin][ch], numSlots );
    1694  9638578188 :                         break;
    1695             :                 }
    1696             :             }
    1697             :         }
    1698             : 
    1699             :         /* Generate diffuse field binaural coherence by mixing the incoherent reverberated channels with pre-defined gains */
    1700   937423870 :         if ( bin <= hReverb->highestBinauralCoherenceBin )
    1701             :         {
    1702   150316343 :             if ( hReverb->useBinauralCoherence )
    1703             :             {
    1704   750272452 :                 for ( sample = 0; sample < numSlots; sample++ )
    1705             :                 {
    1706             :                     float leftRe, rightRe, leftIm, rightIm;
    1707             : 
    1708   599956109 :                     leftRe = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferReal[bin][0][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferReal[bin][1][sample];
    1709   599956109 :                     rightRe = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferReal[bin][1][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferReal[bin][0][sample];
    1710   599956109 :                     leftIm = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferImag[bin][0][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferImag[bin][1][sample];
    1711   599956109 :                     rightIm = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferImag[bin][1][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferImag[bin][0][sample];
    1712             : 
    1713   599956109 :                     hReverb->outputBufferReal[bin][0][sample] = leftRe;
    1714   599956109 :                     hReverb->outputBufferReal[bin][1][sample] = rightRe;
    1715   599956109 :                     hReverb->outputBufferImag[bin][0][sample] = leftIm;
    1716   599956109 :                     hReverb->outputBufferImag[bin][1][sample] = rightIm;
    1717             :                 }
    1718             :             }
    1719             :         }
    1720             :     }
    1721             : 
    1722             :     /* 4) Write data to output */
    1723    65243982 :     for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1724             :     {
    1725   217103806 :         for ( sample = 0; sample < numSlots; sample++ )
    1726             :         {
    1727             :             /* Audio was in the temporally inverted order for convolution, re-invert audio to output */
    1728   173607818 :             invertSampleIndex = numSlots - sample - 1;
    1729             : 
    1730  7654463378 :             for ( bin = 0; bin < hReverb->numBins; bin++ )
    1731             :             {
    1732  7480855560 :                 outReal[ch][sample][bin] = hReverb->outputBufferReal[bin][ch][invertSampleIndex];
    1733  7480855560 :                 outImag[ch][sample][bin] = hReverb->outputBufferImag[bin][ch][invertSampleIndex];
    1734             :             }
    1735  3109221338 :             for ( ; bin < CLDFB_NO_CHANNELS_MAX; bin++ )
    1736             :             {
    1737  2935613520 :                 outReal[ch][sample][bin] = 0.0f;
    1738  2935613520 :                 outImag[ch][sample][bin] = 0.0f;
    1739             :             }
    1740             :         }
    1741             :     }
    1742             : 
    1743    21747994 :     pop_wmops();
    1744    21747994 :     return;
    1745             : }
    1746             : 
    1747             : 
    1748             : /*-------------------------------------------------------------------------
    1749             :  * ivas_binaural_reverb_open()
    1750             :  *
    1751             :  * Allocate and initialize binaural room reverberator handle
    1752             :  *------------------------------------------------------------------------*/
    1753             : 
    1754       32899 : static ivas_error ivas_binaural_reverb_open(
    1755             :     REVERB_STRUCT_HANDLE *hReverbPr,     /* i/o: binaural reverb handle                                  */
    1756             :     const int16_t numBins,               /* i  : number of CLDFB bins                                    */
    1757             :     const int16_t numCldfbSlotsPerFrame, /* i  : number of CLDFB slots per frame                         */
    1758             :     const int32_t sampling_rate,         /* i  : sampling rate                                           */
    1759             :     const float *revTimes,               /* i  : reverberation times T60 for each CLDFB bin in seconds   */
    1760             :     const float *revEnes,                /* i  : spectrum for reverberated sound at each CLDFB bin       */
    1761             :     const int16_t preDelay               /* i  : reverb pre-delay in CLDFB slots                         */
    1762             : )
    1763             : {
    1764             :     int16_t bin, chIdx, k, len;
    1765             :     REVERB_STRUCT_HANDLE hReverb;
    1766             : 
    1767       32899 :     if ( ( *hReverbPr = (REVERB_STRUCT_HANDLE) malloc( sizeof( REVERB_STRUCT ) ) ) == NULL )
    1768             :     {
    1769           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    1770             :     }
    1771             : 
    1772       32899 :     hReverb = *hReverbPr;
    1773             : 
    1774       32899 :     hReverb->useBinauralCoherence = 1;
    1775       32899 :     hReverb->preDelayBufferLength = 1;
    1776       32899 :     hReverb->preDelayBufferIndex = 0;
    1777             : 
    1778       32899 :     hReverb->numBins = numBins;
    1779       32899 :     hReverb->blockSize = numCldfbSlotsPerFrame;
    1780             : 
    1781      723778 :     for ( k = 0; k < IVAS_REVERB_PREDELAY_MAX + 1; k++ )
    1782             :     {
    1783      690879 :         set_f( hReverb->preDelayBufferReal[k], 0.0f, hReverb->numBins );
    1784      690879 :         set_f( hReverb->preDelayBufferImag[k], 0.0f, hReverb->numBins );
    1785             :     }
    1786             : 
    1787     1362609 :     for ( bin = 0; bin < hReverb->numBins; bin++ )
    1788             :     {
    1789             :         /* Loop Buffer */
    1790     1329710 :         hReverb->loopBufLengthMax[bin] = (int16_t) ( 500 / ( 1 + bin ) + ( CLDFB_NO_CHANNELS_MAX - bin ) );
    1791             : 
    1792     1329710 :         len = hReverb->loopBufLengthMax[bin] + hReverb->blockSize;
    1793     1329710 :         if ( ( hReverb->loopBufReal[bin] = (float *) malloc( len * sizeof( float ) ) ) == NULL )
    1794             :         {
    1795           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    1796             :         }
    1797             : 
    1798     1329710 :         if ( ( hReverb->loopBufImag[bin] = (float *) malloc( len * sizeof( float ) ) ) == NULL )
    1799             :         {
    1800           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    1801             :         }
    1802             : 
    1803     1329710 :         set_f( hReverb->loopBufReal[bin], 0.0f, len );
    1804     1329710 :         set_f( hReverb->loopBufImag[bin], 0.0f, len );
    1805             : 
    1806             :         /* Determine loop buffer length. The following formula is manually tuned to generate sufficiently long
    1807             :          * but not excessively long loops to generate reverberation. */
    1808             :         /* Note: the resulted length is very sensitive to the precision of the constants below (e.g. 1.45 vs. 1.45f) */
    1809     1329710 :         hReverb->loopBufLength[bin] = (int16_t) ( 1.45 * (int16_t) ( revTimes[bin] * 150.0 ) + 1 );
    1810     1329710 :         hReverb->loopBufLength[bin] = min( hReverb->loopBufLength[bin], hReverb->loopBufLengthMax[bin] );
    1811             : 
    1812             :         /* Sparse Filter Tap Locations */
    1813     3989130 :         for ( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ )
    1814             :         {
    1815     2659420 :             len = hReverb->loopBufLength[bin];
    1816             : 
    1817     2659420 :             if ( ( hReverb->tapPhaseShiftType[bin][chIdx] = (int16_t *) malloc( len * sizeof( int16_t ) ) ) == NULL )
    1818             :             {
    1819           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    1820             :             }
    1821     2659420 :             set_s( hReverb->tapPhaseShiftType[bin][chIdx], 0, len );
    1822             : 
    1823     2659420 :             if ( ( hReverb->tapPointersReal[bin][chIdx] = (float **) malloc( len * sizeof( float * ) ) ) == NULL )
    1824             :             {
    1825           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    1826             :             }
    1827             : 
    1828     2659420 :             if ( ( hReverb->tapPointersImag[bin][chIdx] = (float **) malloc( len * sizeof( float * ) ) ) == NULL )
    1829             :             {
    1830           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    1831             :             }
    1832             : 
    1833     2659420 :             len = hReverb->blockSize;
    1834     2659420 :             if ( ( hReverb->outputBufferReal[bin][chIdx] = (float *) malloc( len * sizeof( float ) ) ) == NULL )
    1835             :             {
    1836           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    1837             :             }
    1838             : 
    1839     2659420 :             if ( ( hReverb->outputBufferImag[bin][chIdx] = (float *) malloc( len * sizeof( float ) ) ) == NULL )
    1840             :             {
    1841           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    1842             :             }
    1843             : 
    1844     2659420 :             set_f( hReverb->outputBufferReal[bin][chIdx], 0.0f, len );
    1845     2659420 :             set_f( hReverb->outputBufferImag[bin][chIdx], 0.0f, len );
    1846             :         }
    1847             :     }
    1848             : 
    1849       32899 :     ivas_binaural_reverb_setReverbTimes( hReverb, sampling_rate, revTimes, revEnes );
    1850             : 
    1851       32899 :     ivas_binaural_reverb_setPreDelay( hReverb, preDelay );
    1852             : 
    1853       32899 :     return IVAS_ERR_OK;
    1854             : }
    1855             : 
    1856             : 
    1857             : /*-------------------------------------------------------------------------
    1858             :  * ivas_binaural_reverb_init()
    1859             :  *
    1860             :  * Initialize binaural room reverberator handle for FastConv renderer
    1861             :  *------------------------------------------------------------------------*/
    1862             : 
    1863       32899 : ivas_error ivas_binaural_reverb_init(
    1864             :     REVERB_STRUCT_HANDLE *hReverbPr,                      /* i/o: binaural reverb handle               */
    1865             :     const HRTFS_STATISTICS_HANDLE hHrtfStatistics,        /* i  : HRTF statistics handle               */
    1866             :     const int16_t numBins,                                /* i  : number of CLDFB bins                 */
    1867             :     const int16_t numCldfbSlotsPerFrame,                  /* i  : number of CLDFB slots per frame      */
    1868             :     const IVAS_ROOM_ACOUSTICS_CONFIG_DATA *roomAcoustics, /* i/o: room acoustics parameters            */
    1869             :     const int32_t sampling_rate,                          /* i  : sampling rate                        */
    1870             :     const float *defaultTimes,                            /* i  : default reverberation times          */
    1871             :     const float *defaultEne,                              /* i  : default reverberation energies       */
    1872             :     float *earlyEne                                       /* i/o: Early part energies to be modified   */
    1873             : )
    1874             : {
    1875             :     ivas_error error;
    1876             :     int16_t preDelay, bin;
    1877             :     float revTimes[CLDFB_NO_CHANNELS_MAX];
    1878             :     float revEne[CLDFB_NO_CHANNELS_MAX];
    1879             : 
    1880       32899 :     if ( roomAcoustics != NULL )
    1881             :     {
    1882       18206 :         if ( ( error = ivas_reverb_prepare_cldfb_params( roomAcoustics, hHrtfStatistics, sampling_rate, revTimes, revEne ) ) != IVAS_ERR_OK )
    1883             :         {
    1884           0 :             return error;
    1885             :         }
    1886             : 
    1887             :         /* Convert preDelay from seconds to CLDFB slots as needed by binaural reverb */
    1888       18206 :         preDelay = (int16_t) roundf( roomAcoustics->acousticPreDelay * CLDFB_SLOTS_PER_SECOND );
    1889             :     }
    1890             :     else
    1891             :     {
    1892      654253 :         for ( bin = 0; bin < numBins; bin++ )
    1893             :         {
    1894      639560 :             revTimes[bin] = defaultTimes[bin];
    1895      639560 :             revEne[bin] = defaultEne[bin];
    1896             :         }
    1897       14693 :         preDelay = 10;
    1898             :     }
    1899             : 
    1900     1362609 :     for ( bin = 0; bin < numBins; bin++ )
    1901             :     {
    1902             :         /* Adjust the room effect parameters when the reverberation time is less than a threshold value, to avoid
    1903             :            spectral artefacts with the synthetic reverberator. */
    1904     1329710 :         if ( revTimes[bin] < REV_TIME_THRESHOLD )
    1905             :         {
    1906             :             float adjustedEarlyEne, adjustedLateEne, adjustedRevTime;
    1907             :             float revTimeModifier, energyModifier;
    1908             : 
    1909             :             /* Adjust reverberation times, higher towards a threshold */
    1910      422674 :             revTimeModifier = fmaxf( 0.0f, 1.0f - ( revTimes[bin] / REV_TIME_THRESHOLD ) );
    1911      422674 :             adjustedRevTime = ( 1.0f - revTimeModifier ) * revTimes[bin];
    1912      422674 :             adjustedRevTime += revTimeModifier * ( revTimes[bin] + REV_TIME_THRESHOLD ) * 0.5f;
    1913      422674 :             energyModifier = ( adjustedRevTime - revTimes[bin] ) / adjustedRevTime;
    1914             : 
    1915             :             /* Adjust early and late energies, by moving late energy to early energy */
    1916      422674 :             if ( earlyEne != NULL )
    1917             :             {
    1918      326554 :                 adjustedEarlyEne = earlyEne[bin] + revEne[bin] * energyModifier;
    1919      326554 :                 earlyEne[bin] = adjustedEarlyEne; /* Store already here */
    1920             :             }
    1921             : 
    1922      422674 :             adjustedLateEne = revEne[bin] * ( 1.0f - energyModifier );
    1923             : 
    1924             :             /* Store adjusted room effect parameters to be used in reverb processing */
    1925      422674 :             revTimes[bin] = adjustedRevTime;
    1926      422674 :             revEne[bin] = adjustedLateEne;
    1927             :         }
    1928             :     }
    1929             : 
    1930       32899 :     error = ivas_binaural_reverb_open( hReverbPr, numBins, numCldfbSlotsPerFrame, sampling_rate, revTimes, revEne, preDelay );
    1931             : 
    1932       32899 :     return error;
    1933             : }
    1934             : 
    1935             : 
    1936             : /*-------------------------------------------------------------------------
    1937             :  * ivas_binaural_reverb_close()
    1938             :  *
    1939             :  * Close binaural room reverberator handle
    1940             :  *------------------------------------------------------------------------*/
    1941             : 
    1942       32899 : void ivas_binaural_reverb_close(
    1943             :     REVERB_STRUCT_HANDLE *hReverb /* i/o: binaural reverb handle */
    1944             : )
    1945             : {
    1946             :     int16_t bin, chIdx;
    1947             : 
    1948       32899 :     if ( hReverb == NULL || *hReverb == NULL )
    1949             :     {
    1950           0 :         return;
    1951             :     }
    1952             : 
    1953     1362609 :     for ( bin = 0; bin < ( *hReverb )->numBins; bin++ )
    1954             :     {
    1955     3989130 :         for ( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ )
    1956             :         {
    1957     2659420 :             free( ( *hReverb )->tapPhaseShiftType[bin][chIdx] );
    1958     2659420 :             free( ( *hReverb )->tapPointersReal[bin][chIdx] );
    1959     2659420 :             free( ( *hReverb )->tapPointersImag[bin][chIdx] );
    1960     2659420 :             free( ( *hReverb )->outputBufferReal[bin][chIdx] );
    1961     2659420 :             free( ( *hReverb )->outputBufferImag[bin][chIdx] );
    1962             :         }
    1963     1329710 :         free( ( *hReverb )->loopBufReal[bin] );
    1964     1329710 :         free( ( *hReverb )->loopBufImag[bin] );
    1965             :     }
    1966             : 
    1967       32899 :     free( ( *hReverb ) );
    1968       32899 :     ( *hReverb ) = NULL;
    1969             : 
    1970       32899 :     return;
    1971             : }

Generated by: LCOV version 1.14