From c139df938a2fceb2a6b65e9fed97df7999643966 Mon Sep 17 00:00:00 2001 From: mave2802 <59919483+mave2802@users.noreply.github.com> Date: Thu, 30 Oct 2025 08:59:13 +0100 Subject: [PATCH 1/3] added dedicated version of formulate2x2MixingMatrix() for the case if cross terms are zero --- lib_com/options.h | 1 + lib_rend/ivas_dirac_dec_binaural_functions.c | 117 ++++++++++++++++++- 2 files changed, 116 insertions(+), 2 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index c9c5644f9..58dfb3295 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -188,6 +188,7 @@ /*#define NONBE_1324_TC_BUFFER_MEMOERY_KEEP*/ /* VA: issue 1324: do not reset TSM memory in JBM bitrate switching */ #define FIX_1370_EXTERNAL_ORIENTATION_CHECK /* Nokia: add sanity check for Euler angles for external orientations */ #define FIX_1413_IGF_INIT_PRINTOUT /* FhG: use correct variable for IGF initiliazation */ +#define NONBE_2169_BINAURAL_MIXING_MATRIX_OPT /* Dlb: use dedicated formulate2x2MixingMatrix() function if cross terms are zero */ #define CODE_IMPROVEMENTS #define NONBE_1359_FIX_IVASREND_OMASA_BINAURAL_LOUDNESS /* Nokia: issue 1339: Apply scaling to the object-part of OMASA for binaural rendering in IVAS_rend. */ #define NONBE_1362_FIX_OMASA_TO_MASA1_RENDERING /* Nokia: Fix OMASA to MASA1 rendering in IVAS_rend */ diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index 11a3a16aa..9d94e0ab1 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -111,7 +111,9 @@ static void adaptTransportSignalsHeadtracked( COMBINED_ORIENTATION_HANDLE hHeadT static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( COMBINED_ORIENTATION_HANDLE hHeadTrackData, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nBins, const int16_t nSlots, float Rmat[3][3] ); 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 NONBE_2169_BINAURAL_MIXING_MATRIX_OPT +static void formulate2x2MixingMatrixNoCross(float Ein1, float Ein2, 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]); +#endif 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, HRTFS_PARAMBIN_HANDLE hHrtfParambin ); 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, HRTFS_PARAMBIN_HANDLE hHrtfParambin ); @@ -1589,7 +1591,7 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( CrEneR *= decorrelationReductionFactor; CrCrossRe *= decorrelationReductionFactor; CrCrossIm *= decorrelationReductionFactor; - +#ifndef NONBE_2169_BINAURAL_MIXING_MATRIX_OPT /* Determine a residual mixing matrix Mdec for processing the decorrelated signal to obtain * the residual signal (that has the residual covariance matrix) */ formulate2x2MixingMatrix( hDiracDecBin->ChEne[0][bin], hDiracDecBin->ChEne[1][bin], @@ -1597,6 +1599,16 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( CrEneL, CrEneR, CrCrossRe, CrCrossIm, prototypeMtx, MdecRe, MdecIm, 0.2f ); +#else + /* Determine a residual mixing matrix Mdec for processing the decorrelated signal to obtain + * the residual signal (that has the residual covariance matrix) + * Decorrelated signal has ideally no cross-terms */ + formulate2x2MixingMatrixNoCross( hDiracDecBin->ChEne[0][bin], hDiracDecBin->ChEne[1][bin], + CrEneL, CrEneR, + CrCrossRe, CrCrossIm, + prototypeMtx, MdecRe, MdecIm ); +#endif + } else { @@ -2442,6 +2454,107 @@ static void formulate2x2MixingMatrix( return; } +#ifdef NONBE_2169_BINAURAL_MIXING_MATRIX_OPT +static void formulate2x2MixingMatrixNoCross( + float Ein1, + float Ein2, + 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] ) +{ + /* + This function implements a 2x2 solution for an optimized spatial audio rendering algorithm + Vilkamo, J., Bäckström, T. and Kuntz, A., 2013. + "Optimized covariance domain framework for time–frequency processing of spatial audio." + Journal of the Audio Engineering Society, 61(6), pp.403-411. + + The result of the formulas below are the same as those in the publication, however, some + derivation details differ for as simple as possible 2x2 formulattion + */ + int16_t chA, chB; + float maxEne, maxEneDiv; + float KyRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], KyIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + float tmpRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmpIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + float Ure[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Uim[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + float D[BINAURAL_CHANNELS]; + float div[BINAURAL_CHANNELS]; + float Ghat[BINAURAL_CHANNELS]; + float GhatQ[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + float Pre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Pim[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + + /* Normalize energy values */ + maxEne = Ein1; + maxEne = max( maxEne, Ein2 ); + maxEne = max( maxEne, Eout1 ); + maxEne = max( maxEne, Eout2 ); + maxEneDiv = 1.0f / ( maxEne + 1e-12f ); + Ein1 *= maxEneDiv; + Ein2 *= maxEneDiv; + Eout1 *= maxEneDiv; + Eout2 *= maxEneDiv; + CoutRe *= maxEneDiv; + CoutIm *= maxEneDiv; + + /* Cholesky decomposition of target / output covariance matrix */ + chol2x2( Eout1, Eout2, CoutRe, CoutIm, KyRe, KyIm ); + + /* If there are no cross-terms, the Eigendecomposition of input covariance matrix + can be skipped. Uxre is a unit matrix, Uxim is a zero matrix and Sx is (1, 1) + Further on, also Kxre is a unit matrix and Kxim is a zero matrix + Multiplication with these matrices / scalars can be skipped + */ + + /* This is equivalent to the prototype signal energy normalization in the publication */ + Ghat[0] = sqrtf( Eout1 / ( 1e-12f + max( Ein1, 0.001f * Ein2 ) ) ); + Ghat[1] = sqrtf( Eout2 / ( 1e-12f + max( Ein2, 0.001f * Ein1 ) ) ); + + /* Matrix multiplication, A = Ky' * G_hat * Q */ + for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + GhatQ[chA][0] = Q[chA][0] * Ghat[chA]; + GhatQ[chA][1] = Q[chA][1] * Ghat[chA]; + } + for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ ) + { + Are[chA][chB] = KyRe[0][chA] * GhatQ[0][chB] + KyRe[1][chA] * GhatQ[1][chB]; + Aim[chA][chB] = -KyIm[0][chA] * GhatQ[0][chB] - KyIm[1][chA] * GhatQ[1][chB]; + } + } + + /* Find nearest orthonormal matrix P to A = Ky' * G_hat * Q * Kx + For matrix A that is P = A(A'A)^0.5 + */ + matrixTransp1Mul( Are, Aim, Are, Aim, tmpRe, tmpIm ); + + eig2x2( tmpRe[0][0], tmpRe[1][1], tmpRe[1][0], tmpIm[1][0], Ure, Uim, D ); + + div[0] = min( 10000.0f, sqrtf( 1.0f / ( 1e-12f + D[0] ) ) ); + div[1] = min( 10000.0f, sqrtf( 1.0f / ( 1e-12f + D[1] ) ) ); + + matrixMul( Are, Aim, Ure, Uim, tmpRe, tmpIm ); + + for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ ) + { + tmpRe[chA][chB] *= div[chB]; + tmpIm[chA][chB] *= div[chB]; + } + } + + matrixTransp2Mul( tmpRe, tmpIm, Ure, Uim, Pre, Pim ); /* Nearest orthonormal matrix P to matrix A formulated */ + matrixMul( KyRe, KyIm, Pre, Pim, Mre, Mim ); + + return; +} +#endif static void getDirectPartGains( const int16_t bin, -- GitLab From dc412235856dbf23384e9233ebf979cc6032819a Mon Sep 17 00:00:00 2001 From: mave2802 <59919483+mave2802@users.noreply.github.com> Date: Thu, 30 Oct 2025 09:12:31 +0100 Subject: [PATCH 2/3] clang format --- lib_rend/ivas_dirac_dec_binaural_functions.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index 9d94e0ab1..b68750a81 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -112,7 +112,7 @@ static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( COM 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 NONBE_2169_BINAURAL_MIXING_MATRIX_OPT -static void formulate2x2MixingMatrixNoCross(float Ein1, float Ein2, 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]); +static void formulate2x2MixingMatrixNoCross( float Ein1, float Ein2, 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] ); #endif 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, HRTFS_PARAMBIN_HANDLE hHrtfParambin ); @@ -1608,7 +1608,6 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( CrCrossRe, CrCrossIm, prototypeMtx, MdecRe, MdecIm ); #endif - } else { -- GitLab From 9f5a385650df8e8e7c7288ec6df6642285d46799 Mon Sep 17 00:00:00 2001 From: mave2802 <59919483+mave2802@users.noreply.github.com> Date: Thu, 30 Oct 2025 13:19:22 +0100 Subject: [PATCH 3/3] fixed comment --- lib_rend/ivas_dirac_dec_binaural_functions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index b68750a81..82a1c3baf 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -2548,7 +2548,7 @@ static void formulate2x2MixingMatrixNoCross( } } - matrixTransp2Mul( tmpRe, tmpIm, Ure, Uim, Pre, Pim ); /* Nearest orthonormal matrix P to matrix A formulated */ + matrixTransp2Mul( tmpRe, tmpIm, Ure, Uim, Pre, Pim ); /* Nearest orthonormal matrix P to matrix tmp formulated */ matrixMul( KyRe, KyIm, Pre, Pim, Mre, Mim ); return; -- GitLab