LCOV - code coverage report
Current view: top level - lib_rend - ivas_reverb_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 994 1107 89.8 %
Date: 2025-05-03 01:55:50 Functions: 35 36 97.2 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : #include <stdint.h>
      34             : #include "options.h"
      35             : #include "prot_fx.h"
      36             : #include "ivas_prot_rend_fx.h"
      37             : #include "ivas_cnst.h"
      38             : #include "math.h"
      39             : #include "ivas_rom_rend.h"
      40             : #include <assert.h>
      41             : #include "wmc_auto.h"
      42             : #include "debug.h"
      43             : #define float_to_fix( n, factor ) ( round( n * ( 1 << factor ) ) )
      44             : #define float_to_fixQ31( n )      ( round( n * 0x7fffffff ) )
      45             : #define fix_to_float( n, factor ) ( (float) n / ( 1 << factor ) )
      46             : 
      47        1626 : static Word16 wrap_rad_fixed(
      48             :     Word32 angle /* Q13 */ )
      49             : {
      50        1626 :     Word32 L_tmp = angle;
      51        1626 :     move32();
      52             : 
      53             :     /* Wrap azimuth value */
      54        4065 :     WHILE( GT_32( L_tmp, EVS_PI_FX ) )
      55             :     {
      56        2439 :         L_tmp = L_sub( L_tmp, EVS_2PI_FX );
      57             :     }
      58        1626 :     WHILE( LE_32( L_tmp, -EVS_PI_FX ) )
      59             :     {
      60           0 :         L_tmp = L_add( L_tmp, EVS_2PI_FX );
      61             :     }
      62             : 
      63        1626 :     return extract_l( L_tmp );
      64             : }
      65             : 
      66             : /* The reverberator structure implemented here is described in detail in:
      67             :  * Vilkamo, J., Neugebauer, B., & Plogsties, J. (2012). Sparse frequency-domain reverberator.
      68             :  * Journal of the Audio Engineering Society, 59(12), 936-943. */
      69             : 
      70             : /*-------------------------------------------------------------------------
      71             :  * Local constants
      72             :  *------------------------------------------------------------------------*/
      73             : 
      74             : #define BIN_REND_RANDOM_SEED 1 /* random seed for generating reverb decorrelators */
      75             : 
      76             : #define CLDFB_SLOTS_PER_SECOND 800 /* Used for initializing reverb */
      77             : 
      78             : #define INNER_BLK_SIZE 80 /* size of data blocks used for more efficient delay line and IIR filter processing */
      79             : /* should be a divisor of the frame length at any sampling rate and an even number*/
      80             : #define FFT_FILTER_WND_FLAT_REGION     ( 0.40f ) /* flat section (==1) length of FFT filter window, in proportion to overlap */
      81             : #define FFT_FILTER_WND_TRANS_REGION    ( 0.15f ) /* transition (1->0) length of FFT filter window, in proportion to overlap */
      82             : #define FFT_FILTER_WND_FLAT_REGION_FX  ( 26214 ) /*Q16 flat section (==1) length of FFT filter window, in proportion to overlap */
      83             : #define FFT_FILTER_WND_TRANS_REGION_FX ( 9830 )  /*Q16 transition (1->0) length of FFT filter window, in proportion to overlap */
      84             : #define REF_LF_MIN                     ( 100.0f )
      85             : #define REF_LF_MAX                     ( 250.0f )
      86             : #define REF_HF_MIN                     ( 5000.0f )
      87             : #define REF_HF_MAX                     ( 7950.0f )
      88             : 
      89             : #define REF_LF_MIN_FX ( 100 )
      90             : #define REF_LF_MAX_FX ( 250 )
      91             : #define REF_HF_MIN_FX ( 5000 )
      92             : #define REF_HF_MAX_FX ( 7950 )
      93             : #define LF_BIAS       ( 0.5f )
      94             : 
      95             : #define DEFAULT_SRC_DIST                ( 1.5f ) /* default source distance [m] for reverb dmx factor computing */
      96             : #define DMX_GAIN                        ( 1410542208 )
      97             : #define IVAS_REVERB_FFT_SIZE_48K        ( 512 )
      98             : #define IVAS_REVERB_FFT_SIZE_32K        ( 512 )
      99             : #define IVAS_REVERB_FFT_SIZE_16K        ( 256 )
     100             : #define IVAS_REVERB_FFT_N_SUBBLOCKS_48K ( 1 )
     101             : #define IVAS_REVERB_FFT_N_SUBBLOCKS_32K ( 1 )
     102             : #define IVAS_REVERB_FFT_N_SUBBLOCKS_16K ( 1 )
     103             : 
     104             : #define MAX_NR_OUTPUTS ( 2 )
     105             : 
     106             : const Word16 init_loop_delay[IVAS_REV_MAX_NR_BRANCHES] = { 37, 31, 29, 23, 19, 17, 13, 11 };
     107             : const Word16 default_loop_delay_48k[IVAS_REV_MAX_NR_BRANCHES] = { 2309, 1861, 1523, 1259, 1069, 919, 809, 719 };
     108             : const Word16 default_loop_delay_32k[IVAS_REV_MAX_NR_BRANCHES] = { 1531, 1237, 1013, 839, 709, 613, 541, 479 };
     109             : const Word16 default_loop_delay_16k[IVAS_REV_MAX_NR_BRANCHES] = { 769, 619, 509, 421, 353, 307, 269, 239 };
     110             : 
     111             : /*------------------------------------------------------------------------------------------*
     112             :  * Local Struct definition
     113             :  *------------------------------------------------------------------------------------------*/
     114             : typedef struct ivas_reverb_params_t
     115             : {
     116             :     Word16 pre_delay;                                                                                                                                                     /* Delay of the FDC reverb, first peak after pre_delay samples. Note that               */
     117             :                                                                                                                                                                           /*       there may be non-zero samples earlier due to the filters being                 */
     118             :                                                                                                                                                                           /*       linear-phase.                                                                  */
     119             :     Word16 nr_loops;                                                                                                                                                      /* Number of feedback loops (= L)                                                       */
     120             :     Word16 pLoop_delays[IVAS_REV_MAX_NR_BRANCHES]; /* Delay for each feedback loop in samples.                                             */                             /* Feedback [L][L] matrix that mixes the signals of the loops.                          */
     121             :     Word32 pLoop_feedback_matrix_fx[IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_NR_BRANCHES];                                                                                 /* Feedback [L][L] matrix that mixes the signals of the loops.                          */
     122             :     Word16 nr_outputs;                                                                                                                                                    /* Nr of signals extracted from the loops (= S).                                        */
     123             :     /*       Currently this is fixed to 2.                                                  */                                                                            /* Mix [S][L] matrix from feedback loops to outputs.                                    */
     124             :     Word16 pLoop_extract_matrix_fx[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES]; /* Mix [S][L] matrix from feedback loops to outputs.                                    */ /* In Matlab: [S x L] - Currently S=2, later may be more than 2 for speaker playback.   */
     125             :     Word16 t60_filter_order;                                                                                                                                              /* Filter order (length of vector)                                                      */
     126             :     // float pT60_filter_coeff[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_IIR_FILTER_LENGTH];                                                                  /* Filters [][] in feedback loops, controlling T60.                                    */
     127             :     Word16 pT60_filter_coeff_fx[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_IIR_FILTER_LENGTH];
     128             :     /* In Matlab: IIR: [(2 * L) x (<order> + 1)] (odd: b-vector, even: a-vector)            */
     129             :     /* In Matlab: FIR: [L       x <order>]                                                  */
     130             :     // float *pFc;                                                                                                                                                           /* Center frequencies for FFT filter design                                             */
     131             :     // float *pRt60;                                                                                                                                                         /* RT60 values at these frequencies                                                     */
     132             :     // float *pDsr;                                                                                                                                                          /* DSR values at these frequencies                                                      */
     133             :     Word32 *pFc_fx;   /* Center frequencies for FFT filter design                                             */
     134             :     Word32 *pRt60_fx; /* RT60 values at these frequencies                                                     */
     135             :     Word16 *pRt60_e;  /* exponents for RT60 values at these frequencies                                                     */
     136             :     Word32 *pDsr_fx;  /* DSR values at these frequencies                                                      */
     137             :     Word16 *pDsr_e;   /* DSR values at these frequencies                                                      */
     138             :     // float *pHrtf_avg_pwr_response_l;                                                                                                                                      /* The HRTF set's average left  ear power response                                      */
     139             :     // float *pHrtf_avg_pwr_response_r;                                                                                                                                      /* The HRTF set's average right ear power response                                      */
     140             :     // float *pHrtf_inter_aural_coherence;                                                                                                                                   /* The HRTF set's inter-aural coherence for diffuse sound                               */
     141             :     // const float *pHrtf_avg_pwr_response_l_const;                                                                                                                          /* The HRTF set's average left  ear power response                                      */
     142             :     // const float *pHrtf_avg_pwr_response_r_const;                                                                                                                          /* The HRTF set's average right ear power response                                      */
     143             :     // const float *pHrtf_inter_aural_coherence_const;                                                                                                                       /* The HRTF set's inter-aural coherence for diffuse sound                               */
     144             : 
     145             :     Word32 *pHrtf_avg_pwr_response_l_fx;                /* The HRTF set's average left  ear power response                                      */
     146             :     Word32 *pHrtf_avg_pwr_response_r_fx;                /* The HRTF set's average right ear power response                                      */
     147             :     Word32 *pHrtf_inter_aural_coherence_fx;             /* The HRTF set's inter-aural coherence for diffuse sound                               */
     148             :     const Word32 *pHrtf_avg_pwr_response_l_const_fx;    /* The HRTF set's average left  ear power response                                      */
     149             :     const Word32 *pHrtf_avg_pwr_response_r_const_fx;    /* The HRTF set's average right ear power response                                      */
     150             :     const Word32 *pHrtf_inter_aural_coherence_const_fx; /* The HRTF set's inter-aural coherence for diffuse sound                               */
     151             :     Word16 do_corr_filter;                              /* Flag indicating whether correlation filters should be used.                          */
     152             :                                                         /*        Correlation only supported and needed for binaural playback (i.e.             */
     153             :                                                         /*        when nr_outputs != 2 correlation filtering is never supported).               */
     154             : } ivas_reverb_params_t;
     155             : 
     156             : /*------------------------------------------------------------------------------------------*
     157             :  * Static functions declarations
     158             :  *------------------------------------------------------------------------------------------*/
     159             : 
     160             : static ivas_error calc_jot_t60_coeffs_fx( Word16 *pH_dB_fx, Word16 pH_dB_exp, const UWord16 nrFrequencies, Word16 *pFrequencies_fx, Word16 *pCoeffA_fx, Word16 *pCoeffB_fx, const Word16 fNyquist_fx );
     161             : 
     162             : /*-------------------------------------------------------------------------
     163             :  * binRend_rand()
     164             :  *
     165             :  *
     166             :  *------------------------------------------------------------------------*/
     167             : 
     168     1516034 : static UWord16 binRend_rand(
     169             :     REVERB_STRUCT_HANDLE hReverb /* i/o: binaural reverb handle          */
     170             : )
     171             : {
     172     1516034 :     hReverb->binRend_RandNext = hReverb->binRend_RandNext * 1103515245 + 12345;
     173             : 
     174     1516034 :     return (UWord16) ( hReverb->binRend_RandNext / 65536 ) % 32768;
     175             : }
     176             : 
     177             : 
     178             : /*-------------------------------------------------------------------------
     179             :  * ivas_binaural_reverb_setPreDelay()
     180             :  *
     181             :  *
     182             :  *------------------------------------------------------------------------*/
     183             : 
     184         271 : static void ivas_binaural_reverb_setPreDelay_fx(
     185             :     REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle          */
     186             :     const Word16 delaySamples     /* i  : reverb pre-delay in CLDFB slots */
     187             : )
     188             : {
     189         271 :     IF( LT_16( delaySamples, 1 ) )
     190             :     {
     191           0 :         hReverb->preDelayBufferLength = 1;
     192           0 :         move16();
     193             : 
     194           0 :         return;
     195             :     }
     196             : 
     197         271 :     IF( GT_16( delaySamples, REVERB_PREDELAY_MAX ) )
     198             :     {
     199           0 :         hReverb->preDelayBufferLength = REVERB_PREDELAY_MAX;
     200           0 :         move16();
     201             : 
     202           0 :         return;
     203             :     }
     204             : 
     205         271 :     hReverb->preDelayBufferLength = delaySamples;
     206         271 :     move16();
     207             : 
     208         271 :     return;
     209             : }
     210             : 
     211             : 
     212             : /*-------------------------------------------------------------------------
     213             :  * ivas_binaural_reverb_setReverbTimes()
     214             :  *
     215             :  *
     216             :  *------------------------------------------------------------------------*/
     217             : 
     218             : 
     219         271 : static void ivas_binaural_reverb_setReverbTimes_fx(
     220             :     REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle                                  */
     221             :     const Word32 output_Fs,       /* i  : sampling_rate                                           */
     222             :     const Word32 *revTimes_fx,    /*Q31 i  : reverberation times T60 for each CLDFB bin in seconds   */
     223             :     const Word32 *revEnes_fx      /*Q31 i  : spectrum for reverberated sound at each CLDFB bin       */
     224             : )
     225             : {
     226             :     Word16 bin, ch, tap, sample;
     227             : 
     228             :     Word32 binCenterFreq_fx, diffuseFieldICC_fx, tmpVal_fx, attenuationFactorPerSample_fx, L_tmp;
     229             :     Word32 intendedEnergy_fx, actualizedEnergy_fx, energyBuildup_fx, currentEnergy_fx, attenuationFactorPerSampleSq_fx;
     230             :     Word16 tmp, tmp_exp, scale, tmpVal_exp, attenuationFactorPerSample_exp, attenuationFactorPerSampleSq_exp, energyBuildup_exp, currentEnergy_exp, intendedEnergy_exp, actualizedEnergy_exp;
     231             :     Word16 sine_inp, norm, div_exp1, div1, sine, binCenterFreq_exp;
     232         271 :     Word16 reverb_exp = 0;
     233         271 :     move16();
     234             : 
     235         271 :     hReverb->binRend_RandNext = (UWord16) BIN_REND_RANDOM_SEED;
     236         271 :     move16();
     237         271 :     hReverb->highestBinauralCoherenceBin = 0;
     238         271 :     move16();
     239             : 
     240       12371 :     FOR( bin = 0; bin < hReverb->numBins; bin++ )
     241             :     {
     242             :         /* Determine the diffuse field binaural coherence */
     243             :         Word16 exp;
     244       12100 :         tmp_exp = BASOP_Util_Add_MantExp( bin, 15, 1, 14, &tmp );
     245       12100 :         tmp = BASOP_Util_Divide3232_Scale( L_deposit_h( tmp ), L_deposit_h( hReverb->numBins ), &exp );
     246       12100 :         exp = add( exp, sub( tmp_exp, 15 ) );
     247       12100 :         L_tmp = Mpy_32_16_1( output_Fs, tmp ); /*- exp */
     248       12100 :         binCenterFreq_exp = add( 31, exp );
     249       12100 :         binCenterFreq_fx = L_shr( L_tmp, 1 ); // divide by 2
     250       12100 :         IF( bin == 0 )
     251             :         {
     252         271 :             diffuseFieldICC_fx = ONE_IN_Q31;
     253         271 :             move32();
     254             :         }
     255       11829 :         ELSE IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( binCenterFreq_fx, binCenterFreq_exp, 2700, 31 ), -1 ) )
     256             :         {
     257             :             /* binCenterFreq / 550.0f */
     258        1626 :             L_tmp = Mpy_32_32( binCenterFreq_fx, 3904516 /* 1 / 550 in Q31 */ );
     259        1626 :             norm = norm_l( L_tmp );
     260        1626 :             tmp = extract_h( L_shl( L_tmp, norm ) );
     261        1626 :             tmp = add( mult( EVS_PI_FX, tmp ), EPSILLON_FX ); // to avoid divide by 0 issue
     262        1626 :             tmp_exp = sub( add( binCenterFreq_exp, 2 ), norm );
     263             : 
     264        1626 :             sine_inp = wrap_rad_fixed( L_shl( tmp, sub( tmp_exp, 2 ) ) ); // Q13
     265             : 
     266        1626 :             sine = getSinWord16( sine_inp ); // Q15
     267        1626 :             div1 = BASOP_Util_Divide1616_Scale( sine, tmp, &scale );
     268        1626 :             div_exp1 = add( scale, sub( 0, tmp_exp ) );
     269        1626 :             div1 = shl( div1, div_exp1 ); /* Q15 */
     270             : 
     271             :             /* binCenterFreq / 2700.0f */
     272        1626 :             L_tmp = Mpy_32_32( binCenterFreq_fx, 795364 /* 1 / 2700 in Q31 */ );
     273        1626 :             norm = norm_l( L_tmp );
     274        1626 :             L_tmp = L_shl( L_tmp, norm ); /* Q31 */
     275             : 
     276             :             /* ( 1.0f - binCenterFreq / 2700.0f ) */
     277        1626 :             L_tmp = L_sub( ONE_IN_Q31, L_tmp ); /* Q31 */
     278             : 
     279        1626 :             diffuseFieldICC_fx = Mpy_32_16_1( L_tmp, div1 ); /* Q31 */
     280             : 
     281        1626 :             hReverb->highestBinauralCoherenceBin = bin;
     282        1626 :             move16();
     283             :         }
     284             :         ELSE
     285             :         {
     286             : 
     287       10203 :             diffuseFieldICC_fx = 0;
     288       10203 :             move32();
     289             :         }
     290             : 
     291             :         /* Mixing gains to generate a diffuse-binaural sound based on incoherent sound */
     292             :         /* tmpVal = ( 1.0f - sqrtf( 1.0f - powf( diffuseFieldICC, 2.0 ) ) ) / 2.0f; */
     293       12100 :         L_tmp = Mpy_32_32( diffuseFieldICC_fx, diffuseFieldICC_fx ); // square
     294       12100 :         L_tmp = L_sub( ONE_IN_Q31, L_tmp );
     295       12100 :         scale = 0;
     296       12100 :         L_tmp = Sqrt32( L_tmp, &scale );
     297       12100 :         L_tmp = L_shl( L_tmp, scale ); /* Q31 */
     298       12100 :         tmpVal_fx = L_shr( L_sub( ONE_IN_Q31, L_tmp ), 1 );
     299       12100 :         tmpVal_exp = 0;
     300       12100 :         move16();
     301             : 
     302       12100 :         IF( diffuseFieldICC_fx > 0 )
     303             :         {
     304         813 :             exp = tmpVal_exp;
     305         813 :             move16();
     306         813 :             L_tmp = Sqrt32( L_abs( tmpVal_fx ), &exp );
     307         813 :             hReverb->binauralCoherenceCrossmixGains_fx[bin] = L_shl( L_tmp, exp ); // Q31
     308             :         }
     309             :         ELSE
     310             :         {
     311       11287 :             exp = tmpVal_exp;
     312       11287 :             move16();
     313       11287 :             L_tmp = Sqrt32( L_abs( tmpVal_fx ), &exp );
     314       11287 :             hReverb->binauralCoherenceCrossmixGains_fx[bin] = L_negate( L_shl( L_tmp, exp ) ); // Q31
     315             :         }
     316             : 
     317             :         /* hReverb->binauralCoherenceDirectGains[bin] = sqrtf( 1.0f - fabsf( tmpVal ) ); */
     318       12100 :         exp = tmpVal_exp;
     319       12100 :         move16();
     320       12100 :         L_tmp = L_sub( ONE_IN_Q31, L_abs( tmpVal_fx ) );
     321       12100 :         L_tmp = Sqrt32( L_abs( L_tmp ), &exp );
     322       12100 :         hReverb->binauralCoherenceDirectGains_fx[bin] = L_shl( L_tmp, exp ); // making as Q31
     323             : 
     324             :         /* Determine attenuation factor that generates the appropriate energy decay according to reverberation time */
     325       12100 :         L_tmp = Mpy_32_32( 1677721600, revTimes_fx[bin] ); // e10 --> 800 * 2^21, + e0
     326       12100 :         tmp = BASOP_Util_Divide3232_Scale( 1073741824, L_tmp, &scale );
     327       12100 :         scale = add( scale, sub( 1, 10 ) );
     328       12100 :         L_tmp = Mpy_32_16_1( -1610612736, tmp ); // * -3
     329       12100 :         scale = add( 2, scale );
     330       12100 :         L_tmp = Mpy_32_32( 1783446563, L_tmp ); // scale + 2
     331       12100 :         attenuationFactorPerSample_fx = BASOP_util_Pow2( L_tmp, add( scale, 2 ), &attenuationFactorPerSample_exp );
     332             : 
     333             :         Word32 tmp_mul;
     334       12100 :         scale = norm_l( hReverb->loopBufLength[bin] );
     335       12100 :         tmp_mul = L_shl( hReverb->loopBufLength[bin], scale );
     336       12100 :         L_tmp = BASOP_Util_Log2( attenuationFactorPerSample_fx );                     // Q25
     337       12100 :         L_tmp = L_add( L_tmp, L_shl( (Word32) attenuationFactorPerSample_exp, 25 ) ); // Q25
     338       12100 :         L_tmp = Mpy_32_32( L_tmp, tmp_mul );
     339       12100 :         L_tmp = BASOP_util_Pow2( L_tmp, sub( 6 + 31, scale ), &exp );
     340       12100 :         hReverb->loopAttenuationFactor_fx[bin] = L_shl( L_tmp, exp ); // making as Q31
     341             : 
     342       12100 :         attenuationFactorPerSampleSq_fx = Mpy_32_32( attenuationFactorPerSample_fx, attenuationFactorPerSample_fx );
     343       12100 :         attenuationFactorPerSampleSq_exp = attenuationFactorPerSample_exp + attenuationFactorPerSample_exp;
     344             : 
     345             :         /* Design sparse decorrelation filters. The decorrelation filters, due to random procedures involved,
     346             :          * may affect the spectrum of the output. The spectral effect is therefore monitored and compensated for. */
     347             : 
     348       12100 :         intendedEnergy_fx = 0;
     349       12100 :         move32();
     350       12100 :         intendedEnergy_exp = 0;
     351       12100 :         move16();
     352       12100 :         actualizedEnergy_fx = 0;
     353       12100 :         move32();
     354       12100 :         actualizedEnergy_exp = 0;
     355       12100 :         move16();
     356             : 
     357       36300 :         FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
     358             :         {
     359             : 
     360       24200 :             energyBuildup_fx = 0;
     361       24200 :             move32();
     362       24200 :             energyBuildup_exp = 0;
     363       24200 :             move16();
     364       24200 :             currentEnergy_fx = ONE_IN_Q30;
     365       24200 :             move32();
     366       24200 :             currentEnergy_exp = 1;
     367       24200 :             move16();
     368             : 
     369       24200 :             tap = 0;
     370       24200 :             move16();
     371             : 
     372     1218720 :             FOR( sample = 0; sample < hReverb->loopBufLength[bin]; sample++ )
     373             :             {
     374     1194520 :                 intendedEnergy_fx = BASOP_Util_Add_Mant32Exp( intendedEnergy_fx, intendedEnergy_exp, currentEnergy_fx, currentEnergy_exp, &intendedEnergy_exp );
     375             :                 /* The randomization at the energy build up affects where the sparse taps are located */
     376             : 
     377     1194520 :                 UWord16 ret_binRend = binRend_rand( hReverb );
     378             : 
     379     1194520 :                 tmp = BASOP_Util_Divide3232_Scale( ret_binRend, PCM16_TO_FLT_FAC_FX, &tmp_exp );
     380     1194520 :                 L_tmp = BASOP_Util_Add_Mant32Exp( L_deposit_h( tmp ), tmp_exp, L_negate( 1073741824 ), 0, &exp );
     381     1194520 :                 L_tmp = Mpy_32_32( L_tmp, 214748364 ); // exp + 0
     382     1194520 :                 L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, exp, currentEnergy_fx, currentEnergy_exp, &exp );
     383     1194520 :                 energyBuildup_fx = BASOP_Util_Add_Mant32Exp( energyBuildup_fx, energyBuildup_exp, L_tmp, exp, &energyBuildup_exp );
     384     1194520 :                 IF( energyBuildup_fx >= 0 ) /* A new filter tap is added at this condition */
     385             :                 {
     386     1194024 :                     IF( ( BASOP_Util_Cmp_Mant32Exp( energyBuildup_fx, energyBuildup_exp, 1, 31 ) > 0 ) )
     387             :                     {
     388             :                         /* Four efficient phase operations: n*pi/2, n=0,1,2,3 */
     389      321514 :                         hReverb->tapPhaseShiftType[bin][ch][tap] = (Word16) ( binRend_rand( hReverb ) % 4 );
     390      321514 :                         move16();
     391             :                         /* Set the tapPointer to point to the determined sample at the loop buffer */
     392             : 
     393      321514 :                         hReverb->tapPointersReal_fx[bin][ch][tap] = &( hReverb->loopBufReal_fx[bin][sample] );
     394      321514 :                         hReverb->tapPointersImag_fx[bin][ch][tap] = &( hReverb->loopBufImag_fx[bin][sample] );
     395             : 
     396      321514 :                         energyBuildup_fx = BASOP_Util_Add_Mant32Exp( energyBuildup_fx, energyBuildup_exp, L_negate( 1073741824 ), 1, &energyBuildup_exp ); /* A tap is added, thus remove its energy from the buildup */
     397             : 
     398      321514 :                         tap = add( tap, 1 );
     399             : 
     400      321514 :                         actualizedEnergy_fx = BASOP_Util_Add_Mant32Exp( actualizedEnergy_fx, actualizedEnergy_exp, 1073741824, 1, &actualizedEnergy_exp );
     401             :                     }
     402             :                 }
     403             : 
     404     1194520 :                 currentEnergy_fx = BASOP_Util_Add_Mant32Exp( currentEnergy_fx, currentEnergy_exp, 0, 0, &currentEnergy_exp );
     405     1194520 :                 currentEnergy_fx = Mpy_32_32( currentEnergy_fx, attenuationFactorPerSampleSq_fx );
     406     1194520 :                 currentEnergy_exp = currentEnergy_exp + attenuationFactorPerSampleSq_exp;
     407             :             }
     408       24200 :             hReverb->taps[bin][ch] = tap; /* Number of taps determined at the above random procedure */
     409       24200 :             move16();
     410             :         }
     411             : 
     412             :         /* The decorrelator design and IIR attenuation rate affects the energy of reverb, which is compensated here */
     413       12100 :         reverb_exp = 0;
     414       12100 :         move16();
     415       12100 :         hReverb->reverbEqGains_fx[bin] = Sqrt32( revEnes_fx[bin], &reverb_exp ); /* Determined reverb spectrum */
     416       12100 :         move32();
     417       12100 :         hReverb->reverbEqGains_fx[bin] = BASOP_Util_Add_Mant32Exp( hReverb->reverbEqGains_fx[bin], reverb_exp, 0, 0, &reverb_exp );
     418       12100 :         move32();
     419             : 
     420       12100 :         tmp = BASOP_Util_Divide3232_Scale( intendedEnergy_fx, actualizedEnergy_fx, &tmp_exp );
     421       12100 :         tmp_exp = add( tmp_exp, sub( intendedEnergy_exp, actualizedEnergy_exp ) );
     422       12100 :         hReverb->reverbEqGains_fx[bin] = BASOP_Util_Add_Mant32Exp( hReverb->reverbEqGains_fx[bin], reverb_exp, 0, 0, &reverb_exp );
     423       12100 :         move32();
     424       12100 :         L_tmp = Sqrt32( L_deposit_h( tmp ), &tmp_exp );
     425       12100 :         hReverb->reverbEqGains_fx[bin] = Mpy_32_32( hReverb->reverbEqGains_fx[bin], L_tmp );
     426       12100 :         move32();
     427       12100 :         reverb_exp = add( reverb_exp, tmp_exp );
     428             : 
     429       12100 :         L_tmp = BASOP_Util_Add_Mant32Exp( 1073741824, 1, L_negate( attenuationFactorPerSampleSq_fx ), attenuationFactorPerSampleSq_exp, &tmp_exp );
     430       12100 :         L_tmp = Mpy_32_32( L_tmp, 1073741824 ); // tmp_exp + 1
     431       12100 :         tmp_exp = add( tmp_exp, 0 );
     432       12100 :         L_tmp = Sqrt32( L_tmp, &tmp_exp );
     433       12100 :         hReverb->reverbEqGains_fx[bin] = Mpy_32_32( L_tmp, hReverb->reverbEqGains_fx[bin] );
     434       12100 :         move32();
     435       12100 :         reverb_exp = add( reverb_exp, tmp_exp );
     436       12100 :         hReverb->reverbEqGains_fx[bin] = L_shl( hReverb->reverbEqGains_fx[bin], reverb_exp ); // making as Q31
     437       12100 :         move32();
     438             :     }
     439         271 :     return;
     440             : }
     441             : 
     442             : /*-----------------------------------------------------------------------------------------*
     443             :  * Function compute_feedback_matrix()
     444             :  *
     445             :  * Compute the N x N matrix for the mixing the N feedback loop outputs into the N inputs again
     446             :  *-----------------------------------------------------------------------------------------*/
     447             : 
     448         159 : static ivas_error compute_feedback_matrix_fx(
     449             :     Word32 *pFeedbackMatrix, // Q31
     450             :     const Word16 n )
     451             : {
     452             :     Word32 u;
     453             :     Word16 i, j, x;
     454             : 
     455         159 :     u = MATRIX_CONSTANT; // Q31
     456         159 :     move32();
     457             : 
     458         159 :     pFeedbackMatrix[0] = u;
     459         159 :     move32();
     460         636 :     FOR( x = 1; x < n; x += x )
     461             :     {
     462        1590 :         FOR( i = 0; i < x; i++ )
     463             :         {
     464        4452 :             FOR( j = 0; j < x; j++ )
     465             :             {
     466        3339 :                 pFeedbackMatrix[add( i_mult( add( i, x ), n ), j )] = pFeedbackMatrix[add( i_mult( i, n ), j )];
     467        3339 :                 move32();
     468        3339 :                 pFeedbackMatrix[i_mult( i, n ) + j + x] = pFeedbackMatrix[add( i_mult( i, n ), j )];
     469        3339 :                 move32();
     470        3339 :                 pFeedbackMatrix[add( add( i_mult( add( i, x ), n ), j ), x )] = L_negate( pFeedbackMatrix[add( i_mult( i, n ), j )] );
     471        3339 :                 move32();
     472             :             }
     473             :         }
     474             :     }
     475             : 
     476             : 
     477         159 :     return IVAS_ERR_OK;
     478             : }
     479             : 
     480             : 
     481             : /*-----------------------------------------------------------------------------------------*
     482             :  * Function compute_2_out_extract_matrix()
     483             :  *
     484             :  * Compute the N x 2 matrix for mixing the N Jot feedback loops to 2 outputs
     485             :  *-----------------------------------------------------------------------------------------*/
     486             : 
     487         159 : static void compute_2_out_extract_matrix_fx(
     488             :     Word16 *pExtractMatrix,
     489             :     const Word16 n )
     490             : {
     491             :     Word16 ff;
     492             :     Word16 i;
     493             : 
     494         159 :     ff = 1;
     495         159 :     move16();
     496             : 
     497        1431 :     FOR( i = 0; i < n; i++ )
     498             :     {
     499        1272 :         pExtractMatrix[i] = 1;
     500        1272 :         move16();
     501        1272 :         pExtractMatrix[add( i, n )] = ff;
     502        1272 :         move16();
     503        1272 :         ff = negate( ff );
     504             :     }
     505             : 
     506         159 :     return;
     507             : }
     508             : /*-----------------------------------------------------------------------------------------*
     509             :  * Function set_base_config()
     510             :  *
     511             :  * Set all jot reverb parameters that are independent of the input reverb configuration
     512             :  *-----------------------------------------------------------------------------------------*/
     513             : 
     514         159 : static ivas_error set_base_config_fx(
     515             :     ivas_reverb_params_t *pParams,
     516             :     const Word32 output_Fs )
     517             : {
     518             :     ivas_error error;
     519             :     Word16 loop_idx;
     520         159 :     const Word16 *selected_loop_delay = NULL;
     521             : 
     522         159 :     IF( pParams == NULL )
     523             :     {
     524           0 :         return IVAS_ERR_INTERNAL;
     525             :     }
     526             : 
     527         159 :     pParams->pre_delay = 0;
     528         159 :     move16();
     529         159 :     pParams->nr_outputs = BINAURAL_CHANNELS;
     530         159 :     move16();
     531         159 :     pParams->nr_loops = IVAS_REV_MAX_NR_BRANCHES;
     532         159 :     move16();
     533             : 
     534             :     /* set loop delays to default */
     535         159 :     IF( EQ_32( output_Fs, 48000 ) )
     536             :     {
     537          98 :         selected_loop_delay = default_loop_delay_48k; // Q0
     538             :     }
     539          61 :     ELSE IF( EQ_32( output_Fs, 32000 ) )
     540             :     {
     541           0 :         selected_loop_delay = default_loop_delay_32k; // Q0
     542             :     }
     543          61 :     ELSE IF( EQ_32( output_Fs, 16000 ) )
     544             :     {
     545          61 :         selected_loop_delay = default_loop_delay_16k; // Q0
     546             :     }
     547             : 
     548        1431 :     FOR( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ )
     549             :     {
     550        1272 :         pParams->pLoop_delays[loop_idx] = selected_loop_delay[loop_idx];
     551        1272 :         move16();
     552             :     }
     553             : 
     554             :     /* set feedback and output matrices */
     555         159 :     IF( NE_32( ( error = compute_feedback_matrix_fx( pParams->pLoop_feedback_matrix_fx, pParams->nr_loops ) ), IVAS_ERR_OK ) )
     556             :     {
     557           0 :         return error;
     558             :     }
     559             : 
     560         159 :     compute_2_out_extract_matrix_fx( pParams->pLoop_extract_matrix_fx, pParams->nr_loops );
     561             :     /* pre-set the various filters; they will be set later based on reverb configuration */
     562         159 :     pParams->t60_filter_order = 1; /* set to 1 in base config. */
     563         159 :     move16();
     564             : 
     565         159 :     IF( EQ_16( pParams->nr_outputs, 2 ) )
     566             :     {
     567         159 :         pParams->do_corr_filter = 1;
     568         159 :         move16();
     569             :     }
     570             :     ELSE
     571             :     {
     572           0 :         pParams->do_corr_filter = 0;
     573           0 :         move16();
     574             :     }
     575             : 
     576         159 :     return IVAS_ERR_OK;
     577             : }
     578             : 
     579             : /*-----------------------------------------------------------------------------------------*
     580             :  * Function calc_dmx_gain()
     581             :  *
     582             :  * Computes the downmix gain
     583             :  *-----------------------------------------------------------------------------------------*/
     584         159 : static Word32 calc_dmx_gain_fx( void )
     585             : {
     586         159 :     const Word32 gain = DMX_GAIN; // Q25
     587         159 :     move32();
     588         159 :     return gain;
     589             : }
     590             : /*-----------------------------------------------------------------------------------------*
     591             :  * Function calc_predelay()
     592             :  *
     593             :  * Calculate the predelay, taking shortest jot loop delay into account
     594             :  *-----------------------------------------------------------------------------------------*/
     595             : 
     596         159 : static void calc_predelay_fx(
     597             :     ivas_reverb_params_t *pParams,
     598             :     Word32 acoustic_predelay_sec,
     599             :     const Word32 output_Fs )
     600             : {
     601             :     Word16 predelay, fbdelay, output_frame;
     602         159 :     predelay = round_fx( L_shl( Mult_32_32( L_shl( output_Fs, 15 ), acoustic_predelay_sec ), 5 ) );
     603         159 :     output_frame = extract_l( Mult_32_16( output_Fs, INV_FRAME_PER_SEC_Q15 ) );
     604         159 :     fbdelay = pParams->pLoop_delays[sub( pParams->nr_loops, 1 )];
     605         159 :     move16();
     606         159 :     predelay = sub( predelay, fbdelay );
     607             : 
     608         159 :     if ( predelay < 0 )
     609             :     {
     610           0 :         predelay = 0;
     611           0 :         move16();
     612             :     }
     613             : 
     614         159 :     if ( LT_16( output_frame, predelay ) )
     615             :     {
     616           0 :         predelay = output_frame; // Q0
     617           0 :         move16();
     618             :     }
     619             : 
     620         159 :     pParams->pre_delay = predelay; // Q0
     621         159 :     move16();
     622         159 :     move16();
     623         159 :     move16();
     624         159 :     return;
     625             : }
     626             : 
     627             : /*-----------------------------------------------------------------------------------------*
     628             :  * Function compute_t60_coeffs()
     629             :  *
     630             :  * Calculate Jot reverb's T60 filter coefficients
     631             :  *-----------------------------------------------------------------------------------------*/
     632         159 : static ivas_error compute_t60_coeffs_fx(
     633             :     ivas_reverb_params_t *pParams,
     634             :     const Word16 nr_fc_fft_filter, /*Q0*/
     635             :     const Word32 output_Fs )
     636             : {
     637             :     Word16 bin_idx, loop_idx, tf_T60_len, len;
     638             :     ivas_error error;
     639             : 
     640             :     Word16 loop_delay_sec_fx, norm_f_e, tmp;
     641         159 :     Word32 freq_Nyquist_fx = L_shr( output_Fs, 1 );
     642             :     Word16 target_gains_db_fx[RV_LENGTH_NR_FC];
     643             :     Word16 norm_f_fx[RV_LENGTH_NR_FC];
     644             :     Word32 *targetT60_fx, *pFc_fx;
     645             :     Word16 *pCoeffs_a_fx, *pCoeffs_b_fx, *targetT60_e;
     646             :     Word16 target_gains_db_exp[RV_LENGTH_NR_FC];
     647         159 :     error = IVAS_ERR_OK;
     648         159 :     move32();
     649         159 :     tf_T60_len = nr_fc_fft_filter;
     650         159 :     move16();
     651         159 :     len = add( pParams->t60_filter_order, 1 );
     652             : 
     653         159 :     pFc_fx = pParams->pFc_fx;
     654         159 :     targetT60_fx = pParams->pRt60_fx;
     655         159 :     targetT60_e = pParams->pRt60_e;
     656         159 :     move16();
     657             : 
     658       33214 :     FOR( bin_idx = 0; bin_idx < tf_T60_len; bin_idx++ )
     659             :     {
     660       33055 :         norm_f_fx[bin_idx] = BASOP_Util_Divide3232_Scale( pFc_fx[bin_idx], freq_Nyquist_fx, &norm_f_e );
     661       33055 :         move16();
     662       33055 :         norm_f_e = add( norm_f_e, sub( 17, 31 ) );
     663       33055 :         norm_f_fx[bin_idx] = shl( norm_f_fx[bin_idx], sub( norm_f_e, 1 ) ); // making Q14
     664       33055 :         move16();
     665             :     }
     666             : 
     667        1431 :     FOR( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ )
     668             :     {
     669             : 
     670             :         Word16 loop_delay_sec_fx_exp;
     671        1272 :         loop_delay_sec_fx = BASOP_Util_Divide3232_Scale( pParams->pLoop_delays[loop_idx], output_Fs, &loop_delay_sec_fx_exp );
     672             : 
     673      265712 :         FOR( bin_idx = 0; bin_idx < tf_T60_len; bin_idx++ )
     674             :         {
     675      264440 :             tmp = BASOP_Util_Divide3232_Scale( L_deposit_h( loop_delay_sec_fx ), targetT60_fx[bin_idx], &target_gains_db_exp[bin_idx] );
     676      264440 :             target_gains_db_exp[bin_idx] = add( target_gains_db_exp[bin_idx], sub( loop_delay_sec_fx_exp, targetT60_e[bin_idx] ) );
     677      264440 :             move16();
     678      264440 :             target_gains_db_fx[bin_idx] = mult( -30720, tmp ); // -60 in Q9 -> -30720
     679      264440 :             move16();
     680      264440 :             target_gains_db_exp[bin_idx] = add( target_gains_db_exp[bin_idx], 6 ); // Q9 -> e6
     681      264440 :             move16();
     682             : 
     683      264440 :             tmp = BASOP_Util_Cmp_Mant32Exp( L_deposit_h( target_gains_db_fx[bin_idx] ), target_gains_db_exp[bin_idx], -2013265920, 7 );
     684      264440 :             IF( tmp < 0 )
     685             :             {
     686           0 :                 target_gains_db_fx[bin_idx] = -30720; // -60 in Q9 -> -30720
     687           0 :                 move16();
     688           0 :                 target_gains_db_exp[bin_idx] = 7;
     689           0 :                 move16();
     690             :             }
     691             :         }
     692             : 
     693        1272 :         pCoeffs_a_fx = &pParams->pT60_filter_coeff_fx[add( shl( i_mult( len, loop_idx ), 1 ), len )]; // Q14
     694        1272 :         pCoeffs_b_fx = &pParams->pT60_filter_coeff_fx[shl( i_mult( len, loop_idx ), 1 )];             // Q14
     695             : 
     696        1272 :         Word16 val = target_gains_db_exp[0];
     697        1272 :         move16();
     698             : 
     699      264440 :         FOR( Word16 i = 1; i < nr_fc_fft_filter; i++ )
     700             :         {
     701      263168 :             val = s_max( val, target_gains_db_exp[i] );
     702             :         }
     703             : 
     704      265712 :         FOR( Word16 i = 0; i < nr_fc_fft_filter; i++ )
     705             :         {
     706      264440 :             target_gains_db_fx[i] = shr( target_gains_db_fx[i], sub( val, target_gains_db_exp[i] ) );
     707      264440 :             move16();
     708             :         }
     709             : 
     710        1272 :         IF( NE_32( ( error = calc_jot_t60_coeffs_fx( target_gains_db_fx, val, tf_T60_len, norm_f_fx, pCoeffs_a_fx, pCoeffs_b_fx, extract_l( freq_Nyquist_fx ) ) ), IVAS_ERR_OK ) )
     711             :         {
     712           0 :             return error;
     713             :         }
     714             :     }
     715             : 
     716         159 :     len = shr( ( add( pParams->t60_filter_order, 1 ) ), 1 ); // Q0// /* == floor( (order+1) / 2) */
     717        1431 :     FOR( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ )
     718             :     {
     719        1272 :         pParams->pLoop_delays[loop_idx] = sub( pParams->pLoop_delays[loop_idx], len ); // Q0
     720        1272 :         move16();
     721             :     }
     722         159 :     return error;
     723             : }
     724             : 
     725             : 
     726             : /*-----------------------------------------------------------------------------------------*
     727             :  * Function calc_low_shelf_first_order_filter()
     728             :  *
     729             :  * Calculate 1st order low shelf filter
     730             :  *-----------------------------------------------------------------------------------------*/
     731             : 
     732             : 
     733        1272 : static void calc_low_shelf_first_order_filter_fx(
     734             :     Word16 *pNum, /* Q14 */
     735             :     Word16 *pDen, /* Q14 */
     736             :     const Word16 f0,
     737             :     const Word16 lin_gain_lf,
     738             :     const Word16 lin_gain_hf )
     739             : {
     740             :     Word16 sine_val, shift;
     741             :     Word16 cos_val, tmp, tan_val, tan_exp, gain_exp, exp, norm_num0, norm_num1, norm_den0, norm_den1;
     742             :     Word32 L_tmp;
     743             : 
     744        1272 :     tmp = mult( EVS_PI_BY_2_FX, f0 );
     745        1272 :     sine_val = getSinWord16( shl( tmp, 1 ) ); // Q15
     746             : 
     747        1272 :     tmp = mult( EVS_PI_BY_2_FX, f0 );
     748        1272 :     cos_val = getCosWord16( shl( tmp, 1 ) ); // Q14
     749             : 
     750        1272 :     tan_val = BASOP_Util_Divide1616_Scale( sine_val, cos_val, &tan_exp );
     751        1272 :     tan_exp = add( tan_exp, sub( 0, 1 ) );
     752             : 
     753             :     Word16 gain_fx;
     754        1272 :     gain_fx = BASOP_Util_Divide1616_Scale( lin_gain_lf, lin_gain_hf, &gain_exp );
     755             : 
     756        1272 :     IF( LT_16( gain_fx, 16384 ) )
     757             :     {
     758             : 
     759           3 :         tmp = mult( tan_val, gain_fx );
     760           3 :         norm_num0 = add( tan_exp, gain_exp );
     761           3 :         L_tmp = L_add( L_shl( 1, sub( 15, norm_num0 ) ), tmp );
     762           3 :         shift = norm_l( L_tmp );
     763           3 :         L_tmp = L_shl( L_tmp, shift );
     764           3 :         tmp = extract_h( L_tmp );
     765           3 :         pNum[0] = tmp;
     766           3 :         move16();
     767           3 :         norm_num0 = sub( norm_num0, sub( shift, 16 ) );
     768             : 
     769           3 :         tmp = mult( tan_val, gain_fx );
     770           3 :         norm_num1 = add( tan_exp, gain_exp );
     771           3 :         L_tmp = L_sub( tmp, L_shl( 1, sub( 15, norm_num1 ) ) );
     772           3 :         shift = norm_l( L_tmp );
     773           3 :         L_tmp = L_shl( L_tmp, shift );
     774           3 :         tmp = extract_h( L_tmp );
     775           3 :         pNum[1] = tmp;
     776           3 :         move16();
     777           3 :         norm_num1 = sub( norm_num1, sub( shift, 16 ) );
     778             : 
     779           3 :         L_tmp = L_add( L_shl( 1, sub( 15, tan_exp ) ), tan_val );
     780           3 :         shift = norm_l( L_tmp );
     781           3 :         L_tmp = L_shl( L_tmp, shift );
     782           3 :         tmp = extract_h( L_tmp );
     783           3 :         pDen[0] = tmp;
     784           3 :         move16();
     785           3 :         norm_den0 = sub( tan_exp, sub( shift, 16 ) );
     786             : 
     787           3 :         L_tmp = L_sub( tan_val, L_shl( 1, sub( 15, tan_exp ) ) );
     788           3 :         shift = norm_l( L_tmp );
     789           3 :         L_tmp = L_shl( L_tmp, shift );
     790           3 :         tmp = extract_h( L_tmp );
     791           3 :         pDen[1] = tmp;
     792           3 :         move16();
     793           3 :         norm_den1 = sub( tan_exp, sub( shift, 16 ) );
     794             :     }
     795             :     ELSE
     796             :     {
     797        1269 :         L_tmp = L_add( L_shl( 1, ( sub( 15, tan_exp ) ) ), tan_val );
     798        1269 :         shift = norm_l( L_tmp );
     799        1269 :         L_tmp = L_shl( L_tmp, shift );
     800        1269 :         tmp = extract_h( L_tmp );
     801        1269 :         pNum[0] = tmp;
     802        1269 :         move16();
     803        1269 :         norm_num0 = sub( tan_exp, sub( shift, 16 ) );
     804             : 
     805        1269 :         L_tmp = L_sub( tan_val, L_shl( 1, ( sub( 15, tan_exp ) ) ) );
     806        1269 :         shift = norm_l( L_tmp );
     807        1269 :         L_tmp = L_shl( L_tmp, shift );
     808        1269 :         tmp = extract_h( L_tmp );
     809        1269 :         pNum[1] = tmp;
     810        1269 :         move16();
     811        1269 :         norm_num1 = sub( tan_exp, sub( shift, 16 ) );
     812             : 
     813        1269 :         tmp = BASOP_Util_Divide1616_Scale( tan_val, gain_fx, &exp );
     814        1269 :         exp = add( exp, sub( tan_exp, gain_exp ) );
     815        1269 :         L_tmp = L_add( L_shl( 1, sub( 15, exp ) ), tmp );
     816        1269 :         shift = norm_l( L_tmp );
     817        1269 :         L_tmp = L_shl( L_tmp, shift );
     818        1269 :         tmp = extract_h( L_tmp );
     819        1269 :         pDen[0] = tmp;
     820        1269 :         move16();
     821        1269 :         norm_den0 = sub( exp, sub( shift, 16 ) );
     822             : 
     823        1269 :         tmp = BASOP_Util_Divide1616_Scale( tan_val, gain_fx, &exp );
     824        1269 :         exp = add( exp, sub( tan_exp, gain_exp ) );
     825        1269 :         L_tmp = L_sub( tmp, 1 * L_shl( 1, sub( 15, exp ) ) );
     826        1269 :         shift = norm_l( L_tmp );
     827        1269 :         L_tmp = L_shl( L_tmp, shift );
     828        1269 :         tmp = extract_h( L_tmp );
     829        1269 :         pDen[1] = tmp;
     830        1269 :         move16();
     831        1269 :         norm_den1 = sub( exp, sub( shift, 16 ) );
     832             :     }
     833             : 
     834             :     /* Normalize and adjust gain to match target amplitudes */
     835        1272 :     pNum[0] = mult( BASOP_Util_Divide1616_Scale( pNum[0], pDen[0], &exp ), lin_gain_hf );
     836        1272 :     move16();
     837        1272 :     norm_num0 = add( exp, sub( norm_num0, norm_den0 ) );
     838             : 
     839        1272 :     pNum[1] = mult( BASOP_Util_Divide1616_Scale( pNum[1], pDen[0], &exp ), lin_gain_hf );
     840        1272 :     move16();
     841        1272 :     norm_num1 = add( exp, sub( norm_num1, norm_den0 ) );
     842             : 
     843        1272 :     pDen[1] = BASOP_Util_Divide1616_Scale( pDen[1], pDen[0], &exp );
     844        1272 :     move16();
     845        1272 :     norm_den1 = add( exp, sub( norm_den1, norm_den0 ) );
     846             : 
     847        1272 :     pNum[0] = shr( pNum[0], sub( 1, norm_num0 ) ); // Q14
     848        1272 :     move16();
     849        1272 :     pNum[1] = shr( pNum[1], sub( 1, norm_num1 ) ); // Q14
     850        1272 :     move16();
     851        1272 :     pDen[1] = shr( pDen[1], sub( 1, norm_den1 ) ); // Q14
     852        1272 :     move16();
     853        1272 :     pDen[0] = shl( 1, 14 ); // Q14
     854        1272 :     move16();
     855        1272 :     return;
     856             : }
     857             : 
     858             : 
     859             : /*-----------------------------------------------------------------------------------------*
     860             :  * Function calc_jot_t60_coeffs()
     861             :  *
     862             :  * Calculate Jot reverb's T60 filters
     863             :  *-----------------------------------------------------------------------------------------*/
     864             : 
     865             : 
     866        1272 : static ivas_error calc_jot_t60_coeffs_fx(
     867             :     Word16 *pH_dB_fx,
     868             :     Word16 pH_dB_exp,
     869             :     const UWord16 nrFrequencies,
     870             :     Word16 *pFrequencies_fx,
     871             :     Word16 *pCoeffA_fx, /* Q14 */
     872             :     Word16 *pCoeffB_fx, /* Q14 */
     873             :     const Word16 fNyquist_fx )
     874             : {
     875             :     Word16 scale1, scale2, scale3, scale4;
     876        1272 :     Word16 ref_lf_min_norm_fx = BASOP_Util_Divide1616_Scale( REF_LF_MIN_FX, fNyquist_fx, &scale1 );
     877        1272 :     Word16 ref_lf_max_norm_fx = BASOP_Util_Divide1616_Scale( REF_LF_MAX_FX, fNyquist_fx, &scale2 );
     878        1272 :     Word16 ref_hf_min_norm_fx = BASOP_Util_Divide1616_Scale( REF_HF_MIN_FX, fNyquist_fx, &scale3 );
     879        1272 :     Word16 ref_hf_max_norm_fx = BASOP_Util_Divide1616_Scale( REF_HF_MAX_FX, fNyquist_fx, &scale4 );
     880             : 
     881        1272 :     ref_lf_min_norm_fx = shl( ref_lf_min_norm_fx, sub( scale1, 1 ) ); // Q14
     882        1272 :     ref_lf_max_norm_fx = shl( ref_lf_max_norm_fx, sub( scale2, 1 ) ); // Q14
     883        1272 :     ref_hf_min_norm_fx = shl( ref_hf_min_norm_fx, sub( scale3, 1 ) ); // Q14
     884        1272 :     ref_hf_max_norm_fx = shl( ref_hf_max_norm_fx, sub( scale4, 1 ) ); // Q14
     885             : 
     886             :     Word32 L_tmp;
     887             :     Word16 f0_fx, tmp_fx, lf_target_gain_dB_fx, hf_target_gain_dB_fx, mid_crossing_gain_dB_fx;
     888             :     Word16 lin_gain_lf_fx, lin_gain_hf_fx, shift, expl, exph;
     889        1272 :     Word16 f_idx, e = pH_dB_exp;
     890        1272 :     move16();
     891             :     UWord16 n_points_lf, n_points_hf;
     892             : 
     893        1272 :     lf_target_gain_dB_fx = 0;
     894        1272 :     move16();
     895        1272 :     hf_target_gain_dB_fx = 0;
     896        1272 :     move16();
     897        1272 :     Word32 minval_fx = 1455191552;
     898        1272 :     move32();
     899        1272 :     Word16 minval_e = 67, exp;
     900        1272 :     move16();
     901             : 
     902        1272 :     Word32 L_tmpl = 0, L_tmph = 0;
     903        1272 :     move32();
     904        1272 :     move32();
     905        1272 :     n_points_lf = 0;
     906        1272 :     move16();
     907        1272 :     n_points_hf = 0;
     908        1272 :     move16();
     909        1272 :     Word16 minidx_fx = sub( nrFrequencies, 1 );
     910             : 
     911      265712 :     FOR( f_idx = 0; f_idx < nrFrequencies; f_idx++ )
     912             :     {
     913      264440 :         test();
     914      264440 :         IF( GE_16( pFrequencies_fx[f_idx], ref_lf_min_norm_fx ) && LE_16( pFrequencies_fx[f_idx], ref_lf_max_norm_fx ) )
     915             :         {
     916        2248 :             L_tmpl = L_add( L_tmpl, pH_dB_fx[f_idx] );
     917        2248 :             n_points_lf = add( n_points_lf, 1 );
     918             :         }
     919      264440 :         test();
     920      264440 :         IF( GE_16( pFrequencies_fx[f_idx], ref_hf_min_norm_fx ) && LE_16( pFrequencies_fx[f_idx], ref_hf_max_norm_fx ) )
     921             :         {
     922       47728 :             L_tmph = L_add( L_tmph, pH_dB_fx[f_idx] );
     923       47728 :             n_points_hf = add( n_points_hf, 1 );
     924             :         }
     925             :     }
     926        1272 :     shift = norm_l( L_tmpl );
     927        1272 :     L_tmpl = L_shl( L_tmpl, shift );
     928        1272 :     tmp_fx = extract_h( L_tmpl );
     929        1272 :     expl = sub( e, sub( shift, 16 ) );
     930        1272 :     lf_target_gain_dB_fx = tmp_fx;
     931        1272 :     move16();
     932             : 
     933        1272 :     shift = norm_l( L_tmph );
     934        1272 :     L_tmph = L_shl( L_tmph, shift );
     935        1272 :     tmp_fx = extract_h( L_tmph );
     936        1272 :     exph = sub( e, sub( shift, 16 ) );
     937        1272 :     hf_target_gain_dB_fx = tmp_fx;
     938        1272 :     move16();
     939             : 
     940        1272 :     test();
     941        1272 :     IF( ( n_points_lf == 0 ) || ( n_points_hf == 0 ) )
     942             :     {
     943           0 :         return IVAS_ERR_INTERNAL;
     944             :     }
     945             : 
     946        1272 :     lf_target_gain_dB_fx = BASOP_Util_Divide1616_Scale( lf_target_gain_dB_fx, n_points_lf, &e );
     947        1272 :     expl = add( e, sub( expl, 15 ) );
     948             : 
     949        1272 :     hf_target_gain_dB_fx = BASOP_Util_Divide1616_Scale( hf_target_gain_dB_fx, n_points_hf, &e );
     950        1272 :     exph = add( e, sub( exph, 15 ) );
     951             : 
     952        1272 :     e = BASOP_Util_Add_MantExp( lf_target_gain_dB_fx, expl, negate( hf_target_gain_dB_fx ), exph, &tmp_fx );
     953        1272 :     exp = BASOP_Util_Add_MantExp( hf_target_gain_dB_fx, exph, tmp_fx, e - 1, &mid_crossing_gain_dB_fx );
     954             : 
     955      263168 :     FOR( f_idx = 1; f_idx < nrFrequencies - 1; f_idx++ )
     956             :     {
     957             :         Word16 tmp1;
     958      261896 :         e = BASOP_Util_Add_MantExp( pH_dB_fx[f_idx], pH_dB_exp, negate( mid_crossing_gain_dB_fx ), exp, &tmp_fx );
     959      261896 :         tmp1 = abs_s( tmp_fx );
     960             : 
     961      261896 :         tmp_fx = BASOP_Util_Cmp_Mant32Exp( L_deposit_h( tmp1 ), e, minval_fx, minval_e );
     962             : 
     963      261896 :         IF( EQ_16( tmp_fx, -1 ) )
     964             :         {
     965       21184 :             minval_fx = L_deposit_h( tmp1 );
     966       21184 :             minval_e = e;
     967       21184 :             move16();
     968       21184 :             minidx_fx = f_idx;
     969       21184 :             move16();
     970             :         }
     971             :     }
     972             : 
     973        1272 :     f0_fx = pFrequencies_fx[minidx_fx];
     974        1272 :     move16();
     975             : 
     976        1272 :     tmp_fx = mult( lf_target_gain_dB_fx, 5443 ); // expl
     977        1272 :     L_tmp = BASOP_util_Pow2( L_deposit_h( tmp_fx ), expl, &e );
     978        1272 :     lin_gain_lf_fx = extract_l( L_shr( L_tmp, sub( 16, e ) ) );
     979             : 
     980        1272 :     tmp_fx = mult( hf_target_gain_dB_fx, 5443 ); // exph
     981        1272 :     L_tmp = BASOP_util_Pow2( L_deposit_h( tmp_fx ), exph, &e );
     982        1272 :     lin_gain_hf_fx = extract_l( L_shr( L_tmp, sub( 16, e ) ) );
     983             : 
     984             :     /* call low-pass iir shelf */
     985        1272 :     calc_low_shelf_first_order_filter_fx( pCoeffB_fx, pCoeffA_fx, f0_fx, lin_gain_lf_fx, lin_gain_hf_fx );
     986        1272 :     return IVAS_ERR_OK;
     987             : }
     988             : 
     989             : /*-----------------------------------------------------------------------------------------*
     990             :  * Function initialize_reverb_filters()
     991             :  *
     992             :  * Set the number of branches (feedback loops) and Initializes the memory structure (pointers to data)
     993             :  *-----------------------------------------------------------------------------------------*/
     994         159 : static ivas_error initialize_reverb_filters_fx(
     995             :     REVERB_HANDLE hReverb )
     996             : {
     997             :     ivas_error error;
     998             : 
     999         159 :     error = IVAS_ERR_OK;
    1000             : 
    1001             :     /* init correlation and coloration filters */
    1002         159 :     IF( NE_32( ( error = ivas_reverb_t2f_f2t_init( &hReverb->fft_filter_ols, hReverb->fft_size, hReverb->fft_subblock_size ) ), IVAS_ERR_OK ) )
    1003             :     {
    1004           0 :         return error;
    1005             :     }
    1006             : 
    1007         159 :     IF( NE_32( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_correl_0, hReverb->fft_size ) ), IVAS_ERR_OK ) )
    1008             :     {
    1009           0 :         return error;
    1010             :     }
    1011             : 
    1012         159 :     IF( NE_32( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_correl_1, hReverb->fft_size ) ), IVAS_ERR_OK ) )
    1013             :     {
    1014           0 :         return error;
    1015             :     }
    1016             : 
    1017         159 :     IF( NE_32( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_color_0, hReverb->fft_size ) ), IVAS_ERR_OK ) )
    1018             :     {
    1019           0 :         return error;
    1020             :     }
    1021             : 
    1022         159 :     IF( NE_32( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_color_1, hReverb->fft_size ) ), IVAS_ERR_OK ) )
    1023             :     {
    1024           0 :         return error;
    1025             :     }
    1026             : 
    1027         159 :     return error;
    1028             : }
    1029             : 
    1030             : /*-----------------------------------------------------------------------------------------*
    1031             :  * Function set_t60_filter()
    1032             :  *
    1033             :  * Sets t60 number of taps and coefficients A and B
    1034             :  *-----------------------------------------------------------------------------------------*/
    1035             : 
    1036        1272 : static ivas_error set_t60_filter(
    1037             :     REVERB_HANDLE hReverb,
    1038             :     const UWord16 branch,
    1039             :     const UWord16 nr_taps,
    1040             :     const Word16 coefA[], /*Q14*/
    1041             :     const Word16 coefB[] /*Q14*/ )
    1042             : {
    1043        1272 :     IF( GE_32( branch, hReverb->nr_of_branches ) )
    1044             :     {
    1045           0 :         return IVAS_ERR_INTERNAL;
    1046             :     }
    1047             : 
    1048        1272 :     IF( GT_32( nr_taps, IVAS_REV_MAX_IIR_FILTER_LENGTH ) )
    1049             :     {
    1050           0 :         return IVAS_ERR_INTERNAL;
    1051             :     }
    1052             : 
    1053        1272 :     ivas_reverb_iir_filt_set( &( hReverb->t60[branch] ), nr_taps, coefA, coefB );
    1054             : 
    1055        1272 :     return IVAS_ERR_OK;
    1056             : }
    1057             : 
    1058             : /*-----------------------------------------------------------------------------------------*
    1059             :  * Function set_feedback_delay()
    1060             :  *
    1061             :  * Sets Delay of feedback branch in number of samples
    1062             :  *-----------------------------------------------------------------------------------------*/
    1063             : 
    1064        1272 : static ivas_error set_feedback_delay_fx(
    1065             :     REVERB_HANDLE hReverb,
    1066             :     const UWord16 branch,
    1067             :     const Word16 fb_delay /*Q0*/ )
    1068             : {
    1069        1272 :     IF( GE_32( branch, hReverb->nr_of_branches ) )
    1070             :     {
    1071           0 :         return IVAS_ERR_INTERNAL;
    1072             :     }
    1073             : 
    1074        1272 :     hReverb->delay_line[branch].Delay = fb_delay;
    1075        1272 :     move16();
    1076             : 
    1077        1272 :     return IVAS_ERR_OK;
    1078             : }
    1079             : /*-----------------------------------------------------------------------------------------*
    1080             :  * Function set_feedback_gain()
    1081             :  *
    1082             :  * Sets nr_of_branches feedback gain values in feedback matrix
    1083             :  *-----------------------------------------------------------------------------------------*/
    1084             : 
    1085        1272 : static ivas_error set_feedback_gain_fx(
    1086             :     REVERB_HANDLE hReverb,
    1087             :     const UWord16 branch,
    1088             :     const Word32 *pGain /*Q31*/ )
    1089             : {
    1090             :     UWord16 gain_idx;
    1091        1272 :     IF( GE_32( branch, hReverb->nr_of_branches ) )
    1092             :     {
    1093           0 :         return IVAS_ERR_INTERNAL;
    1094             :     }
    1095             : 
    1096       11448 :     FOR( gain_idx = 0; gain_idx < hReverb->nr_of_branches; gain_idx++ )
    1097             :     {
    1098       10176 :         hReverb->gain_matrix_fx[branch][gain_idx] = pGain[gain_idx]; // Q31
    1099       10176 :         move32();
    1100             :     }
    1101             : 
    1102        1272 :     return IVAS_ERR_OK;
    1103             : }
    1104             : /*-----------------------------------------------------------------------------------------*
    1105             :  * Function set_correl_fft_filter()
    1106             :  *
    1107             :  * Sets correlation filter complex gains
    1108             :  *-----------------------------------------------------------------------------------------*/
    1109             : 
    1110         318 : static ivas_error set_correl_fft_filter_fx(
    1111             :     REVERB_HANDLE hReverb,
    1112             :     const UWord16 channel,
    1113             :     rv_fftwf_type_complex_fx *pSpectrum )
    1114             : {
    1115         318 :     IF( GT_32( channel, 1 ) )
    1116             :     {
    1117           0 :         return IVAS_ERR_INTERNAL;
    1118             :     }
    1119             : 
    1120         318 :     IF( EQ_32( channel, 0 ) )
    1121             :     {
    1122         159 :         ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR_fx( pSpectrum, hReverb->fft_filter_correl_0.fft_spectrum_fx, hReverb->fft_filter_correl_0.fft_size );
    1123             :     }
    1124             :     ELSE
    1125             :     {
    1126         159 :         ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR_fx( pSpectrum, hReverb->fft_filter_correl_1.fft_spectrum_fx, hReverb->fft_filter_correl_1.fft_size );
    1127             :     }
    1128             : 
    1129         318 :     return IVAS_ERR_OK;
    1130             : }
    1131             : 
    1132             : 
    1133             : /*-----------------------------------------------------------------------------------------*
    1134             :  * Function set_color_fft_filter()
    1135             :  *
    1136             :  * Sets coloration filter complex gains
    1137             :  *-----------------------------------------------------------------------------------------*/
    1138             : 
    1139         318 : static ivas_error set_color_fft_filter_fx(
    1140             :     REVERB_HANDLE hReverb,
    1141             :     const UWord16 channel,
    1142             :     rv_fftwf_type_complex_fx *pSpectrum )
    1143             : {
    1144         318 :     IF( GT_32( channel, 1 ) )
    1145             :     {
    1146           0 :         return IVAS_ERR_INTERNAL;
    1147             :     }
    1148             : 
    1149         318 :     IF( EQ_32( channel, 0 ) )
    1150             :     {
    1151         159 :         ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR_fx( pSpectrum, hReverb->fft_filter_color_0.fft_spectrum_fx, hReverb->fft_filter_color_0.fft_size );
    1152             :     }
    1153             :     ELSE
    1154             :     {
    1155         159 :         ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR_fx( pSpectrum, hReverb->fft_filter_color_1.fft_spectrum_fx, hReverb->fft_filter_color_1.fft_size );
    1156             :     }
    1157             : 
    1158         318 :     return IVAS_ERR_OK;
    1159             : }
    1160             : 
    1161             : 
    1162             : /*-----------------------------------------------------------------------------------------*
    1163             :  * Function set_mixer_level_fx()
    1164             :  *
    1165             :  * Sets Mixer level: to mix 2 output channels from 8 feedback branches
    1166             :  *-----------------------------------------------------------------------------------------*/
    1167             : 
    1168         318 : static ivas_error set_mixer_level_fx(
    1169             :     REVERB_HANDLE hReverb,
    1170             :     const UWord16 channel,
    1171             :     const Word16 level[] /*Q0*/ )
    1172             : {
    1173             :     UWord16 branch_idx;
    1174         318 :     IF( GE_32( channel, BINAURAL_CHANNELS ) )
    1175             :     {
    1176           0 :         return IVAS_ERR_INTERNAL;
    1177             :     }
    1178             : 
    1179        2862 :     FOR( branch_idx = 0; branch_idx < hReverb->nr_of_branches; branch_idx++ )
    1180             :     {
    1181        2544 :         hReverb->mixer_fx[channel][branch_idx] = level[branch_idx]; /*Q0*/
    1182        2544 :         move16();
    1183             :     }
    1184             : 
    1185         318 :     return IVAS_ERR_OK;
    1186             : }
    1187             : /*-----------------------------------------------------------------------------------------*
    1188             :  * Function clear_buffers_fx()
    1189             :  *
    1190             :  * Clears buffers of delay lines and filters
    1191             :  *-----------------------------------------------------------------------------------------*/
    1192             : 
    1193         159 : static void clear_buffers_fx(
    1194             :     REVERB_HANDLE hReverb )
    1195             : {
    1196             :     Word16 branch_idx;
    1197             :     ivas_rev_iir_filter_t *iirFilter;
    1198             :     ivas_rev_delay_line_t *delay_line;
    1199             : 
    1200        1431 :     FOR( branch_idx = 0; branch_idx < IVAS_REV_MAX_NR_BRANCHES; branch_idx++ )
    1201             :     {
    1202        1272 :         delay_line = &( hReverb->delay_line[branch_idx] );
    1203        1272 :         set32_fx( delay_line->pBuffer_fx, 0, delay_line->MaxDelay );
    1204        1272 :         delay_line->BufferPos = 0;
    1205        1272 :         move16();
    1206             : 
    1207        1272 :         iirFilter = &( hReverb->t60[branch_idx] );
    1208        1272 :         set32_fx( iirFilter->pBuffer_fx, 0, iirFilter->MaxTaps );
    1209             :     }
    1210             : 
    1211         159 :     ivas_reverb_t2f_f2t_ClearHistory( &hReverb->fft_filter_ols );
    1212             : 
    1213         159 :     return;
    1214             : }
    1215             : 
    1216             : /*-----------------------------------------------------------------------------------------*
    1217             :  * Function set_fft_and_datablock_sizes_fx()
    1218             :  *
    1219             :  * Sets frame size and fft-filter related sizes
    1220             :  *-----------------------------------------------------------------------------------------*/
    1221             : 
    1222         159 : static void set_fft_and_datablock_sizes_fx(
    1223             :     REVERB_HANDLE hReverb,
    1224             :     const Word16 subframe_len )
    1225             : {
    1226         159 :     hReverb->full_block_size = subframe_len;
    1227         159 :     IF( EQ_16( subframe_len, 240 /*L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES*/ ) )
    1228             :     {
    1229          98 :         hReverb->fft_size = IVAS_REVERB_FFT_SIZE_48K;
    1230          98 :         move16();
    1231          98 :         hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_48K;
    1232          98 :         move16();
    1233             :     }
    1234          61 :     ELSE IF( EQ_16( subframe_len, 160 /*L_FRAME32k / MAX_PARAM_SPATIAL_SUBFRAMES*/ ) )
    1235             :     {
    1236           0 :         hReverb->fft_size = IVAS_REVERB_FFT_SIZE_32K;
    1237           0 :         move16();
    1238           0 :         hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_32K;
    1239           0 :         move16();
    1240             :     }
    1241          61 :     ELSE IF( EQ_16( subframe_len, 80 /*L_FRAME16k / MAX_PARAM_SPATIAL_SUBFRAMES*/ ) )
    1242             :     {
    1243          61 :         hReverb->fft_size = IVAS_REVERB_FFT_SIZE_16K;
    1244          61 :         move16();
    1245          61 :         hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_16K;
    1246          61 :         move16();
    1247             :     }
    1248             :     ELSE
    1249             :     {
    1250           0 :         assert( 0 ); /* unsupported block size */
    1251             :     }
    1252             : 
    1253         159 :     hReverb->fft_subblock_size = (UWord16) idiv1616( subframe_len, hReverb->num_fft_subblocks );
    1254         159 :     move16();
    1255             : 
    1256         159 :     return;
    1257             : }
    1258             : 
    1259             : /*-----------------------------------------------------------------------------------------*
    1260             :  * Function set_reverb_acoustic_data()
    1261             :  *
    1262             :  * Sets reverb acoustic data (room acoustics and HRTF), interpolating it to the filter grid
    1263             :  *-----------------------------------------------------------------------------------------*/
    1264             : 
    1265         159 : static void set_reverb_acoustic_data_fx(
    1266             :     ivas_reverb_params_t *pParams,
    1267             :     const AUDIO_CONFIG input_audio_config,
    1268             :     const HRTFS_HANDLE hHrtf,
    1269             :     IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pRoomAcoustics,
    1270             :     const Word16 subframe_len,
    1271             :     const Word16 nr_fc_input,
    1272             :     const Word16 nr_fc_fft_filter )
    1273             : {
    1274             :     Word16 nr_out_ch, hrtf_idx, offset, iter_idx, bin_idx;
    1275             :     Word32 *pHrtf_set_l_re_fx[MAX_INTERN_CHANNELS];
    1276             :     Word32 *pHrtf_set_l_im_fx[MAX_INTERN_CHANNELS];
    1277             :     Word32 *pHrtf_set_r_re_fx[MAX_INTERN_CHANNELS];
    1278             :     Word32 *pHrtf_set_r_im_fx[MAX_INTERN_CHANNELS];
    1279             :     Word32 ln_1e6_inverted_fx, delay_diff_fx, L_tmp;
    1280             :     Word16 exp_argument_fx, tmp, tmp_flag, exp_argument_e;
    1281             :     Word16 pow_exp;
    1282             : 
    1283         159 :     Word32 *pFc_input_fx = pRoomAcoustics->pFc_input_fx;
    1284         159 :     Word32 *pAcoustic_rt60_fx = pRoomAcoustics->pAcoustic_rt60_fx;
    1285         159 :     Word32 *pAcoustic_dsr_fx = pRoomAcoustics->pAcoustic_dsr_fx;
    1286             : 
    1287         159 :     Word32 *pFc_fx = pParams->pFc_fx;
    1288         159 :     Word32 *pRt60_fx = pParams->pRt60_fx;
    1289         159 :     Word16 *pRt60_e = pParams->pRt60_e;
    1290         159 :     Word32 *pDsr_fx = pParams->pDsr_fx;
    1291         159 :     Word16 *pDsr_e = pParams->pDsr_e;
    1292             : 
    1293             :     /* use crend hrtf filters */
    1294         159 :     IF( hHrtf != NULL )
    1295             :     {
    1296             :         /* Compute HRTF set properties: average left/right energies, IA coherence */
    1297             :         /* First, find the offset of the frequency-domain data for the 1st frame and assign HRTF pointers */
    1298         330 :         FOR( nr_out_ch = 0; nr_out_ch < BINAURAL_CHANNELS; nr_out_ch++ )
    1299             :         {
    1300        1792 :             FOR( hrtf_idx = 0; hrtf_idx < hHrtf->max_num_ir; hrtf_idx++ )
    1301             :             {
    1302        1572 :                 offset = 0;
    1303        1572 :                 move16();
    1304        1572 :                 FOR( iter_idx = 0; iter_idx < hHrtf->num_iterations[hrtf_idx][nr_out_ch] - 1; iter_idx++ )
    1305             :                 {
    1306           0 :                     offset = add( offset, hHrtf->pIndex_frequency_max[hrtf_idx][nr_out_ch][iter_idx] );
    1307             :                 }
    1308             : 
    1309        1572 :                 IF( EQ_16( nr_out_ch, 0 ) )
    1310             :                 {
    1311         786 :                     pHrtf_set_l_re_fx[hrtf_idx] = &hHrtf->pOut_to_bin_re_fx[hrtf_idx][0][offset];
    1312         786 :                     pHrtf_set_l_im_fx[hrtf_idx] = &hHrtf->pOut_to_bin_im_fx[hrtf_idx][0][offset];
    1313             :                 }
    1314             :                 ELSE
    1315             :                 {
    1316         786 :                     pHrtf_set_r_re_fx[hrtf_idx] = &hHrtf->pOut_to_bin_re_fx[hrtf_idx][1][offset];
    1317         786 :                     pHrtf_set_r_im_fx[hrtf_idx] = &hHrtf->pOut_to_bin_im_fx[hrtf_idx][1][offset];
    1318             :                 }
    1319             :             }
    1320             :         }
    1321             : 
    1322             :         /* Compute HRTF set properties using frequency-domain HRTF data */
    1323         110 :         Word32 *pHrtf_avg_pwr_response_l_fx = pParams->pHrtf_avg_pwr_response_l_fx;
    1324         110 :         Word32 *pHrtf_avg_pwr_response_r_fx = pParams->pHrtf_avg_pwr_response_r_fx;
    1325         110 :         Word32 *pHrtf_inter_aural_coherence_fx = pParams->pHrtf_inter_aural_coherence_fx;
    1326         110 :         ivas_reverb_get_hrtf_set_properties_fx( pHrtf_set_l_re_fx, pHrtf_set_l_im_fx, pHrtf_set_r_re_fx, pHrtf_set_r_im_fx, input_audio_config, hHrtf->max_num_ir, subframe_len,
    1327             :                                                 nr_fc_fft_filter, pHrtf_avg_pwr_response_l_fx, pHrtf_avg_pwr_response_r_fx, pHrtf_inter_aural_coherence_fx );
    1328             : 
    1329         110 :         pParams->pHrtf_avg_pwr_response_l_const_fx = (const Word32 *) pParams->pHrtf_avg_pwr_response_l_fx;
    1330         110 :         pParams->pHrtf_avg_pwr_response_r_const_fx = (const Word32 *) pParams->pHrtf_avg_pwr_response_r_fx;
    1331         110 :         pParams->pHrtf_inter_aural_coherence_const_fx = (const Word32 *) pParams->pHrtf_inter_aural_coherence_fx;
    1332             :     }
    1333             : 
    1334             :     /* interpolate input table data for T60 and DSR to the FFT filter grid */
    1335         159 :     ivas_reverb_interpolate_acoustic_data_fx( nr_fc_input, pFc_input_fx, pAcoustic_rt60_fx, pAcoustic_dsr_fx,
    1336             :                                               nr_fc_fft_filter, pFc_fx, pRt60_fx, pDsr_fx, pRt60_e, pDsr_e );
    1337             : 
    1338             :     /* adjust DSR for the delay difference */
    1339             : 
    1340         159 :     delay_diff_fx = L_sub( pRoomAcoustics->inputPreDelay_fx, pRoomAcoustics->acousticPreDelay_fx );
    1341             : 
    1342         159 :     ln_1e6_inverted_fx = 155440049; // Q31 /* 1.0f / logf( 1e06f ) */
    1343         159 :     move32();
    1344             : 
    1345       33214 :     FOR( bin_idx = 0; bin_idx < nr_fc_fft_filter; bin_idx++ )
    1346             :     {
    1347       33055 :         L_tmp = Mpy_32_32( pRt60_fx[bin_idx], ln_1e6_inverted_fx ); // exp = pRt60_e[bin_idx] + 0
    1348       33055 :         exp_argument_fx = BASOP_Util_Divide3232_Scale( delay_diff_fx, L_tmp, &exp_argument_e );
    1349       33055 :         exp_argument_e = add( exp_argument_e, sub( 4, pRt60_e[bin_idx] ) ); // Q27 -> e4
    1350             :         /* Limit exponent to approx +/-100 dB in case of incoherent value of delay_diff, to prevent overflow */
    1351             : 
    1352             :         // 23 in Q26
    1353       33055 :         tmp_flag = BASOP_Util_Cmp_Mant32Exp( L_deposit_h( exp_argument_fx ), exp_argument_e, 1543503872, 5 );
    1354       33055 :         IF( tmp_flag > 0 )
    1355             :         {
    1356           0 :             exp_argument_fx = 23552;
    1357           0 :             move16();
    1358           0 :             exp_argument_e = 5;
    1359           0 :             move16();
    1360             :         }
    1361             : 
    1362       33055 :         tmp_flag = BASOP_Util_Cmp_Mant32Exp( L_deposit_h( exp_argument_fx ), exp_argument_e, 0, 31 );
    1363       33055 :         IF( tmp_flag < 0 )
    1364             :         {
    1365           0 :             tmp_flag = BASOP_Util_Cmp_Mant32Exp( L_deposit_h( negate( exp_argument_fx ) ), exp_argument_e, 1543503872, 5 );
    1366           0 :             IF( tmp_flag < 0 )
    1367             :             {
    1368           0 :                 exp_argument_fx = -23552;
    1369           0 :                 move16();
    1370           0 :                 exp_argument_e = 5;
    1371           0 :                 move16();
    1372             :             }
    1373             :         }
    1374             : 
    1375             :         Word16 tmp_exp;
    1376             :         /* expf(exp_argument) -> pow(2, log2(e) * exp_argument) */
    1377       33055 :         tmp = mult( 23637, exp_argument_fx ); // exp_argument_e + 1
    1378       33055 :         tmp_exp = add( exp_argument_e, 1 );
    1379       33055 :         L_tmp = BASOP_util_Pow2( L_deposit_h( tmp ), tmp_exp, &pow_exp );
    1380       33055 :         L_tmp = Mpy_32_32( L_tmp, pDsr_fx[bin_idx] );
    1381       33055 :         tmp_exp = add( pow_exp, pDsr_e[bin_idx] );
    1382             : 
    1383       33055 :         pDsr_fx[bin_idx] = L_tmp;
    1384       33055 :         move32();
    1385       33055 :         pDsr_e[bin_idx] = tmp_exp;
    1386       33055 :         move16();
    1387             :     }
    1388         159 :     return;
    1389             : }
    1390             : 
    1391             : 
    1392             : /*-----------------------------------------------------------------------------------------*
    1393             :  * Function setup_FDN_branches_fx()
    1394             :  *
    1395             :  * Sets up feedback delay network system
    1396             :  *-----------------------------------------------------------------------------------------*/
    1397             : 
    1398         159 : static ivas_error setup_FDN_branches_fx(
    1399             :     REVERB_HANDLE hReverb,
    1400             :     ivas_reverb_params_t *pParams )
    1401             : {
    1402             :     Word16 nr_coefs, branch_idx, channel_idx;
    1403             :     ivas_error error;
    1404             :     Word16 *pCoef_a, *pCoef_b;
    1405         159 :     error = IVAS_ERR_OK;
    1406             : 
    1407             :     /* initialize feedback branches */
    1408        1431 :     FOR( branch_idx = 0; branch_idx < IVAS_REV_MAX_NR_BRANCHES; branch_idx++ )
    1409             :     {
    1410        1272 :         ivas_rev_delay_line_init( &( hReverb->delay_line[branch_idx] ), hReverb->loop_delay_buffer_fx[branch_idx], init_loop_delay[branch_idx], pParams->pLoop_delays[branch_idx] );
    1411        1272 :         ivas_reverb_iir_filt_init( &( hReverb->t60[branch_idx] ), IVAS_REV_MAX_IIR_FILTER_LENGTH );
    1412        1272 :         hReverb->mixer_fx[0][branch_idx] = 0;
    1413        1272 :         move16();
    1414        1272 :         hReverb->mixer_fx[1][branch_idx] = 0;
    1415        1272 :         move16();
    1416             :     }
    1417         159 :     clear_buffers_fx( hReverb );
    1418         159 :     nr_coefs = add( pParams->t60_filter_order, 1 );
    1419             : 
    1420         159 :     IF( LT_16( IVAS_REV_MAX_IIR_FILTER_LENGTH, nr_coefs ) )
    1421             :     {
    1422           0 :         return IVAS_ERR_INTERNAL;
    1423             :     }
    1424             :     ELSE
    1425             :     {
    1426        1431 :         FOR( branch_idx = 0; branch_idx < pParams->nr_loops; branch_idx++ )
    1427             :         {
    1428        1272 :             pCoef_b = &pParams->pT60_filter_coeff_fx[shl( i_mult( nr_coefs, branch_idx ), 1 )];                  /*Q14*/
    1429        1272 :             pCoef_a = &pParams->pT60_filter_coeff_fx[add( shl( i_mult( nr_coefs, branch_idx ), 1 ), nr_coefs )]; /*Q14*/
    1430             : 
    1431        1272 :             IF( NE_32( ( error = set_t60_filter( hReverb, branch_idx, nr_coefs, pCoef_a, pCoef_b ) ), IVAS_ERR_OK ) )
    1432             :             {
    1433           0 :                 return error;
    1434             :             }
    1435             : 
    1436        1272 :             IF( NE_32( ( error = set_feedback_delay_fx( hReverb, branch_idx, pParams->pLoop_delays[branch_idx] ) ), IVAS_ERR_OK ) )
    1437             :             {
    1438           0 :                 return error;
    1439             :             }
    1440        1272 :             IF( NE_32( ( error = set_feedback_gain_fx( hReverb, branch_idx, &( pParams->pLoop_feedback_matrix_fx[i_mult( branch_idx, pParams->nr_loops )] ) ) ), IVAS_ERR_OK ) )
    1441             :             {
    1442           0 :                 return error;
    1443             :             }
    1444             :         }
    1445             :     }
    1446             : 
    1447         477 :     FOR( channel_idx = 0; channel_idx < pParams->nr_outputs; channel_idx++ )
    1448             :     {
    1449         318 :         IF( NE_32( ( error = set_mixer_level_fx( hReverb, channel_idx, &( pParams->pLoop_extract_matrix_fx[i_mult( channel_idx, pParams->nr_loops )] ) ) ), IVAS_ERR_OK ) )
    1450             :         {
    1451           0 :             return error;
    1452             :         }
    1453             :     }
    1454             : 
    1455         159 :     return error;
    1456             : }
    1457             : /*-------------------------------------------------------------------------
    1458             :  * ivas_reverb_open_fx()
    1459             :  *
    1460             :  * Allocate and initialize Crend reverberation handle
    1461             :  *------------------------------------------------------------------------*/
    1462             : 
    1463         159 : ivas_error ivas_reverb_open_fx(
    1464             :     REVERB_HANDLE *hReverb,                /* i/o: Reverberator handle               */
    1465             :     const AUDIO_CONFIG input_audio_config, /* i  : reverb. input audio configuration */
    1466             :     const HRTFS_HANDLE hHrtf,              /* i  : HRTF handle                       */
    1467             :     const Word32 *lr_energy_and_iac_fx[],  /* i  : precomuputed lr energies and iac  */
    1468             :     RENDER_CONFIG_HANDLE hRenderConfig,    /* i  : Renderer configuration handle     */
    1469             :     const Word32 output_Fs                 /* i  : output sampling rate              */
    1470             : )
    1471             : {
    1472             :     ivas_error error;
    1473         159 :     REVERB_HANDLE pState = NULL;
    1474             :     Word16 bin_idx, subframe_len, output_frame, predelay_bf_len, loop_idx, i;
    1475             :     ivas_reverb_params_t params;
    1476             :     Word32 pColor_target_l_fx[RV_LENGTH_NR_FC];
    1477             :     Word32 pColor_target_r_fx[RV_LENGTH_NR_FC];
    1478             :     Word32 pTime_window_fx[RV_FILTER_MAX_FFT_SIZE];
    1479             :     Word32 freq_step_fx;
    1480             :     Word16 fft_hist_size, transition_start, transition_length;
    1481             :     Word16 nr_fc_input, nr_fc_fft_filter;
    1482             :     rv_fftwf_type_complex_fx pFft_wf_filter_ch0_fx[RV_LENGTH_NR_FC];
    1483             :     rv_fftwf_type_complex_fx pFft_wf_filter_ch1_fx[RV_LENGTH_NR_FC];
    1484             : 
    1485         159 :     error = IVAS_ERR_OK;
    1486         159 :     output_frame = extract_l( Mult_32_16( output_Fs, INV_FRAME_PER_SEC_Q15 ) );
    1487         159 :     subframe_len = shr( output_frame, 2 ); /*output_frame / MAX_PARAM_SPATIAL_SUBFRAMES*/
    1488         159 :     predelay_bf_len = output_frame;
    1489         159 :     move16();
    1490         159 :     nr_fc_input = hRenderConfig->roomAcoustics.nBands;
    1491             : 
    1492             :     /* Allocate main reverb. handle */
    1493         159 :     IF( ( pState = (REVERB_HANDLE) malloc( sizeof( REVERB_DATA ) ) ) == NULL )
    1494             :     {
    1495           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend Reverberator " );
    1496             :     }
    1497             : 
    1498         159 :     IF( NE_32( ( error = set_base_config_fx( &params, output_Fs ) ), IVAS_ERR_OK ) )
    1499             :     {
    1500           0 :         return error;
    1501             :     }
    1502             : 
    1503             :     /* Allocate memory for feedback delay lines */
    1504        1431 :     FOR( loop_idx = 0; loop_idx < IVAS_REV_MAX_NR_BRANCHES; loop_idx++ )
    1505             :     {
    1506        1272 :         IF( ( pState->loop_delay_buffer_fx[loop_idx] = (Word32 *) malloc( params.pLoop_delays[loop_idx] * sizeof( Word32 ) ) ) == NULL )
    1507             :         {
    1508           0 :             return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CREND Reverberator" );
    1509             :         }
    1510             :     }
    1511             : 
    1512             :     /* Allocate memory for the pre-delay delay line */
    1513         159 :     IF( ( pState->pPredelay_buffer_fx = (Word32 *) malloc( output_frame * sizeof( Word32 ) ) ) == NULL )
    1514             :     {
    1515           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CREND Reverberator" );
    1516             :     }
    1517             : 
    1518         159 :     pState->nr_of_branches = IVAS_REV_MAX_NR_BRANCHES;
    1519         159 :     move16();
    1520         159 :     set_fft_and_datablock_sizes_fx( pState, subframe_len );
    1521         159 :     nr_fc_fft_filter = add( extract_l( L_shr( pState->fft_size, 1 ) ), 1 );
    1522             : 
    1523             :     /* === 'Control logic': compute the reverb processing parameters from the              === */
    1524             :     /* === room, source and listener acoustic information provided in the reverb config    === */
    1525             :     /* Setting up shared temporary buffers for fc, RT60, DSR, etc.                             */
    1526         159 :     params.pHrtf_avg_pwr_response_l_fx = &pFft_wf_filter_ch0_fx[0][0];
    1527         159 :     params.pHrtf_avg_pwr_response_r_fx = params.pHrtf_avg_pwr_response_l_fx + nr_fc_fft_filter;
    1528         159 :     params.pRt60_fx = &pFft_wf_filter_ch1_fx[0][0];
    1529         159 :     params.pDsr_fx = params.pRt60_fx + nr_fc_fft_filter;
    1530         159 :     params.pFc_fx = &pState->fft_filter_color_0.fft_spectrum_fx[0];
    1531         159 :     params.pHrtf_inter_aural_coherence_fx = &pState->fft_filter_color_1.fft_spectrum_fx[0];
    1532         159 :     set32_fx( pState->fft_filter_color_1.fft_spectrum_fx, 0, RV_FILTER_MAX_FFT_SIZE );
    1533             :     /* Note: these temp buffers can only be used before the final step of the FFT filter design :     */
    1534             :     /* before calls to ivas_reverb_calc_correl_filters(...) or to ivas_reverb_calc_color_filters(...) */
    1535             : 
    1536             :     /* set the uniform frequency grid for FFT filtering                                               */
    1537         159 :     freq_step_fx = L_mult0( extract_l( L_shr( output_Fs, 2 ) ), div_s( 1, ( nr_fc_fft_filter - 1 ) ) ); /*Q14:0.5f * output_Fs / ( nr_fc_fft_filter - 1 )*/
    1538       33214 :     FOR( bin_idx = 0; bin_idx < nr_fc_fft_filter; bin_idx++ )
    1539             :     {
    1540       33055 :         params.pFc_fx[bin_idx] = W_extract_l( W_mult0_32_32( freq_step_fx, bin_idx ) ); /*Q14*/
    1541             :     }
    1542             : 
    1543         159 :     test();
    1544         159 :     IF( hHrtf == NULL && lr_energy_and_iac_fx != NULL )
    1545             :     {
    1546          49 :         params.pHrtf_avg_pwr_response_l_const_fx = lr_energy_and_iac_fx[0];
    1547          49 :         params.pHrtf_avg_pwr_response_r_const_fx = lr_energy_and_iac_fx[1];
    1548          49 :         params.pHrtf_inter_aural_coherence_const_fx = lr_energy_and_iac_fx[2];
    1549             :     }
    1550             :     /* set up reverb acoustic data on the basis of HRTF data and renderer config  */
    1551         159 :     Scale_sig32( params.pFc_fx, nr_fc_fft_filter, 2 );
    1552         159 :     Word16 *pRt60_e = (Word16 *) malloc( sizeof( Word16 ) * nr_fc_fft_filter );
    1553         159 :     Word16 *pDsr_e = (Word16 *) malloc( sizeof( Word16 ) * nr_fc_fft_filter );
    1554             : 
    1555         159 :     params.pRt60_e = pRt60_e;
    1556         159 :     params.pDsr_e = pDsr_e;
    1557             : 
    1558         159 :     set_reverb_acoustic_data_fx( &params, input_audio_config, hHrtf, &hRenderConfig->roomAcoustics, subframe_len, nr_fc_input, nr_fc_fft_filter );
    1559         159 :     Scale_sig32( params.pFc_fx, nr_fc_fft_filter, -2 );
    1560       33214 :     FOR( i = 0; i < nr_fc_fft_filter; i++ )
    1561             :     {
    1562       33055 :         params.pRt60_fx[i] = L_abs( params.pRt60_fx[i] );
    1563       33055 :         move32();
    1564       33055 :         params.pDsr_fx[i] = L_abs( params.pDsr_fx[i] );
    1565       33055 :         move32();
    1566             :     }
    1567             : 
    1568             :     /* set reverb acoustic configuration based on renderer config  */
    1569         159 :     pState->pConfig.roomAcoustics.override = hRenderConfig->roomAcoustics.override;
    1570         159 :     move16();
    1571         159 :     pState->pConfig.roomAcoustics.nBands = hRenderConfig->roomAcoustics.nBands;
    1572         159 :     move16();
    1573             : 
    1574         159 :     IF( EQ_16( hRenderConfig->roomAcoustics.use_er, 1 ) )
    1575             :     {
    1576           3 :         pState->pConfig.roomAcoustics.use_er = hRenderConfig->roomAcoustics.use_er;
    1577           3 :         move16();
    1578           3 :         pState->pConfig.roomAcoustics.lowComplexity = hRenderConfig->roomAcoustics.lowComplexity;
    1579           3 :         move32();
    1580             :     }
    1581             : 
    1582             :     /*  set up input downmix  */
    1583         159 :     pState->dmx_gain_fx = calc_dmx_gain_fx();
    1584             : 
    1585             :     /*  set up predelay - must be after set_base_config() and before compute_t60_coeffs() */
    1586         159 :     calc_predelay_fx( &params, hRenderConfig->roomAcoustics.acousticPreDelay_fx, output_Fs );
    1587             : 
    1588             :     /*  set up jot reverb 60 filters - must be set up after set_reverb_acoustic_data() */
    1589             : 
    1590         159 :     IF( NE_32( ( error = compute_t60_coeffs_fx( &params, nr_fc_fft_filter, output_Fs ) ), IVAS_ERR_OK ) )
    1591             :     {
    1592           0 :         return error;
    1593             :     }
    1594             :     /* Compute target levels (gains) for the coloration filters */
    1595         159 :     Word32 *pHrtf_avg_pwr_response_l_const = (Word32 *) malloc( nr_fc_fft_filter * sizeof( Word32 * ) );
    1596         159 :     Word32 *pHrtf_avg_pwr_response_r_const = (Word32 *) malloc( nr_fc_fft_filter * sizeof( Word32 * ) );
    1597         159 :     Word16 lenT60_filter_coeff = add( params.t60_filter_order, 1 );
    1598         159 :     lenT60_filter_coeff = add( i_mult( shl( lenT60_filter_coeff, 1 ), sub( params.nr_loops, 1 ) ), add( lenT60_filter_coeff, 2 ) );
    1599         159 :     Word32 *pT60_filter_coeff = (Word32 *) malloc( ( lenT60_filter_coeff ) * sizeof( Word32 * ) );
    1600             : 
    1601             : 
    1602       33214 :     FOR( i = 0; i < nr_fc_fft_filter; i++ )
    1603             :     {
    1604       33055 :         params.pDsr_fx[i] = L_shl( params.pDsr_fx[i], params.pDsr_e[i] );
    1605       33055 :         move32();
    1606       33055 :         pHrtf_avg_pwr_response_l_const[i] = L_shl( params.pHrtf_avg_pwr_response_l_const_fx[i], 5 ); /*Q23+5*/
    1607       33055 :         move32();
    1608       33055 :         pHrtf_avg_pwr_response_r_const[i] = L_shl( params.pHrtf_avg_pwr_response_r_const_fx[i], 5 ); /*Q23+5*/
    1609       33055 :         move32();
    1610             :     }
    1611        5247 :     FOR( i = 0; i < lenT60_filter_coeff; i++ )
    1612             :     {
    1613        5088 :         pT60_filter_coeff[i] = L_shl_sat( params.pT60_filter_coeff_fx[i], 17 );
    1614        5088 :         move32();
    1615             :     }
    1616         159 :     ivas_reverb_calc_color_levels_fx( output_Fs, nr_fc_fft_filter, params.nr_loops, params.pFc_fx, params.pDsr_fx, pHrtf_avg_pwr_response_l_const, pHrtf_avg_pwr_response_r_const,
    1617             :                                       params.pLoop_delays, pT60_filter_coeff, pColor_target_l_fx, pColor_target_r_fx );
    1618             : 
    1619         159 :     free( pHrtf_avg_pwr_response_l_const );
    1620         159 :     free( pHrtf_avg_pwr_response_r_const );
    1621         159 :     free( pT60_filter_coeff );
    1622             : 
    1623             :     /* Defining appropriate windowing parameters for FFT filters to prevent aliasing */
    1624         159 :     fft_hist_size = sub( pState->fft_size, pState->fft_subblock_size );
    1625             : 
    1626         159 :     transition_start = round_fx( L_mult0( FFT_FILTER_WND_FLAT_REGION_FX, fft_hist_size ) );
    1627         159 :     transition_length = round_fx( L_mult0( FFT_FILTER_WND_TRANS_REGION_FX, fft_hist_size ) );
    1628             : 
    1629             :     /* Compute the window used for FFT filters */
    1630         159 :     ivas_reverb_define_window_fft_fx( pTime_window_fx, transition_start, transition_length, nr_fc_fft_filter );
    1631             :     /* === Now, copy parameters from ivas_reverb_params_t into DSP blocks   === */
    1632             :     /* === to be used for subsequent audio signal processing                === */
    1633             : 
    1634         159 :     pState->do_corr_filter = params.do_corr_filter;
    1635         159 :     move16();
    1636             : 
    1637             :     /* clear & init jot reverb fft filters */
    1638         159 :     IF( NE_32( ( error = initialize_reverb_filters_fx( pState ) ), IVAS_ERR_OK ) )
    1639             :     {
    1640           0 :         return error;
    1641             :     }
    1642         159 :     Word16 q_pFft_wf_filter_ch0_fx = 23, q_pFft_wf_filter_ch1_fx = 23;
    1643         159 :     move16();
    1644         159 :     move16();
    1645         159 :     IF( pState->do_corr_filter )
    1646             :     {
    1647             :         /* Computing correlation filters on the basis of target IA coherence */
    1648       65951 :         FOR( i = 0; i < shl( sub( nr_fc_fft_filter, 1 ), 1 ); i++ )
    1649             :         {
    1650       65792 :             pTime_window_fx[i] = L_shr( pTime_window_fx[i], 1 ); /*Scaling signal down to 30*/
    1651       65792 :             move32();
    1652             :         }
    1653             : 
    1654         159 :         Word32 *pHrtf_inter_aural_coherence_const = (Word32 *) malloc( nr_fc_fft_filter * sizeof( Word32 ) );
    1655       33214 :         FOR( i = 0; i < nr_fc_fft_filter; i++ )
    1656             :         {
    1657       33055 :             pHrtf_inter_aural_coherence_const[i] = L_shl( params.pHrtf_inter_aural_coherence_const_fx[i], 3 ); /*Scaling up to Q30*/
    1658       33055 :             move32();
    1659             :         }
    1660         159 :         ivas_reverb_calc_correl_filters_fx( pHrtf_inter_aural_coherence_const, pTime_window_fx, pState->fft_size, pFft_wf_filter_ch0_fx, pFft_wf_filter_ch1_fx, &q_pFft_wf_filter_ch0_fx, &q_pFft_wf_filter_ch1_fx );
    1661             : 
    1662         159 :         free( pHrtf_inter_aural_coherence_const );
    1663             : 
    1664       33214 :         FOR( i = 0; i < nr_fc_fft_filter; i++ )
    1665             :         {
    1666       33055 :             pFft_wf_filter_ch0_fx[i][0] = L_shl( pFft_wf_filter_ch0_fx[i][0], sub( 31, q_pFft_wf_filter_ch0_fx ) );
    1667       33055 :             move32();
    1668       33055 :             pFft_wf_filter_ch0_fx[i][1] = L_shl( pFft_wf_filter_ch0_fx[i][1], sub( 31, q_pFft_wf_filter_ch0_fx ) );
    1669       33055 :             move32();
    1670             :         }
    1671       33214 :         FOR( i = 0; i < nr_fc_fft_filter; i++ )
    1672             :         {
    1673       33055 :             pFft_wf_filter_ch1_fx[i][0] = L_shl( pFft_wf_filter_ch1_fx[i][0], sub( 31, q_pFft_wf_filter_ch1_fx ) );
    1674       33055 :             move32();
    1675       33055 :             pFft_wf_filter_ch1_fx[i][1] = L_shl( pFft_wf_filter_ch1_fx[i][1], sub( 31, q_pFft_wf_filter_ch1_fx ) );
    1676       33055 :             move32();
    1677             :         }
    1678             :         /* Copying the computed FFT correlation filters to the fft_filter components */
    1679         159 :         IF( NE_32( ( error = set_correl_fft_filter_fx( pState, 0, pFft_wf_filter_ch0_fx ) ), IVAS_ERR_OK ) )
    1680             :         {
    1681           0 :             return error;
    1682             :         }
    1683             : 
    1684         159 :         IF( NE_32( ( error = set_correl_fft_filter_fx( pState, 1, pFft_wf_filter_ch1_fx ) ), IVAS_ERR_OK ) )
    1685             :         {
    1686           0 :             return error;
    1687             :         }
    1688             :     }
    1689             : 
    1690             :     /* Computing coloration filters on the basis of target responses */
    1691             : 
    1692         159 :     ivas_reverb_calc_color_filters_fx( pColor_target_l_fx, pColor_target_r_fx, pTime_window_fx, pState->fft_size, pFft_wf_filter_ch0_fx, pFft_wf_filter_ch1_fx, &q_pFft_wf_filter_ch0_fx, &q_pFft_wf_filter_ch1_fx );
    1693       33214 :     FOR( i = 0; i < nr_fc_fft_filter; i++ )
    1694             :     {
    1695       33055 :         pFft_wf_filter_ch0_fx[i][0] = L_shl( pFft_wf_filter_ch0_fx[i][0], sub( 31, q_pFft_wf_filter_ch0_fx ) );
    1696       33055 :         move32();
    1697       33055 :         pFft_wf_filter_ch0_fx[i][1] = L_shl( pFft_wf_filter_ch0_fx[i][1], sub( 31, q_pFft_wf_filter_ch0_fx ) );
    1698       33055 :         move32();
    1699             :     }
    1700       33214 :     FOR( i = 0; i < nr_fc_fft_filter; i++ )
    1701             :     {
    1702       33055 :         pFft_wf_filter_ch1_fx[i][0] = L_shl( pFft_wf_filter_ch1_fx[i][0], sub( 31, q_pFft_wf_filter_ch1_fx ) );
    1703       33055 :         move32();
    1704       33055 :         pFft_wf_filter_ch1_fx[i][1] = L_shl( pFft_wf_filter_ch1_fx[i][1], sub( 31, q_pFft_wf_filter_ch1_fx ) );
    1705       33055 :         move32();
    1706             :     }
    1707             : 
    1708         159 :     Scale_sig32( params.pHrtf_inter_aural_coherence_fx, nr_fc_fft_filter, 4 ); /*Scaling ( *hReverb )->fft_filter_color_0.fft_spectrum_fx to Q31*/
    1709         159 :     Scale_sig32( params.pFc_fx, nr_fc_fft_filter, 17 );                        /*Scaling  ( *hReverb )->fft_filter_color_1.fft_spectrum_fx to Q31*/
    1710             : 
    1711             :     /* Copying the computed FFT colorations filters to the fft_filter components */
    1712         159 :     IF( NE_32( ( error = set_color_fft_filter_fx( pState, 0, pFft_wf_filter_ch0_fx ) ), IVAS_ERR_OK ) )
    1713             :     {
    1714           0 :         return error;
    1715             :     }
    1716             : 
    1717         159 :     IF( NE_32( ( error = set_color_fft_filter_fx( pState, 1, pFft_wf_filter_ch1_fx ) ), IVAS_ERR_OK ) )
    1718             :     {
    1719           0 :         return error;
    1720             :     }
    1721             : 
    1722             :     /* init predelay */
    1723         159 :     ivas_rev_delay_line_init( &( pState->predelay_line ), pState->pPredelay_buffer_fx, params.pre_delay, predelay_bf_len );
    1724             : 
    1725             :     /* set up feedback delay network */
    1726         159 :     IF( NE_32( ( error = setup_FDN_branches_fx( pState, &params ) ), IVAS_ERR_OK ) )
    1727             :     {
    1728           0 :         return error;
    1729             :     }
    1730         159 :     free( pDsr_e );
    1731         159 :     free( pRt60_e );
    1732         159 :     *hReverb = pState;
    1733             : 
    1734         159 :     return error;
    1735             : }
    1736             : /*-------------------------------------------------------------------------
    1737             :  * ivas_reverb_close()
    1738             :  *
    1739             :  * Deallocate Crend reverberation handle
    1740             :  *------------------------------------------------------------------------*/
    1741             : 
    1742        4431 : void ivas_reverb_close(
    1743             :     REVERB_HANDLE *hReverb_in /* i/o: Reverberator handle       */
    1744             : )
    1745             : {
    1746             :     REVERB_HANDLE hReverb;
    1747             :     Word16 loop_idx;
    1748             : 
    1749        4431 :     hReverb = *hReverb_in;
    1750             : 
    1751        4431 :     test();
    1752        4431 :     IF( hReverb_in == NULL || *hReverb_in == NULL )
    1753             :     {
    1754        4272 :         return;
    1755             :     }
    1756             : 
    1757        1431 :     FOR( loop_idx = 0; loop_idx < IVAS_REV_MAX_NR_BRANCHES; loop_idx++ )
    1758             :     {
    1759        1272 :         IF( hReverb->loop_delay_buffer_fx[loop_idx] != NULL )
    1760             :         {
    1761        1272 :             free( hReverb->loop_delay_buffer_fx[loop_idx] );
    1762        1272 :             hReverb->loop_delay_buffer_fx[loop_idx] = NULL;
    1763             :         }
    1764             :     }
    1765             : 
    1766         159 :     free( hReverb->pPredelay_buffer_fx );
    1767         159 :     hReverb->pPredelay_buffer_fx = NULL;
    1768             : 
    1769         159 :     free( *hReverb_in );
    1770         159 :     *hReverb_in = NULL;
    1771             : 
    1772         159 :     return;
    1773             : }
    1774             : /*-----------------------------------------------------------------------------------------*
    1775             :  * Function post_fft_filter()
    1776             :  *
    1777             :  *
    1778             :  *-----------------------------------------------------------------------------------------*/
    1779             : 
    1780      353080 : static void post_fft_filter_fx(
    1781             :     REVERB_HANDLE hReverb,
    1782             :     Word32 *input_L_fx,
    1783             :     Word32 *input_R_fx,
    1784             :     Word32 *buffer_L_fx,
    1785             :     Word32 *buffer_R_fx )
    1786             : {
    1787             : 
    1788      353080 :     IF( hReverb->do_corr_filter )
    1789             :     {
    1790      353080 :         ivas_reverb_t2f_f2t_in_fx( &hReverb->fft_filter_ols, input_L_fx, input_R_fx, buffer_L_fx, buffer_R_fx );
    1791      353080 :         ivas_reverb_fft_filter_ComplexMul_fx( &hReverb->fft_filter_correl_0, buffer_L_fx );
    1792      353080 :         ivas_reverb_fft_filter_ComplexMul_fx( &hReverb->fft_filter_correl_1, buffer_R_fx );
    1793      353080 :         ivas_reverb_fft_filter_CrossMix_fx( buffer_L_fx, buffer_R_fx, hReverb->fft_filter_correl_0.fft_size );
    1794             :     }
    1795             :     ELSE
    1796             :     {
    1797           0 :         ivas_reverb_t2f_f2t_in_fx( &hReverb->fft_filter_ols, input_L_fx, input_R_fx, buffer_L_fx, buffer_R_fx );
    1798             :     }
    1799      353080 :     ivas_reverb_fft_filter_ComplexMul_fx( &hReverb->fft_filter_color_0, buffer_L_fx );
    1800      353080 :     ivas_reverb_fft_filter_ComplexMul_fx( &hReverb->fft_filter_color_1, buffer_R_fx );
    1801      353080 :     ivas_reverb_t2f_f2t_out_fx( &hReverb->fft_filter_ols, buffer_L_fx, buffer_R_fx, input_L_fx, input_R_fx );
    1802             : 
    1803      353080 :     return;
    1804             : }
    1805             : /*-----------------------------------------------------------------------------------------*
    1806             :  * Function reverb_block()
    1807             :  *
    1808             :  * Input a block (mono) and calculate the 2 output blocks.
    1809             :  *-----------------------------------------------------------------------------------------*/
    1810             : 
    1811      353080 : static void reverb_block_fx(
    1812             :     REVERB_HANDLE hReverb,
    1813             :     Word32 *pInput_fx, /*Q11*/
    1814             :     Word32 *pOut0_fx,
    1815             :     Word32 *pOut1_fx )
    1816             : 
    1817             : {
    1818      353080 :     UWord16 nr_branches = hReverb->nr_of_branches;
    1819      353080 :     UWord16 bsize = hReverb->full_block_size;
    1820      353080 :     UWord16 inner_bsize = INNER_BLK_SIZE;
    1821             :     UWord16 i, j, k, ns, branch_idx, blk_idx, start_sample_idx;
    1822             :     Word32 *pFFT_buf[2], FFT_buf_1[RV_FILTER_MAX_FFT_SIZE], FFT_buf_2[RV_FILTER_MAX_FFT_SIZE];
    1823             :     Word32 pFeedback_input_fx[INNER_BLK_SIZE];
    1824             :     Word32 pTemp_fx[INNER_BLK_SIZE];
    1825             :     Word32 *ppOutput_fx[IVAS_REV_MAX_NR_BRANCHES];
    1826             :     Word32 Output_fx[IVAS_REV_MAX_NR_BRANCHES][INNER_BLK_SIZE];
    1827      353080 :     move16();
    1828      353080 :     move16();
    1829      353080 :     move16();
    1830             : 
    1831      353080 :     pFFT_buf[0] = &FFT_buf_1[0];
    1832      353080 :     pFFT_buf[1] = &FFT_buf_2[0];
    1833             : 
    1834     3177720 :     FOR( branch_idx = 0; branch_idx < nr_branches; branch_idx++ )
    1835             :     {
    1836     2824640 :         ppOutput_fx[branch_idx] = (Word32 *) Output_fx + i_mult( branch_idx, inner_bsize );
    1837             :     }
    1838             : 
    1839     1400640 :     FOR( k = 0; k < bsize; k += inner_bsize )
    1840             :     {
    1841     1047560 :         Word32 *pO0 = &pOut0_fx[k];
    1842     1047560 :         Word32 *pO1 = &pOut1_fx[k];
    1843    84852360 :         FOR( i = 0; i < inner_bsize; i++ )
    1844             :         {
    1845    83804800 :             pO0[i] = 0;
    1846    83804800 :             move16();
    1847    83804800 :             pO1[i] = 0;
    1848    83804800 :             move16();
    1849             :         }
    1850             : 
    1851             :         /* feedback network: */
    1852     9428040 :         FOR( i = 0; i < nr_branches; i++ )
    1853             :         {
    1854     8380480 :             Word32 *pOutput_i_fx = &ppOutput_fx[i][0];
    1855     8380480 :             Word16 mixer_0_i = hReverb->mixer_fx[0][i];
    1856     8380480 :             move16();
    1857     8380480 :             Word16 mixer_1_i = hReverb->mixer_fx[1][i];
    1858     8380480 :             move16();
    1859             :             /* output and feedback are same, get sample from delay line ... */
    1860     8380480 :             ivas_rev_delay_line_get_sample_blk_fx( &( hReverb->delay_line[i] ), inner_bsize, pTemp_fx );
    1861     8380480 :             ivas_reverb_iir_filt_2taps_feed_blk_fx( &( hReverb->t60[i] ), inner_bsize, pTemp_fx, ppOutput_fx[i] );
    1862   678818880 :             FOR( ns = 0; ns < inner_bsize; ns++ )
    1863             :             {
    1864   670438400 :                 pO0[ns] = L_add_sat( imult3216( pOutput_i_fx[ns], mixer_0_i ), pO0[ns] ); /* mixer ch 0 */
    1865   670438400 :                 move32();
    1866   670438400 :                 pO1[ns] = L_add_sat( imult3216( pOutput_i_fx[ns], mixer_1_i ), pO1[ns] ); /* mixer ch 1 */
    1867   670438400 :                 move32();
    1868             :             }
    1869             :         }
    1870             : 
    1871     9428040 :         FOR( i = 0; i < nr_branches; i++ )
    1872             :         {
    1873     8380480 :             Word32 *pIn = &pInput_fx[k];
    1874             : 
    1875   678818880 :             FOR( ns = 0; ns < inner_bsize; ns++ )
    1876             :             {
    1877   670438400 :                 pFeedback_input_fx[ns] = L_shr( pIn[ns], 3 ); // to make the Qfactor similar to pOutput
    1878   670438400 :                 move32();
    1879             :             }
    1880             : 
    1881    75424320 :             FOR( j = 0; j < nr_branches; j++ )
    1882             :             {
    1883    67043840 :                 Word32 gain_matrix_j_i = hReverb->gain_matrix_fx[j][i]; // Q31
    1884    67043840 :                 move32();
    1885    67043840 :                 Word32 *pOutput = &ppOutput_fx[j][0];
    1886  5430551040 :                 FOR( ns = 0; ns < inner_bsize; ns++ )
    1887             :                 {
    1888  5363507200 :                     pFeedback_input_fx[ns] = ( L_add( Mpy_32_32( gain_matrix_j_i, pOutput[ns] ), pFeedback_input_fx[ns] ) );
    1889  5363507200 :                     move32();
    1890             :                 }
    1891             :             }
    1892             : 
    1893     8380480 :             ivas_rev_delay_line_feed_sample_blk_fx( &( hReverb->delay_line[i] ), inner_bsize, pFeedback_input_fx );
    1894             :         }
    1895             :     }
    1896             : 
    1897             :     Word16 r_shift;
    1898      353080 :     r_shift = add( find_guarded_bits_fx( hReverb->fft_filter_ols.fft_size ), 1 );
    1899             :     // Applying guard bits for the DoRTFT inside the post_fft_filter function
    1900    84157880 :     FOR( k = 0; k < hReverb->fft_filter_ols.block_size; k++ )
    1901             :     {
    1902    83804800 :         pOut0_fx[k] = (Word32) L_shr( pOut0_fx[k], ( r_shift ) );
    1903    83804800 :         move32();
    1904    83804800 :         pOut1_fx[k] = (Word32) L_shr( pOut1_fx[k], ( r_shift ) );
    1905    83804800 :         move32();
    1906             :     }
    1907             :     /* Applying FFT filter to each sub-frame */
    1908      706160 :     FOR( blk_idx = 0; blk_idx < hReverb->num_fft_subblocks; blk_idx++ )
    1909             :     {
    1910      353080 :         start_sample_idx = imult1616( blk_idx, hReverb->fft_subblock_size );
    1911      353080 :         post_fft_filter_fx( hReverb, pOut0_fx + start_sample_idx, pOut1_fx + start_sample_idx, pFFT_buf[0], pFFT_buf[1] );
    1912             :     }
    1913             : 
    1914    84157880 :     FOR( k = 0; k < hReverb->fft_filter_ols.block_size; k++ )
    1915             :     {
    1916    83804800 :         pOut0_fx[k] = (Word32) L_shl( pOut0_fx[k], 1 );
    1917    83804800 :         move32();
    1918    83804800 :         pOut1_fx[k] = (Word32) L_shl( pOut1_fx[k], 1 );
    1919    83804800 :         move32();
    1920             :     }
    1921             : 
    1922      353080 :     return;
    1923             : }
    1924             : /*-----------------------------------------------------------------------------------------*
    1925             :  * Function downmix_input_block()
    1926             :  *
    1927             :  * Downmix input to mono, taking also DSR gain into account
    1928             :  *-----------------------------------------------------------------------------------------*/
    1929             : 
    1930      353080 : static ivas_error downmix_input_block_fx(
    1931             :     const REVERB_HANDLE hReverb,
    1932             :     Word32 *pcm_in[], /* i Q11 : the input PCM audio   */
    1933             :     const AUDIO_CONFIG input_audio_config,
    1934             :     Word32 *pPcm_out, /* o Q11 : the output PCM audio   */
    1935             :     const Word16 input_offset )
    1936             : {
    1937             :     Word16 i, s, nchan_transport;
    1938      353080 :     Word32 dmx_gain_fx = hReverb->dmx_gain_fx;
    1939      353080 :     move32();
    1940      353080 :     SWITCH( input_audio_config )
    1941             :     {
    1942      353080 :         case IVAS_AUDIO_CONFIG_STEREO:
    1943             :         case IVAS_AUDIO_CONFIG_5_1:
    1944             :         case IVAS_AUDIO_CONFIG_7_1:
    1945             :         case IVAS_AUDIO_CONFIG_5_1_2:
    1946             :         case IVAS_AUDIO_CONFIG_5_1_4:
    1947             :         case IVAS_AUDIO_CONFIG_7_1_4:
    1948             :         case IVAS_AUDIO_CONFIG_ISM1:
    1949             :         case IVAS_AUDIO_CONFIG_ISM2:
    1950             :         case IVAS_AUDIO_CONFIG_ISM3:
    1951             :         case IVAS_AUDIO_CONFIG_ISM4:
    1952             :         {
    1953      353080 :             nchan_transport = audioCfg2channels( input_audio_config );
    1954    84157880 :             FOR( s = 0; s < hReverb->full_block_size; s++ )
    1955             :             {
    1956    83804800 :                 Word32 temp = pcm_in[0][add( input_offset, s )];
    1957    83804800 :                 move32();
    1958   325862400 :                 FOR( i = 1; i < nchan_transport; i++ )
    1959             :                 {
    1960   242057600 :                     temp = L_add( temp, pcm_in[i][add( input_offset, s )] );
    1961             :                 }
    1962    83804800 :                 pPcm_out[s] = W_extract_h( W_shl( W_mult0_32_32( dmx_gain_fx, temp ), 9 ) ); // ( Q23 + Q11 + Q9 ) - 32 = Q11
    1963    83804800 :                 move32();
    1964             :             }
    1965      353080 :             BREAK;
    1966             :         }
    1967           0 :         case IVAS_AUDIO_CONFIG_MONO: /* ~'ZOA_1' */
    1968             :         case IVAS_AUDIO_CONFIG_FOA:
    1969             :         case IVAS_AUDIO_CONFIG_HOA2:
    1970             :         case IVAS_AUDIO_CONFIG_HOA3:
    1971             :         {
    1972           0 :             FOR( s = 0; s < hReverb->full_block_size; s++ )
    1973             :             {
    1974           0 :                 pPcm_out[s] = Mpy_32_32( dmx_gain_fx, L_shl_sat( pcm_in[0][input_offset + s], 8 ) ); //(Q23 + Q11 + Q8) - 31 = Q11
    1975           0 :                 move32();
    1976             :             }
    1977           0 :             BREAK;
    1978             :         }
    1979           0 :         default:
    1980           0 :             return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unsupported input format for reverb" );
    1981             :     }
    1982             : 
    1983      353080 :     return IVAS_ERR_OK;
    1984             : }
    1985             : /*-----------------------------------------------------------------------------------------*
    1986             :  * Function predelay_block()
    1987             :  *
    1988             :  * Perform a predelay
    1989             :  *-----------------------------------------------------------------------------------------*/
    1990             : 
    1991      353080 : static void predelay_block_fx(
    1992             :     const REVERB_HANDLE hReverb,
    1993             :     Word32 *pInput, /*Q11*/
    1994             :     Word32 *pOutput /*Q11*/ )
    1995             : {
    1996             :     UWord16 i, idx, n_samples, blk_size;
    1997      353080 :     UWord16 max_blk_size = (UWord16) hReverb->predelay_line.Delay;
    1998      353080 :     IF( LT_32( max_blk_size, 2 ) )
    1999             :     {
    2000           0 :         IF( max_blk_size == 0 ) /* zero-length delay line: just copy the data from input to output */
    2001             :         {
    2002           0 :             FOR( i = 0; i < hReverb->full_block_size; i++ )
    2003             :             {
    2004           0 :                 pOutput[i] = pInput[i]; // Q11
    2005           0 :                 move32();
    2006             :             }
    2007             :         }
    2008             :         ELSE /* 1-sample length delay line: feed the data sample-by-sample */
    2009             :         {
    2010           0 :             FOR( i = 0; i < hReverb->full_block_size; i++ )
    2011             :             {
    2012           0 :                 pOutput[i] = ivas_rev_delay_line_get_sample_fx( &( hReverb->predelay_line ) ); // Q11
    2013           0 :                 move32();
    2014           0 :                 ivas_rev_delay_line_feed_sample_fx( &( hReverb->predelay_line ), pInput[i] );
    2015             :             }
    2016             :         }
    2017             :     }
    2018             :     ELSE /* multiple-sample length delay line: use block processing */
    2019             :     {
    2020      353080 :         idx = 0;
    2021      353080 :         move16();
    2022      353080 :         n_samples = hReverb->full_block_size;
    2023     2118480 :         WHILE( n_samples > 0 )
    2024             :         {
    2025     1765400 :             blk_size = n_samples;
    2026     1765400 :             move16();
    2027     1765400 :             if ( GT_16( blk_size, max_blk_size ) )
    2028             :             {
    2029     1412320 :                 blk_size = max_blk_size;
    2030     1412320 :                 move16();
    2031             :             }
    2032     1765400 :             ivas_rev_delay_line_get_sample_blk_fx( &( hReverb->predelay_line ), blk_size, &pOutput[idx] );
    2033     1765400 :             ivas_rev_delay_line_feed_sample_blk_fx( &( hReverb->predelay_line ), blk_size, &pInput[idx] );
    2034     1765400 :             idx = (UWord16) UL_addNsD( idx, blk_size );
    2035     1765400 :             move16();
    2036     1765400 :             n_samples = (UWord16) UL_subNsD( n_samples, blk_size );
    2037     1765400 :             move16();
    2038             :         }
    2039             :     }
    2040             : 
    2041      353080 :     return;
    2042             : }
    2043             : /*-----------------------------------------------------------------------------------------*
    2044             :  * Function mix_output_block()
    2045             :  *
    2046             :  * mix one block of *pInL and *pInR samples into *pOutL and *pOutL respectively
    2047             :  *-----------------------------------------------------------------------------------------*/
    2048             : 
    2049       99880 : static void mix_output_block_fx(
    2050             :     const REVERB_HANDLE hReverb,
    2051             :     const Word32 *pInL,
    2052             :     const Word32 *pInR,
    2053             :     Word32 *pOutL,
    2054             :     Word32 *pOutR )
    2055             : {
    2056             :     UWord16 i;
    2057             : 
    2058    23136680 :     FOR( i = 0; i < hReverb->full_block_size; i++ )
    2059             :     {
    2060    23036800 :         pOutL[i] = L_add( pInL[i], ( L_shr( pOutL[i], 2 ) ) );
    2061    23036800 :         move32();
    2062    23036800 :         pOutR[i] = L_add( pInR[i], ( L_shr( pOutR[i], 2 ) ) );
    2063    23036800 :         move32();
    2064             :     }
    2065             : 
    2066       99880 :     return;
    2067             : }
    2068             : /*-----------------------------------------------------------------------------------------*
    2069             :  * ivas_reverb_process()
    2070             :  *
    2071             :  * Process the input PCM audio into output PCM audio, applying reverb
    2072             :  *-----------------------------------------------------------------------------------------*/
    2073             : 
    2074      353080 : ivas_error ivas_reverb_process_fx(
    2075             :     const REVERB_HANDLE hReverb,           /* i  : Reverberator handle                */
    2076             :     const AUDIO_CONFIG input_audio_config, /* i  : reverb. input audio configuration  */
    2077             :     const Word16 mix_signals,              /* i  : add reverb to output signal        */
    2078             :     Word32 *pcm_in_fx[],                   /* i Q11 : the PCM audio to apply reverb on   */
    2079             :     Word32 *pcm_out_fx[],                  /* o Q11 : the PCM audio with reverb applied  */
    2080             :     const Word16 i_ts                      /* i  : subframe index                     */
    2081             : )
    2082             : {
    2083             :     Word32 tmp0_fx[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp1_fx[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp2_fx[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES];
    2084             :     ivas_error error;
    2085             : 
    2086      353080 :     IF( NE_32( ( error = downmix_input_block_fx( hReverb, pcm_in_fx, input_audio_config, tmp1_fx, i_ts * hReverb->full_block_size ) ), IVAS_ERR_OK ) )
    2087             :     {
    2088           0 :         return error;
    2089             :     }
    2090             : 
    2091      353080 :     predelay_block_fx( hReverb, tmp1_fx, tmp0_fx );
    2092             : 
    2093      353080 :     reverb_block_fx( hReverb, tmp0_fx, tmp1_fx, tmp2_fx );
    2094             : 
    2095      353080 :     IF( mix_signals )
    2096             :     {
    2097       99880 :         mix_output_block_fx( hReverb, tmp1_fx, tmp2_fx, &pcm_out_fx[0][i_ts * hReverb->full_block_size], &pcm_out_fx[1][i_ts * hReverb->full_block_size] );
    2098             :     }
    2099             :     ELSE
    2100             :     {
    2101      253200 :         MVR2R_WORD32( tmp1_fx, &pcm_out_fx[0][i_mult( i_ts, hReverb->full_block_size )], hReverb->full_block_size );
    2102      253200 :         MVR2R_WORD32( tmp2_fx, &pcm_out_fx[1][i_mult( i_ts, hReverb->full_block_size )], hReverb->full_block_size );
    2103             :     }
    2104             : 
    2105      353080 :     return IVAS_ERR_OK;
    2106             : }
    2107             : 
    2108             : /*-------------------------------------------------------------------------
    2109             :  * ivas_binaural_reverb_processSubFrame()
    2110             :  *
    2111             :  * Compute the reverberation - room effect
    2112             :  *------------------------------------------------------------------------*/
    2113             : 
    2114             : 
    2115             : /*-------------------------------------------------------------------------
    2116             :  * ivas_binaural_reverb_processSubFrame_fx()
    2117             :  *
    2118             :  * Compute the reverberation - room effect
    2119             :  *------------------------------------------------------------------------*/
    2120             : 
    2121      112972 : void ivas_binaural_reverb_processSubframe_fx(
    2122             :     REVERB_STRUCT_HANDLE hReverb,                                      /* i/o: binaural reverb handle      */
    2123             :     const Word16 numInChannels,                                        /* i  : num inputs to be processed  */
    2124             :     const Word16 numSlots,                                             /* i  : number of slots to be processed    */
    2125             :     Word32 inReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],  /* i (Q_in) : input CLDFB data real, Comment: This change swaps two first dimensions as first dimension is not constant. */
    2126             :     Word32 inImag[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],  /* i (Q_in) : input CLDFB data imag       */
    2127             :     Word32 outReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o (Q_in) : output CLDFB data real      */
    2128             :     Word32 outImag[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]  /* o (Q_in) : output CLDFB data imag      */
    2129             : )
    2130             : {
    2131             :     /* Declare the required variables */
    2132             :     Word16 idx, bin, ch, sample, invertSampleIndex, tapIdx, *phaseShiftTypePr;
    2133             :     Word32 **tapRealPr_fx, **tapImagPr_fx;
    2134      112972 :     push_wmops( "binaural_reverb" );
    2135             : 
    2136             :     /* 1) Rotate the data in the loop buffer of the reverberator.
    2137             :      * Notice that the audio at the loop buffers is at time-inverted order
    2138             :      * for convolution purposes later on. */
    2139     5361772 :     FOR( bin = 0; bin < hReverb->numBins; bin++ )
    2140             :     {
    2141             :         /* Move the data forwards by blockSize (i.e. by the frame size of 16 CLDFB slots) */
    2142     5248800 :         Copy32( hReverb->loopBufReal_fx[bin], hReverb->loopBufReal_fx[bin] + numSlots, hReverb->loopBufLength[bin] );
    2143     5248800 :         Copy32( hReverb->loopBufImag_fx[bin], hReverb->loopBufImag_fx[bin] + numSlots, hReverb->loopBufLength[bin] );
    2144             : 
    2145             :         /* Add the data from the end of the loop to the beginning, with an attenuation factor
    2146             :          * according to RT60. This procedure generates an IIR decaying response. The response
    2147             :          * is decorrelated later on. */
    2148     5248800 :         v_multc_fixed( hReverb->loopBufReal_fx[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor_fx[bin], hReverb->loopBufReal_fx[bin], numSlots );
    2149     5248800 :         v_multc_fixed( hReverb->loopBufImag_fx[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor_fx[bin], hReverb->loopBufImag_fx[bin], numSlots );
    2150             :     }
    2151             : 
    2152             :     /* 2) Apply the determined pre-delay to the input audio, and add the delayed audio to the loop. */
    2153      112972 :     idx = hReverb->preDelayBufferIndex;
    2154      562594 :     FOR( sample = 0; sample < numSlots; sample++ )
    2155             :     {
    2156      449622 :         invertSampleIndex = sub( sub( numSlots, sample ), 1 );
    2157             : 
    2158    21314822 :         FOR( bin = 0; bin < hReverb->numBins; bin++ )
    2159             :         {
    2160             :             /* Add from pre-delay buffer a sample to the loop buffer, in a time-inverted order.
    2161             :              * Also apply the spectral gains determined for the reverberation */
    2162    20865200 :             Word32 temp_1 = Mpy_32_32( hReverb->preDelayBufferReal_fx[idx][bin], hReverb->reverbEqGains_fx[bin] );              /*Q_in*/
    2163    20865200 :             Word32 temp_2 = Mpy_32_32( hReverb->preDelayBufferImag_fx[idx][bin], hReverb->reverbEqGains_fx[bin] );              /*Q_in*/
    2164    20865200 :             hReverb->loopBufReal_fx[bin][invertSampleIndex] = L_add( hReverb->loopBufReal_fx[bin][invertSampleIndex], temp_1 ); /*Q_in*/
    2165    20865200 :             move32();
    2166    20865200 :             hReverb->loopBufImag_fx[bin][invertSampleIndex] = L_add( hReverb->loopBufImag_fx[bin][invertSampleIndex], temp_2 ); /*Q_in*/
    2167    20865200 :             move32();
    2168    20865200 :             hReverb->preDelayBufferReal_fx[idx][bin] = 0;
    2169    20865200 :             move32();
    2170    20865200 :             hReverb->preDelayBufferImag_fx[idx][bin] = 0;
    2171    20865200 :             move32();
    2172             :         }
    2173             : 
    2174             :         /* Add every second input channel as is to the pre-delay buffer, and every second input channel with
    2175             :          * 90 degrees phase shift to reduce energy imbalances between coherent and incoherent sounds */
    2176     1370663 :         FOR( ch = 0; ch < numInChannels; ch++ )
    2177             :         {
    2178      921041 :             IF( s_and( ch, 1 ) )
    2179             :             {
    2180             : #ifdef VEC_ARITH_OPT_v1
    2181      455702 :                 v_add_fixed_no_hdrm( hReverb->preDelayBufferReal_fx[idx], inReal[ch][sample], hReverb->preDelayBufferReal_fx[idx], hReverb->numBins );
    2182      455702 :                 v_add_fixed_no_hdrm( hReverb->preDelayBufferImag_fx[idx], inImag[ch][sample], hReverb->preDelayBufferImag_fx[idx], hReverb->numBins );
    2183             : #else  /* VEC_ARITH_OPT_v1 */
    2184             :                 v_add_fixed( hReverb->preDelayBufferReal_fx[idx], inReal[ch][sample], hReverb->preDelayBufferReal_fx[idx], hReverb->numBins, 0 );
    2185             :                 v_add_fixed( hReverb->preDelayBufferImag_fx[idx], inImag[ch][sample], hReverb->preDelayBufferImag_fx[idx], hReverb->numBins, 0 );
    2186             : #endif /* VEC_ARITH_OPT_v1 */
    2187             :             }
    2188             :             ELSE
    2189             :             {
    2190             : #ifdef VEC_ARITH_OPT_v1
    2191      465339 :                 v_sub_fixed_no_hdrm( hReverb->preDelayBufferReal_fx[idx], inImag[ch][sample], hReverb->preDelayBufferReal_fx[idx], hReverb->numBins );
    2192      465339 :                 v_add_fixed_no_hdrm( hReverb->preDelayBufferImag_fx[idx], inReal[ch][sample], hReverb->preDelayBufferImag_fx[idx], hReverb->numBins );
    2193             : #else  /* VEC_ARITH_OPT_v1 */
    2194             :                 v_sub_fixed( hReverb->preDelayBufferReal_fx[idx], inImag[ch][sample], hReverb->preDelayBufferReal_fx[idx], hReverb->numBins, 0 );
    2195             :                 v_add_fixed( hReverb->preDelayBufferImag_fx[idx], inReal[ch][sample], hReverb->preDelayBufferImag_fx[idx], hReverb->numBins, 0 );
    2196             : #endif /* VEC_ARITH_OPT_v1 */
    2197             :             }
    2198             :         }
    2199      449622 :         idx = add( idx, 1 ) % hReverb->preDelayBufferLength;
    2200      449622 :         move16();
    2201             :     }
    2202      112972 :     hReverb->preDelayBufferIndex = idx;
    2203      112972 :     move16();
    2204             : 
    2205             :     /* 3) Perform the filtering/decorrelating, using complex and sparse FIR filtering */
    2206     5361772 :     FOR( bin = 0; bin < hReverb->numBins; bin++ )
    2207             :     {
    2208    15746400 :         FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2209             :         {
    2210             :             /* These tap pointers have been determined to point to the loop buffer at sparse locations */
    2211    10497600 :             tapRealPr_fx = hReverb->tapPointersReal_fx[bin][ch];
    2212    10497600 :             tapImagPr_fx = hReverb->tapPointersImag_fx[bin][ch];
    2213             : 
    2214    10497600 :             phaseShiftTypePr = hReverb->tapPhaseShiftType[bin][ch];
    2215             : 
    2216             :             /* Flush output */
    2217    10497600 :             set32_fx( hReverb->outputBufferReal_fx[bin][ch], 0, numSlots );
    2218    10497600 :             set32_fx( hReverb->outputBufferImag_fx[bin][ch], 0, numSlots );
    2219             : 
    2220             :             /* Add from temporally decaying sparse tap locations the audio to the output. */
    2221   148955684 :             FOR( tapIdx = 0; tapIdx < hReverb->taps[bin][ch]; tapIdx++ )
    2222             :             {
    2223   138458084 :                 SWITCH( phaseShiftTypePr[tapIdx] )
    2224             :                 {
    2225    32232560 :                     case 0: /* 0 degrees phase */
    2226             : #ifdef VEC_ARITH_OPT_v1
    2227    32232560 :                         v_add_fixed_no_hdrm( hReverb->outputBufferReal_fx[bin][ch], tapRealPr_fx[tapIdx], hReverb->outputBufferReal_fx[bin][ch], numSlots );
    2228    32232560 :                         v_add_fixed_no_hdrm( hReverb->outputBufferImag_fx[bin][ch], tapImagPr_fx[tapIdx], hReverb->outputBufferImag_fx[bin][ch], numSlots );
    2229             : #else  /* VEC_ARITH_OPT_v1 */
    2230             :                         v_add_fixed( hReverb->outputBufferReal_fx[bin][ch], tapRealPr_fx[tapIdx], hReverb->outputBufferReal_fx[bin][ch], numSlots, 0 );
    2231             :                         v_add_fixed( hReverb->outputBufferImag_fx[bin][ch], tapImagPr_fx[tapIdx], hReverb->outputBufferImag_fx[bin][ch], numSlots, 0 );
    2232             : #endif /* VEC_ARITH_OPT_v1 */
    2233    32232560 :                         BREAK;
    2234    38307988 :                     case 1: /* 90 degrees phase */
    2235             : #ifdef VEC_ARITH_OPT_v1
    2236    38307988 :                         v_sub_fixed_no_hdrm( hReverb->outputBufferReal_fx[bin][ch], tapImagPr_fx[tapIdx], hReverb->outputBufferReal_fx[bin][ch], numSlots );
    2237    38307988 :                         v_add_fixed_no_hdrm( hReverb->outputBufferImag_fx[bin][ch], tapRealPr_fx[tapIdx], hReverb->outputBufferImag_fx[bin][ch], numSlots );
    2238             : #else  /* VEC_ARITH_OPT_v1 */
    2239             :                         v_sub_fixed( hReverb->outputBufferReal_fx[bin][ch], tapImagPr_fx[tapIdx], hReverb->outputBufferReal_fx[bin][ch], numSlots, 0 );
    2240             :                         v_add_fixed( hReverb->outputBufferImag_fx[bin][ch], tapRealPr_fx[tapIdx], hReverb->outputBufferImag_fx[bin][ch], numSlots, 0 );
    2241             : #endif /* VEC_ARITH_OPT_v1 */
    2242    38307988 :                         BREAK;
    2243    34487496 :                     case 2: /* 180 degrees phase */
    2244             : #ifdef VEC_ARITH_OPT_v1
    2245    34487496 :                         v_sub_fixed_no_hdrm( hReverb->outputBufferReal_fx[bin][ch], tapRealPr_fx[tapIdx], hReverb->outputBufferReal_fx[bin][ch], numSlots );
    2246    34487496 :                         v_sub_fixed_no_hdrm( hReverb->outputBufferImag_fx[bin][ch], tapImagPr_fx[tapIdx], hReverb->outputBufferImag_fx[bin][ch], numSlots );
    2247             : #else  /* VEC_ARITH_OPT_v1 */
    2248             :                         v_sub_fixed( hReverb->outputBufferReal_fx[bin][ch], tapRealPr_fx[tapIdx], hReverb->outputBufferReal_fx[bin][ch], numSlots, 0 );
    2249             :                         v_sub_fixed( hReverb->outputBufferImag_fx[bin][ch], tapImagPr_fx[tapIdx], hReverb->outputBufferImag_fx[bin][ch], numSlots, 0 );
    2250             : #endif /* VEC_ARITH_OPT_v1 */
    2251    34487496 :                         BREAK;
    2252    33430040 :                     default: /* 270 degrees phase */
    2253             : #ifdef VEC_ARITH_OPT_v1
    2254    33430040 :                         v_add_fixed_no_hdrm( hReverb->outputBufferReal_fx[bin][ch], tapImagPr_fx[tapIdx], hReverb->outputBufferReal_fx[bin][ch], numSlots );
    2255    33430040 :                         v_sub_fixed_no_hdrm( hReverb->outputBufferImag_fx[bin][ch], tapRealPr_fx[tapIdx], hReverb->outputBufferImag_fx[bin][ch], numSlots );
    2256             : #else  /* VEC_ARITH_OPT_v1 */
    2257             :                         v_add_fixed( hReverb->outputBufferReal_fx[bin][ch], tapImagPr_fx[tapIdx], hReverb->outputBufferReal_fx[bin][ch], numSlots, 0 );
    2258             :                         v_sub_fixed( hReverb->outputBufferImag_fx[bin][ch], tapRealPr_fx[tapIdx], hReverb->outputBufferImag_fx[bin][ch], numSlots, 0 );
    2259             : #endif /* VEC_ARITH_OPT_v1 */
    2260    33430040 :                         BREAK;
    2261             :                 }
    2262             :             }
    2263             :         }
    2264             : 
    2265             :         /* Generate diffuse field binaural coherence by mixing the incoherent reverberated channels with pre-defined gains */
    2266     5248800 :         IF( LE_16( bin, hReverb->highestBinauralCoherenceBin ) )
    2267             :         {
    2268      790804 :             IF( hReverb->useBinauralCoherence )
    2269             :             {
    2270     3938158 :                 FOR( sample = 0; sample < numSlots; sample++ )
    2271             :                 {
    2272             :                     Word32 leftRe_fx, rightRe_fx, leftIm_fx, rightIm_fx;
    2273             : 
    2274     3147354 :                     leftRe_fx = L_add( Mpy_32_32( hReverb->binauralCoherenceDirectGains_fx[bin], hReverb->outputBufferReal_fx[bin][0][sample] ),
    2275     3147354 :                                        Mpy_32_32( hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferReal_fx[bin][1][sample] ) ); // Q_in
    2276     3147354 :                     rightRe_fx = L_add( Mpy_32_32( hReverb->binauralCoherenceDirectGains_fx[bin], hReverb->outputBufferReal_fx[bin][1][sample] ),
    2277     3147354 :                                         Mpy_32_32( hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferReal_fx[bin][0][sample] ) ); // Q_in
    2278     3147354 :                     leftIm_fx = L_add( Mpy_32_32( hReverb->binauralCoherenceDirectGains_fx[bin], hReverb->outputBufferImag_fx[bin][0][sample] ),
    2279     3147354 :                                        Mpy_32_32( hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferImag_fx[bin][1][sample] ) ); // Q_in
    2280     3147354 :                     rightIm_fx = L_add( Mpy_32_32( hReverb->binauralCoherenceDirectGains_fx[bin], hReverb->outputBufferImag_fx[bin][1][sample] ),
    2281     3147354 :                                         Mpy_32_32( hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferImag_fx[bin][0][sample] ) ); // Q_in
    2282             : 
    2283     3147354 :                     hReverb->outputBufferReal_fx[bin][0][sample] = leftRe_fx; // Q_in
    2284     3147354 :                     move32();
    2285     3147354 :                     hReverb->outputBufferReal_fx[bin][1][sample] = rightRe_fx; // Q_in
    2286     3147354 :                     move32();
    2287     3147354 :                     hReverb->outputBufferImag_fx[bin][0][sample] = leftIm_fx; // Q_in
    2288     3147354 :                     move32();
    2289     3147354 :                     hReverb->outputBufferImag_fx[bin][1][sample] = rightIm_fx; // Q_in
    2290     3147354 :                     move32();
    2291             :                 }
    2292             :             }
    2293             :         }
    2294             :     }
    2295             : 
    2296             :     /* 4) Write data to output */
    2297      338916 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2298             :     {
    2299     1125188 :         FOR( sample = 0; sample < numSlots; sample++ )
    2300             :         {
    2301             :             /* Audio was in the temporally inverted order for convolution, re-invert audio to output */
    2302      899244 :             invertSampleIndex = sub( sub( numSlots, sample ), 1 );
    2303             : 
    2304    42629644 :             FOR( bin = 0; bin < hReverb->numBins; bin++ )
    2305             :             {
    2306    41730400 :                 outReal[ch][sample][bin] = hReverb->outputBufferReal_fx[bin][ch][invertSampleIndex]; // Q_in
    2307    41730400 :                 move32();
    2308    41730400 :                 outImag[ch][sample][bin] = hReverb->outputBufferImag_fx[bin][ch][invertSampleIndex]; // Q_in
    2309    41730400 :                 move32();
    2310             :             }
    2311    13123484 :             FOR( ; bin < CLDFB_NO_CHANNELS_MAX; bin++ )
    2312             :             {
    2313    12224240 :                 outReal[ch][sample][bin] = 0;
    2314    12224240 :                 move32();
    2315    12224240 :                 outImag[ch][sample][bin] = 0;
    2316    12224240 :                 move32();
    2317             :             }
    2318             :         }
    2319             :     }
    2320             : 
    2321      112972 :     pop_wmops();
    2322      112972 :     return;
    2323             : }
    2324             : 
    2325             : /*-------------------------------------------------------------------------
    2326             :  * ivas_binaural_reverb_open()
    2327             :  *
    2328             :  * Allocate and initialize binaural room reverberator handle
    2329             :  *------------------------------------------------------------------------*/
    2330         271 : static ivas_error ivas_binaural_reverb_open_fx(
    2331             :     REVERB_STRUCT_HANDLE *hReverbPr,    /* i/o: binaural reverb handle                                  */
    2332             :     const Word16 numBins,               /* i  : Q0 number of CLDFB bins                                    */
    2333             :     const Word16 numCldfbSlotsPerFrame, /* i  : Q0 number of CLDFB slots per frame                         */
    2334             :     const Word32 sampling_rate,         /* i  : Q0 sampling rate                                           */
    2335             :     const Word32 *revTimes_fx,          /* i  : Q31 reverberation times T60 for each CLDFB bin in seconds   */
    2336             :     const Word32 *revEnes_fx,           /* i  : Q31 spectrum for reverberated sound at each CLDFB bin       */
    2337             :     const Word16 preDelay               /* i  : Q0 reverb pre-delay in CLDFB slots                         */
    2338             : )
    2339             : {
    2340             :     Word16 bin, chIdx, k, len, scale, tmp;
    2341             :     REVERB_STRUCT_HANDLE hReverb;
    2342             : 
    2343         271 :     IF( ( *hReverbPr = (REVERB_STRUCT_HANDLE) malloc( sizeof( REVERB_STRUCT ) ) ) == NULL )
    2344             :     {
    2345           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    2346             :     }
    2347             : 
    2348         271 :     hReverb = *hReverbPr;
    2349             : 
    2350         271 :     hReverb->useBinauralCoherence = 1;
    2351         271 :     move16();
    2352         271 :     hReverb->preDelayBufferLength = 1;
    2353         271 :     move16();
    2354         271 :     hReverb->preDelayBufferIndex = 0;
    2355         271 :     move16();
    2356             : 
    2357         271 :     hReverb->numBins = numBins;
    2358         271 :     move16();
    2359         271 :     hReverb->blockSize = numCldfbSlotsPerFrame;
    2360         271 :     move16();
    2361             : 
    2362        5962 :     FOR( k = 0; k < REVERB_PREDELAY_MAX + 1; k++ )
    2363             :     {
    2364        5691 :         set32_fx( hReverb->preDelayBufferReal_fx[k], 0, hReverb->numBins );
    2365        5691 :         set32_fx( hReverb->preDelayBufferImag_fx[k], 0, hReverb->numBins );
    2366             :     }
    2367             : 
    2368       12371 :     FOR( bin = 0; bin < hReverb->numBins; bin++ )
    2369             :     {
    2370             :         /* Loop Buffer */
    2371             : 
    2372       12100 :         tmp = BASOP_Util_Divide1616_Scale( 500, add( bin, 1 ), &scale );
    2373       12100 :         tmp = shr( tmp, sub( 15, scale ) );
    2374       12100 :         hReverb->loopBufLengthMax[bin] = add( tmp, sub( CLDFB_NO_CHANNELS_MAX, bin ) );
    2375             :         // hReverb->loopBufLengthMax[bin] = (Word16) ( 500 / ( 1 + bin ) + ( CLDFB_NO_CHANNELS_MAX - bin ) );
    2376             : 
    2377       12100 :         len = add( hReverb->loopBufLengthMax[bin], hReverb->blockSize );
    2378             : 
    2379       12100 :         IF( ( hReverb->loopBufReal_fx[bin] = (Word32 *) malloc( len * sizeof( Word32 ) ) ) == NULL )
    2380             :         {
    2381           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    2382             :         }
    2383             : 
    2384       12100 :         if ( ( hReverb->loopBufImag_fx[bin] = (Word32 *) malloc( len * sizeof( Word32 ) ) ) == NULL )
    2385             :         {
    2386           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    2387             :         }
    2388       12100 :         set32_fx( hReverb->loopBufReal_fx[bin], 0, len );
    2389       12100 :         set32_fx( hReverb->loopBufImag_fx[bin], 0, len );
    2390             : 
    2391             :         /* Determine loop buffer length. The following formula is manually tuned to generate sufficiently long
    2392             :          * but not excessively long loops to generate reverberation. */
    2393             :         /* Note: the resulted length is very sensitive to the precision of the constants below (e.g. 1.45 vs. 1.45f) */
    2394             :         // hReverb->loopBufLength[bin] = (int16_t) ( 1.45 * (int16_t) ( revTimes[bin] * 150.0 ) + 1 );
    2395       12100 :         Word32 L_tmp_BufLength = L_shl( L_shr( Mpy_32_32( revTimes_fx[bin], 1258291200 /*150.0 in Q23*/ ), 23 ), 23 );
    2396       12100 :         L_tmp_BufLength = L_add( Mpy_32_32( 1556925645 /*1.45 in Q30*/, L_tmp_BufLength ), ONE_IN_Q22 );
    2397       12100 :         hReverb->loopBufLength[bin] = (Word16) L_shr( L_tmp_BufLength, 22 ); /*Q0*/
    2398       12100 :         move16();
    2399       12100 :         hReverb->loopBufLength[bin] = s_min( hReverb->loopBufLength[bin], hReverb->loopBufLengthMax[bin] );
    2400             : 
    2401             :         /* Sparse Filter Tap Locations */
    2402       36300 :         FOR( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ )
    2403             :         {
    2404       24200 :             len = hReverb->loopBufLength[bin];
    2405       24200 :             move16();
    2406             : 
    2407       24200 :             IF( ( hReverb->tapPhaseShiftType[bin][chIdx] = (Word16 *) malloc( len * sizeof( Word16 ) ) ) == NULL )
    2408             :             {
    2409           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    2410             :             }
    2411       24200 :             set16_fx( hReverb->tapPhaseShiftType[bin][chIdx], 0, len );
    2412             : 
    2413       24200 :             IF( ( hReverb->tapPointersReal_fx[bin][chIdx] = (Word32 **) malloc( len * sizeof( Word32 * ) ) ) == NULL )
    2414             :             {
    2415           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    2416             :             }
    2417             : 
    2418       24200 :             IF( ( hReverb->tapPointersImag_fx[bin][chIdx] = (Word32 **) malloc( len * sizeof( Word32 * ) ) ) == NULL )
    2419             :             {
    2420           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    2421             :             }
    2422             : 
    2423       24200 :             len = hReverb->blockSize;
    2424       24200 :             move16();
    2425       24200 :             IF( ( hReverb->outputBufferReal_fx[bin][chIdx] = (Word32 *) malloc( len * sizeof( Word32 ) ) ) == NULL )
    2426             :             {
    2427           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    2428             :             }
    2429             : 
    2430       24200 :             IF( ( hReverb->outputBufferImag_fx[bin][chIdx] = (Word32 *) malloc( len * sizeof( Word32 ) ) ) == NULL )
    2431             :             {
    2432           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
    2433             :             }
    2434       24200 :             set32_fx( hReverb->outputBufferReal_fx[bin][chIdx], 0, len );
    2435       24200 :             set32_fx( hReverb->outputBufferImag_fx[bin][chIdx], 0, len );
    2436             :         }
    2437             :     }
    2438             : 
    2439         271 :     ivas_binaural_reverb_setReverbTimes_fx( hReverb, sampling_rate, revTimes_fx, revEnes_fx );
    2440             : 
    2441             :     /*free(revTimes_fx);
    2442             :     free(revEnes_fx);*/
    2443             : 
    2444         271 :     ivas_binaural_reverb_setPreDelay_fx( hReverb, preDelay );
    2445             : 
    2446         271 :     return IVAS_ERR_OK;
    2447             : }
    2448             : 
    2449             : /*-------------------------------------------------------------------------
    2450             :  * ivas_binaural_reverb_open_fastconv()
    2451             :  *
    2452             :  * Allocate and initialize binaural room reverberator handle for FastConv
    2453             :  *------------------------------------------------------------------------*/
    2454           0 : ivas_error ivas_binaural_reverb_open_fastconv_fx(
    2455             :     REVERB_STRUCT_HANDLE *hReverbPr,                /* i/o: binaural reverb handle               */
    2456             :     const Word16 numBins,                           /* i  : number of CLDFB bins                 */
    2457             :     const Word16 numCldfbSlotsPerFrame,             /* i  : number of CLDFB slots per frame      */
    2458             :     IVAS_ROOM_ACOUSTICS_CONFIG_DATA *roomAcoustics, /* i/o: room acoustics parameters            */
    2459             :     const AUDIO_CONFIG internal_config,             /* i  : internal audio config for FastConv   */
    2460             :     const Word32 sampling_rate,                     /* i  : sampling rate                        */
    2461             :     const HRTFS_FASTCONV_HANDLE hHrtfFastConv       /* i  : FastConv HRTF handle                 */
    2462             : )
    2463             : {
    2464             :     ivas_error error;
    2465             :     const Word32 *revTimes;
    2466             :     const Word32 *revEne;
    2467             :     Word32 t60[CLDFB_NO_CHANNELS_MAX];
    2468             :     Word32 ene[CLDFB_NO_CHANNELS_MAX];
    2469             :     Word16 preDelay;
    2470             : 
    2471           0 :     error = IVAS_ERR_OK;
    2472             : 
    2473           0 :     IF( ( roomAcoustics != NULL ) && roomAcoustics->override )
    2474           0 :     {
    2475             :         /* THIS PART IS YET TO BE CONVERTED AS REVERB_UTILS.C IS NOT INVOKED IN GPROF */
    2476             :         float t60_flt[CLDFB_NO_CHANNELS_MAX];
    2477             :         float ene_flt[CLDFB_NO_CHANNELS_MAX];
    2478           0 :         revTimes = t60;
    2479           0 :         revEne = ene;
    2480           0 :         if ( NE_32( ( error = ivas_reverb_prepare_cldfb_params( roomAcoustics,
    2481             :                                                                 hHrtfFastConv,
    2482             :                                                                 internal_config,
    2483             :                                                                 false,
    2484             :                                                                 sampling_rate, t60_flt, ene_flt ) ),
    2485             :                     IVAS_ERR_OK ) )
    2486             :         {
    2487           0 :             return error;
    2488             :         }
    2489           0 :         preDelay = (Word16) roundf( 48000.0f * roomAcoustics->acousticPreDelay / CLDFB_NO_CHANNELS_MAX );
    2490           0 :         floatToFixed_arrL( t60_flt, t60, Q31, CLDFB_NO_CHANNELS_MAX );
    2491           0 :         floatToFixed_arrL( ene_flt, ene, Q31, CLDFB_NO_CHANNELS_MAX );
    2492             :     }
    2493             :     ELSE
    2494             :     {
    2495           0 :         revTimes = hHrtfFastConv->fastconvReverberationTimes_fx;        /*Q31*/
    2496           0 :         revEne = hHrtfFastConv->fastconvReverberationEneCorrections_fx; /*Q31*/
    2497           0 :         preDelay = 10;
    2498           0 :         move16();
    2499             :     }
    2500             : 
    2501           0 :     error = ivas_binaural_reverb_open_fx( hReverbPr, numBins, numCldfbSlotsPerFrame, sampling_rate, revTimes, revEne, preDelay );
    2502             : 
    2503           0 :     return error;
    2504             : }
    2505             : 
    2506             : /*-------------------------------------------------------------------------
    2507             :  * ivas_binaural_reverb_open_parambin()
    2508             :  *
    2509             :  * Allocate and initialize binaural room reverberator handle for ParamBin
    2510             :  *------------------------------------------------------------------------*/
    2511         271 : ivas_error ivas_binaural_reverb_open_parambin(
    2512             :     REVERB_STRUCT_HANDLE *hReverbPr,                /* i/o: binaural reverb handle               */
    2513             :     const Word16 numBins,                           /* i  : number of CLDFB bins Q0                 */
    2514             :     const Word16 numCldfbSlotsPerFrame,             /* i  : number of CLDFB slots per frame Q0      */
    2515             :     IVAS_ROOM_ACOUSTICS_CONFIG_DATA *roomAcoustics, /* i/o: room acoustics parameters            */
    2516             :     const Word32 sampling_rate,                     /* i  : sampling rate Q0                         */
    2517             :     const HRTFS_PARAMBIN_HANDLE hHrtfParambin       /* i  : Parametric binauralizer HRTF handle  */
    2518             : )
    2519             : {
    2520             :     ivas_error error;
    2521             :     const Word32 *revTimes;
    2522             :     const Word32 *revEne;
    2523             :     Word32 t60[CLDFB_NO_CHANNELS_MAX];
    2524             :     Word32 ene[CLDFB_NO_CHANNELS_MAX];
    2525             :     Word16 preDelay;
    2526             : 
    2527         271 :     error = IVAS_ERR_OK;
    2528             : 
    2529         271 :     IF( ( roomAcoustics != NULL ) && roomAcoustics->override )
    2530             :     {
    2531           0 :         revTimes = t60;
    2532           0 :         revEne = ene;
    2533           0 :         preDelay = (Word16) L_shr_r( Mpy_32_32( 1677721600 /*800 in Q21*/, roomAcoustics->acousticPreDelay_fx /*Q27*/ ), Q17 ); /*Q0*/
    2534           0 :         move16();
    2535             :     }
    2536             :     ELSE
    2537             :     {
    2538         271 :         revTimes = hHrtfParambin->parametricReverberationTimes_fx;        /*Q31*/
    2539         271 :         revEne = hHrtfParambin->parametricReverberationEneCorrections_fx; /*Q31*/
    2540         271 :         preDelay = 10;
    2541         271 :         move16();
    2542             :     }
    2543             : 
    2544         271 :     error = ivas_binaural_reverb_open_fx( hReverbPr, numBins, numCldfbSlotsPerFrame, sampling_rate, revTimes, revEne, preDelay );
    2545             : 
    2546         271 :     return error;
    2547             : }
    2548             : 
    2549             : /*-------------------------------------------------------------------------
    2550             :  * ivas_binaural_reverb_close()
    2551             :  *
    2552             :  * Close binaural room reverberator handle
    2553             :  *------------------------------------------------------------------------*/
    2554             : 
    2555         271 : void ivas_binaural_reverb_close_fx(
    2556             :     REVERB_STRUCT_HANDLE *hReverb /* i/o: binaural reverb handle */
    2557             : )
    2558             : {
    2559             :     Word16 bin, chIdx;
    2560             : 
    2561         271 :     test();
    2562         271 :     IF( hReverb == NULL || *hReverb == NULL )
    2563             :     {
    2564           0 :         return;
    2565             :     }
    2566             : 
    2567       12371 :     FOR( bin = 0; bin < ( *hReverb )->numBins; bin++ )
    2568             :     {
    2569       36300 :         FOR( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ )
    2570             :         {
    2571       24200 :             free( ( *hReverb )->tapPhaseShiftType[bin][chIdx] );
    2572       24200 :             free( ( *hReverb )->tapPointersReal_fx[bin][chIdx] );
    2573       24200 :             free( ( *hReverb )->tapPointersImag_fx[bin][chIdx] );
    2574       24200 :             free( ( *hReverb )->outputBufferReal_fx[bin][chIdx] );
    2575       24200 :             free( ( *hReverb )->outputBufferImag_fx[bin][chIdx] );
    2576             :         }
    2577       12100 :         free( ( *hReverb )->loopBufReal_fx[bin] );
    2578       12100 :         free( ( *hReverb )->loopBufImag_fx[bin] );
    2579             :     }
    2580             : 
    2581         271 :     free( ( *hReverb ) );
    2582         271 :     ( *hReverb ) = NULL;
    2583             : 
    2584         271 :     return;
    2585             : }

Generated by: LCOV version 1.14