Commit b949d48c authored by Tapani Pihlajakuja's avatar Tapani Pihlajakuja
Browse files

Merge branch '511-optimise-target-gain-computation-in-parametric-binauralizer' into 'main'

Resolve "Optimise target gain computation in parametric binauralizer."

See merge request !690
parents d9d21b15 98cade9b
Loading
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -243,6 +243,7 @@
#define BINAURAL_AUDIO_CMDLINE
#define FIX_570_TCX_LPC_WRITE                           /* FhG: fix issue 570: LPC bitstream writer in TCX */
#define FIX_506                                         /* FhG: Compiler warnings */
#define FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH            /* Nokia: Issue 511, significant optimization of parametric binauralizer gain fetching. */

/* ################## End DEVELOPMENT switches ######################### */
/* clang-format on */
+158 −1
Original line number Diff line number Diff line
@@ -64,6 +64,19 @@
#define ADAPT_HTPROTO_ROT_LIM_0   0.4f
#define ADAPT_HTPROTO_ROT_LIM_1   0.8f

#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
#define MAX_GAIN_CACHE_SIZE 6

typedef struct hrtfGainCache
{
    int16_t azi;
    int16_t ele;

    float shVec[HRTF_SH_CHANNELS];
} PARAMBIN_HRTF_GAIN_CACHE;
#endif


/*-------------------------------------------------------------------------
 * Local function prototypes
 *------------------------------------------------------------------------*/
@@ -75,9 +88,15 @@ static void ivas_dirac_dec_binaural_internal( Decoder_Struct *st_ivas, float out
#endif
static void ivas_dirac_dec_decorrelate_slot( DIRAC_DEC_HANDLE hDirAC, const int16_t slot, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float decRe[][CLDFB_NO_CHANNELS_MAX], float decIm[][CLDFB_NO_CHANNELS_MAX] );

#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( Decoder_Struct *st_ivas, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float Rmat[3][3], const int16_t subframe, const int16_t isHeadtracked );

static void ivas_dirac_dec_binaural_determine_processing_matrices( Decoder_Struct *st_ivas, const int16_t max_band_decorr, float Rmat[3][3], const int16_t isHeadtracked );
#else
static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( Decoder_Struct *st_ivas, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float Rmat[3][3], const int16_t subframe );

static void ivas_dirac_dec_binaural_determine_processing_matrices( Decoder_Struct *st_ivas, const int16_t max_band_decorr, float Rmat[3][3] );
#endif

#ifdef JBM_TSM_ON_TCS
static void ivas_dirac_dec_binaural_process_output( Decoder_Struct *st_ivas, float *output_f[], float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, const int16_t numInChannels, const int16_t subframe );
@@ -94,10 +113,15 @@ static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( HEA
#endif

static void formulate2x2MixingMatrix( float Ein1, float Ein2, float CinRe, float CinIm, float Eout1, float Eout2, float CoutRe, float CoutIm, float Q[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Mre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Mim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], const float regularizationFactor );
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
static void hrtfShGetHrtf( const int16_t bin, const int16_t aziDeg, const int16_t eleDeg, float *lRealp, float *lImagp, float *rRealp, float *rImagp, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const int16_t useCachedValue );

static void getDirectPartGains( const int16_t bin, int16_t aziDeg, int16_t eleDeg, float *lRealp, float *lImagp, float *rRealp, float *rImagp, const uint8_t stereoMode, float Rmat[3][3], PARAMBIN_HRTF_GAIN_CACHE *gainCache, const int16_t isHeadtracked );
#else
static void hrtfShGetHrtf( const int16_t bin, const int16_t aziDeg, const int16_t eleDeg, float *lRealp, float *lImagp, float *rRealp, float *rImagp );

static void getDirectPartGains( const int16_t bin, int16_t aziDeg, int16_t eleDeg, float *lRealp, float *lImagp, float *rRealp, float *rImagp, const uint8_t stereoMode, float Rmat[3][3] );
#endif

static void matrixMul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] );

@@ -706,7 +730,11 @@ static void ivas_dirac_dec_binaural_internal(
        }
    }

#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
    ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, Rmat, subframe, st_ivas->hHeadTrackData && st_ivas->hHeadTrackData->num_quaternions >= 0 );
#else
    ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, Rmat, subframe );
#endif

    if ( st_ivas->ivas_format == ISM_FORMAT )
    {
@@ -721,8 +749,11 @@ static void ivas_dirac_dec_binaural_internal(
        max_band_decorr = st_ivas->hDirAC->h_freq_domain_decorr_ap_params->max_band_decorr;
    }

#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
    ivas_dirac_dec_binaural_determine_processing_matrices( st_ivas, max_band_decorr, Rmat, st_ivas->hHeadTrackData && st_ivas->hHeadTrackData->num_quaternions >= 0 );
#else
    ivas_dirac_dec_binaural_determine_processing_matrices( st_ivas, max_band_decorr, Rmat );

#endif
    ivas_dirac_dec_binaural_process_output( st_ivas, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, max_band_decorr, numInChannels, subframe );

    st_ivas->hDirAC->hDiffuseDist = NULL;
@@ -799,7 +830,12 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric
    float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    float Rmat[3][3],
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
    const int16_t subframe,
    const int16_t isHeadtracked )
#else
    const int16_t subframe )
#endif
{
    int16_t ch, slot, bin;
    uint8_t separateCenterChannelRendering;
@@ -813,6 +849,9 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric
    uint8_t applyLowBitRateEQ;
    int16_t dirac_read_idx;
    float subFrameTotalEne[CLDFB_NO_CHANNELS_MAX];
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
    PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_GAIN_CACHE_SIZE];
#endif

    hDirAC = st_ivas->hDirAC;
    h = st_ivas->hDiracDecBin;
@@ -832,6 +871,13 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric

    set_zero( frameMeanDiffusenessEneWeight, CLDFB_NO_CHANNELS_MAX );

#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
    for ( idx = 0; idx < MAX_GAIN_CACHE_SIZE; idx++ )
    {
        gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */
    }
#endif

    /* Determine EQ for low bit rates (13.2 and 16.4 kbps) */
    applyLowBitRateEQ = 0;
    if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MC_FORMAT ) && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE )
@@ -954,9 +1000,21 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric
            }
            else /* For second of the two simultaneous directions */
            {
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
                if ( ( ratio = hDirAC->energy_ratio2[dirac_read_idx][bin] ) < 0.001 )
                {
                    /* This touches only MASA path where second direction always has smaller ratio and
                     * for non-2dir it is zero. As the whole direction contribution is multiplied with
                     * the ratio, a very small ratio does not contribute any energy to output. Thus,
                     * it is better to save complexity. */
                    continue;
                }
#endif
                aziDeg = hDirAC->azimuth2[dirac_read_idx][bin];
                eleDeg = hDirAC->elevation2[dirac_read_idx][bin];
#ifndef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
                ratio = hDirAC->energy_ratio2[dirac_read_idx][bin];
#endif
                spreadCoh = hDirAC->spreadCoherence2[dirac_read_idx][bin];
            }
            diffuseness -= ratio; /* diffuseness = 1 - ratio1 - ratio2 */
@@ -975,7 +1033,11 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric
                spreadCoh = max( spreadCoh, altSpreadCoh );
            }

#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
            getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, h->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[( dirIndex * 3 )], isHeadtracked );
#else
            getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, h->renderStereoOutputInsteadOfBinaural, Rmat );
#endif

            if ( h->renderStereoOutputInsteadOfBinaural )
            {
@@ -1018,7 +1080,11 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric
                rImagp *= centerMul;

                /* Apply the gain for the left source of the three coherent sources */
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
                getDirectPartGains( bin, aziDeg + 30, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, h->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[( dirIndex * 3 + 1 )], isHeadtracked );
#else
                getDirectPartGains( bin, aziDeg + 30, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, h->renderStereoOutputInsteadOfBinaural, Rmat );
#endif

                hrtfEneSides = ( lRealpTmp * lRealpTmp ) + ( lImagpTmp * lImagpTmp ) + ( rRealpTmp * rRealpTmp ) + ( rImagpTmp * rImagpTmp );
                lRealp += sidesMul * lRealpTmp;
@@ -1028,7 +1094,11 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric

                /* Apply the gain for the right source of the three coherent sources.
                 * -30 degrees to 330 wrapping due to internal functions. */
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
                getDirectPartGains( bin, aziDeg + 330, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, h->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[( dirIndex * 3 + 2 )], isHeadtracked );
#else
                getDirectPartGains( bin, aziDeg + 330, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, h->renderStereoOutputInsteadOfBinaural, Rmat );
#endif

                hrtfEneSides += ( lRealpTmp * lRealpTmp ) + ( lImagpTmp * lImagpTmp ) + ( rRealpTmp * rRealpTmp ) + ( rImagpTmp * rImagpTmp );
                lRealp += sidesMul * lRealpTmp;
@@ -1215,16 +1285,29 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric
static void ivas_dirac_dec_binaural_determine_processing_matrices(
    Decoder_Struct *st_ivas,
    const int16_t max_band_decorr,
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
    float Rmat[3][3],
    const int16_t isHeadtracked )
#else
    float Rmat[3][3] )
#endif
{
    int16_t chA, chB, bin;
    uint8_t separateCenterChannelRendering;
    int16_t nBins;
    DIRAC_DEC_BIN_HANDLE h;
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
    PARAMBIN_HRTF_GAIN_CACHE gainCache;
#endif

    h = st_ivas->hDiracDecBin;
    separateCenterChannelRendering = st_ivas->hOutSetup.separateChannelEnabled;
    nBins = st_ivas->hDirAC->num_freq_bands; /* Actually bins */

#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
    gainCache.azi = -1000; /* Use -1000 as value for uninitialized cache. */
#endif

    for ( bin = 0; bin < nBins; bin++ )
    {
        float tmpMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmpMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], gain;
@@ -1367,7 +1450,11 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices(
                h->processMtxImPrev[chA][2][bin] = h->processMtxIm[chA][2][bin];
            }

#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
            getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, h->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache, isHeadtracked );
#else
            getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, h->renderStereoOutputInsteadOfBinaural, Rmat );
#endif

            h->processMtxRe[0][2][bin] = lRealp * gainFactor;
            h->processMtxIm[0][2][bin] = lImagp * gainFactor;
@@ -2108,7 +2195,13 @@ static void getDirectPartGains(
    float *rRealp,
    float *rImagp,
    const uint8_t renderStereoOutputInsteadOfBinaural,
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
    float Rmat[3][3],
    PARAMBIN_HRTF_GAIN_CACHE *gainCache,
    const int16_t isHeadtracked )
#else
    float Rmat[3][3] )
#endif
{
    float aziRad, eleRad;
    float y, mappedX, aziRadMapped, A, A2, A3;
@@ -2151,8 +2244,25 @@ static void getDirectPartGains(
    }
    else /* In regular binaural rendering mode */
    {
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
        if ( aziDeg == gainCache->azi && eleDeg == gainCache->ele )
        {
            hrtfShGetHrtf( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, TRUE );
        }
        else
        {
            gainCache->azi = aziDeg;
            gainCache->ele = eleDeg;
            if ( isHeadtracked )
            {
                rotateAziEle( (float) aziDeg, (float) eleDeg, &aziDeg, &eleDeg, Rmat, 0 );
            }
            hrtfShGetHrtf( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, FALSE );
        }
#else
        rotateAziEle( (float) aziDeg, (float) eleDeg, &aziDeg, &eleDeg, Rmat, 0 );
        hrtfShGetHrtf( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp );
#endif
    }

    return;
@@ -2166,9 +2276,55 @@ static void hrtfShGetHrtf(
    float *lRealp,
    float *lImagp,
    float *rRealp,
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH
    float *rImagp,
    PARAMBIN_HRTF_GAIN_CACHE *gainCache,
    const int16_t useCachedValue )
#else
    float *rImagp )
#endif
{
    int16_t k;
#ifdef FIX_511_OPTIMIZE_PARAMBIN_GAIN_FETCH

    *lRealp = 0.0f;
    *lImagp = 0.0f;
    *rRealp = 0.0f;
    *rImagp = 0.0f;

    if ( useCachedValue )
    {
        float *shVec;
        shVec = gainCache->shVec;

        for ( k = 0; k < HRTF_SH_CHANNELS; k++ )
        {
            *lRealp += hrtfShCoeffsRe[0][k][bin] * shVec[k];
            *lImagp += hrtfShCoeffsIm[0][k][bin] * shVec[k];
            *rRealp += hrtfShCoeffsRe[1][k][bin] * shVec[k];
            *rImagp += hrtfShCoeffsIm[1][k][bin] * shVec[k];
        }
    }
    else
    {
        float shVec[HRTF_SH_CHANNELS];

        ivas_dirac_dec_get_response( aziDeg,
                                     eleDeg,
                                     shVec,
                                     HRTF_SH_ORDER );

        for ( k = 0; k < HRTF_SH_CHANNELS; k++ )
        {
            *lRealp += hrtfShCoeffsRe[0][k][bin] * shVec[k];
            *lImagp += hrtfShCoeffsIm[0][k][bin] * shVec[k];
            *rRealp += hrtfShCoeffsRe[1][k][bin] * shVec[k];
            *rImagp += hrtfShCoeffsIm[1][k][bin] * shVec[k];

            gainCache->shVec[k] = shVec[k];
        }
    }
#else
    float shVec[HRTF_SH_CHANNELS];

    ivas_dirac_dec_get_response( aziDeg,
@@ -2187,6 +2343,7 @@ static void hrtfShGetHrtf(
        *rRealp += hrtfShCoeffsRe[1][k][bin] * shVec[k];
        *rImagp += hrtfShCoeffsIm[1][k][bin] * shVec[k];
    }
#endif

    return;
}