LCOV - code coverage report
Current view: top level - lib_rend - ivas_reverb.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 14fa671a0e9ecae0631dc716f445f21ff3af3ff8 Lines: 590 671 87.9 %
Date: 2026-01-11 05:19:33 Functions: 35 35 100.0 %

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

Generated by: LCOV version 1.14