From 683fb23c10a69022f7eeda976e638e47ee330a3b Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Thu, 23 Apr 2026 13:59:53 +0300 Subject: [PATCH 1/5] Fix float issue 1578 by adjusting the stereo type detection. --- lib_com/ivas_cnst.h | 5 + lib_com/options.h | 2 +- lib_dec/ivas_dirac_dec_fx.c | 4 + lib_rend/ivas_dirac_output_synthesis_dec_fx.c | 8 + lib_rend/ivas_dirac_rend_fx.c | 417 ++++++++++++++++++ lib_rend/ivas_prot_rend_fx.h | 5 + lib_rend/ivas_stat_rend.h | 8 + lib_rend/lib_rend_fx.c | 4 + 8 files changed, 452 insertions(+), 1 deletion(-) diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 7bb753feb..7becf0647 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1256,7 +1256,12 @@ typedef enum { MASA_STEREO_NOT_DEFINED, MASA_STEREO_SPACED_MICS, +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + MASA_STEREO_DOWNMIX, + MASA_DUAL_MONO +#else MASA_STEREO_DOWNMIX +#endif } MASA_TRANSPORT_SIGNAL_TYPE; typedef enum diff --git a/lib_com/options.h b/lib_com/options.h index be45e9246..6e3574e9b 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -129,7 +129,7 @@ #define FIX_FLOAT_1573_POSITION_UPDATE /* Eri: Float issue 1573: For static orientation and listener movement, the PoseUpdated flag is cleared and prevents 5 ms update rate. */ #define FIX_BASOP_2521_DIRAC_STEREO_STEFFI_NRGS /* FhG: BASOP issue 2521: Fix wrong porting for determination of first subframe length in ivas_sba_dirac_stereo_compute_td_stefi_nrgs() */ #define FIX_1452_DEFAULT_REVERB /* Nokia/Philips/FhG: Fix default room presets and their usage in renderer */ - +#define FIX_FLOAT_1578_OMASA_REND_SPIKES /* Nokia: Float issue 1578: Fix spikes and collapsed perception in OMASA/MASA rendering to FOA/HOA */ /* ##################### End NON-BE switches ########################### */ diff --git a/lib_dec/ivas_dirac_dec_fx.c b/lib_dec/ivas_dirac_dec_fx.c index a92537347..23e90009b 100644 --- a/lib_dec/ivas_dirac_dec_fx.c +++ b/lib_dec/ivas_dirac_dec_fx.c @@ -364,7 +364,11 @@ static ivas_error ivas_dirac_rend_config_fx( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } } +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + ivas_masa_init_stereotype_detection_fx( hDirACRend->masa_stereo_type_detect, ivas_total_brate ); +#else ivas_masa_init_stereotype_detection_fx( hDirACRend->masa_stereo_type_detect ); +#endif } ELSE { diff --git a/lib_rend/ivas_dirac_output_synthesis_dec_fx.c b/lib_rend/ivas_dirac_output_synthesis_dec_fx.c index beb4f6617..0a6afb017 100644 --- a/lib_rend/ivas_dirac_output_synthesis_dec_fx.c +++ b/lib_rend/ivas_dirac_output_synthesis_dec_fx.c @@ -3001,6 +3001,14 @@ void ivas_dirac_dec_compute_directional_responses_fx( move32(); } } +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + ELSE IF( EQ_16( transport_signal_type, MASA_DUAL_MONO ) ) + { + direct_response_fx[0] = ONE_IN_Q29; /*q29*/ + move32(); + /* direct_response[1] is not adjusted for dual mono input */ + } +#endif ELSE { set32_fx( direct_response_fx, ONE_IN_Q29, hDirACRend->num_protos_ambi ); /*q29*/ diff --git a/lib_rend/ivas_dirac_rend_fx.c b/lib_rend/ivas_dirac_rend_fx.c index 10092f166..1d294b350 100644 --- a/lib_rend/ivas_dirac_rend_fx.c +++ b/lib_rend/ivas_dirac_rend_fx.c @@ -41,6 +41,15 @@ #include "ivas_prot_fx.h" #include "ivas_rom_binaural_crend_head.h" +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES +/*------------------------------------------------------------------------------------------* + * Local constants + *------------------------------------------------------------------------------------------*/ + +/* Constants for MASA dual mono detection */ +#define MASA_DUAL_MONO_TAU1_FX 33554432 /* Q31, float 0.01562500000000000f, which is 2^-6, which is about -18 dB */ +#define MASA_DUAL_MONO_TAU2_FX 16384 /* Q31, float 0.00000762939453125f, which is 2^-17, which is about -51 dB */ +#endif /*------------------------------------------------------------------------- * ivas_dirac_allocate_parameters() @@ -1725,8 +1734,16 @@ void protoSignalComputation2_fx( Word16 q_sum_total_ratio = 0; move16(); Word32 a_fx, b_fx, a2_fx, b2_fx; +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + Word16 interpolatorSpaced_fx, interpolatorDmx_fx, interpolatorDualMono_fx; + Word32 tempSpaced_fx, tempDmx_fx, tempDualMono_fx; + Word64 inst_diff_bb_power_64fx; + Word16 inst_diff_bb_power_norm; + Word16 max_band_diff_ene; +#else Word16 interpolatorSpaced_fx, interpolatorDmx_fx; Word32 tempSpaced_fx, tempDmx_fx; +#endif Word16 q_shift, min_q_shift[2], exp, q_temp[2]; Word32 temp; Word64 W_tmp1, W_tmp2, W_tmp3; @@ -1747,6 +1764,11 @@ void protoSignalComputation2_fx( move16(); interpolatorDmx_fx = MAX16B; move16(); +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + interpolatorDualMono_fx = 0; + move16(); + max_band_diff_ene = s_min( stereo_type_detect->max_band_diff_ene, num_freq_bands ); /* Local version for correct maximum */ +#endif /* Calculate the max shift possible for the buffers RealBuffer_fx and ImagBuffer_fx */ FOR( l = 0; l < 2; l++ ) @@ -1919,6 +1941,21 @@ void protoSignalComputation2_fx( total_hi_power_fx = 0; move32(); +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + inst_diff_bb_power_64fx = 0; + move64(); + + stereo_type_detect->inst_diff_bb_power_fx = 0; + move32(); + stereo_type_detect->inst_total_bb_power_fx = 0; + move32(); + + stereo_type_detect->q_inst_diff_bb_power_fx = Q31; + move16(); + stereo_type_detect->q_inst_total_bb_power_fx = Q31; + move16(); + +#endif dipole_freq_range[0] = stereo_type_detect->dipole_freq_range[0]; move16(); dipole_freq_range[1] = stereo_type_detect->dipole_freq_range[1]; @@ -1939,12 +1976,30 @@ void protoSignalComputation2_fx( /* interpolatorSpaced = ( (float) ( stereo_type_detect->interpolator ) ) / ( (float) MASA_STEREO_INTERPOLATION_SLOTS ); */ interpolatorSpaced_fx = i_mult_sat( stereo_type_detect->interpolator, 2048 /* 1 / MASA_STEREO_INTERPOLATION_SLOTS in Q15 */ ); /* Q15 */ interpolatorDmx_fx = sub( MAX16B, interpolatorSpaced_fx ); /* Q15 */ +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + interpolatorDualMono_fx = interpolatorDmx_fx; + move16(); +#endif } +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + ELSE IF( EQ_16( stereo_type_detect->type_change_direction, MASA_DUAL_MONO ) ) + { + /* interpolatorDualMono = ( (float) ( stereo_type_detect->interpolator ) ) / ( (float) MASA_STEREO_INTERPOLATION_SLOTS ); */ + interpolatorDualMono_fx = i_mult_sat( stereo_type_detect->interpolator, 2048 /* 1 / MASA_STEREO_INTERPOLATION_SLOTS in Q15 */ ); /* Q15 */ + interpolatorDmx_fx = sub( MAX16B, interpolatorDualMono_fx ); /* Q15 */ + interpolatorSpaced_fx = interpolatorDmx_fx; + move16(); + } +#endif ELSE { /* interpolatorDmx = ( (float) ( stereo_type_detect->interpolator ) ) / ( (float) MASA_STEREO_INTERPOLATION_SLOTS ); */ interpolatorDmx_fx = i_mult_sat( stereo_type_detect->interpolator, 2048 /* 1 / MASA_STEREO_INTERPOLATION_SLOTS in Q15 */ ); /* Q15 */ interpolatorSpaced_fx = sub( MAX16B, interpolatorDmx_fx ); /* Q15 */ +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + interpolatorDualMono_fx = interpolatorSpaced_fx; + move16(); +#endif } } @@ -2085,6 +2140,44 @@ void protoSignalComputation2_fx( q_sum_total_ratio = s_max( q_sum_total_ratio, exp_sum_total_ratio_fx[l] ); } +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + RealSubtract_fx = L_sub( re1, re2 ); // q_cldfb+min_q_shift + ImagSubtract_fx = L_sub( im1, im2 ); // q_cldfb+min_q_shift + + IF( LT_16( l, max_band_diff_ene ) ) + { + /* Accumulate difference power in Word64 for full precision. */ + inst_diff_bb_power_64fx = W_add( inst_diff_bb_power_64fx, W_shr( W_add( W_mult0_32_32( RealSubtract_fx, RealSubtract_fx ), W_mult0_32_32( ImagSubtract_fx, ImagSubtract_fx ) ), + total_shift[qidx] ) ); // 2*(q_cldfb+min( min_q_shift[0], min_q_shift[1] )) + + IF( EQ_16( l, sub( max_band_diff_ene, 1 ) ) ) + { + /* Stores sum of reference power (i.e., sum of transport channels) up to max_band_diff_ene - 1. */ + stereo_type_detect->inst_total_bb_power_fx = total_bb_power_fx; /* Total energy before smoothing, q_Left_Right_power */ + move32(); + stereo_type_detect->q_inst_total_bb_power_fx = q_Left_Right_power; + move16(); + } + + IF( l == 0 ) + { + temp = Madd_32_32( Mpy_32_32( RealSubtract_fx, RealSubtract_fx ), ImagSubtract_fx, ImagSubtract_fx ); // 2*(q_cldfb+min_q_shift)-31 + + IF( LT_16( q_temp[qidx], stereo_type_detect->q_subtract_power_y ) ) + { + stereo_type_detect->subtract_power_y_fx = L_add( L_shr( stereo_type_detect->subtract_power_y_fx, sub( stereo_type_detect->q_subtract_power_y, q_temp[qidx] ) ), temp ); // q_temp + move32(); + stereo_type_detect->q_subtract_power_y = q_temp[qidx]; + move16(); + } + ELSE + { + stereo_type_detect->subtract_power_y_fx = L_add( stereo_type_detect->subtract_power_y_fx, L_shr( temp, sub( q_temp[qidx], stereo_type_detect->q_subtract_power_y ) ) ); // stereo_type_detect->q_subtract_power_y + move32(); + } + } + } +#else IF( l == 0 ) { RealSubtract_fx = L_sub( re1, re2 ); // q_cldfb+min_q_shift @@ -2105,12 +2198,14 @@ void protoSignalComputation2_fx( move32(); } } +#endif /* Compute protos (and their power) for direct sound rendering */ /* W prototype */ IF( stereo_type_detect->interpolator > 0 ) { +#ifndef FIX_FLOAT_1578_OMASA_REND_SPIKES IF( L_or( LT_16( l, sub( dipole_freq_range[1], 1 ) ), GE_16( l, MASA_SUM_PROTO_START_BIN ) ) ) { Real_aux_fx = Madd_32_16( Mpy_32_16_1( Real_aux_fx, shr( interpolatorSpaced_fx, 1 ) ), Real_aux_fx, interpolatorDmx_fx ); // q_cldfb+min_q_shift @@ -2155,6 +2250,136 @@ void protoSignalComputation2_fx( p_proto_buffer_fx[2 * l + 1] = Madd_32_16( Mpy_32_16_1( im1, interpolatorSpaced_fx ), Imag_aux_fx, interpolatorDmx_fx ); // q_cldfb+min_q_shift move32(); } +#else + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( EQ_16( stereo_type_detect->type_change_direction, MASA_STEREO_SPACED_MICS ) && EQ_16( stereo_type_detect->current_stereo_type, MASA_STEREO_DOWNMIX ) ) || + ( EQ_16( stereo_type_detect->type_change_direction, MASA_STEREO_DOWNMIX ) && EQ_16( stereo_type_detect->current_stereo_type, MASA_STEREO_SPACED_MICS ) ) ) + { + IF( L_or( LT_16( l, sub( dipole_freq_range[1], 1 ) ), GE_16( l, MASA_SUM_PROTO_START_BIN ) ) ) + { + Real_aux_fx = Madd_32_16( Mpy_32_16_1( Real_aux_fx, shr( interpolatorSpaced_fx, 1 ) ), Real_aux_fx, interpolatorDmx_fx ); // q_cldfb+min_q_shift + Imag_aux_fx = Madd_32_16( Mpy_32_16_1( Imag_aux_fx, shr( interpolatorSpaced_fx, 1 ) ), Imag_aux_fx, interpolatorDmx_fx ); // q_cldfb+min_q_shift + + temp = Madd_32_32( Mpy_32_32( Real_aux_fx, Real_aux_fx ), Imag_aux_fx, Imag_aux_fx ); // 2*(q_cldfb+min_q_shift) -31 + IF( LT_16( q_temp[qidx], q_proto_power_smooth[qidx] ) ) + { + proto_power_smooth_fx[l] = L_add( L_shr( proto_power_smooth_fx[l], sub( q_proto_power_smooth[qidx], q_temp[qidx] ) ), temp ); // q_temp + move32(); + } + ELSE + { + proto_power_smooth_fx[l] = L_add( proto_power_smooth_fx[l], L_shr( temp, sub( q_temp[qidx], q_proto_power_smooth[qidx] ) ) ); // q_proto_power_smooth + move32(); + } + + p_proto_buffer_fx[2 * l] = Real_aux_fx; // q_cldfb+min_q_shift + move32(); + p_proto_buffer_fx[2 * l + 1] = Imag_aux_fx; // q_cldfb+min_q_shift + move32(); + } + ELSE + { + tempSpaced_fx = Madd_32_32( Mpy_32_32( re1, re1 ), im1, im1 ); // 2*(q_cldfb+min_q_shift)-31 + tempDmx_fx = Madd_32_32( Mpy_32_32( Real_aux_fx, Real_aux_fx ), Imag_aux_fx, Imag_aux_fx ); // 2*(q_cldfb+min_q_shift)-31 + + temp = Madd_32_16( Mpy_32_16_1( tempSpaced_fx, interpolatorSpaced_fx ), tempDmx_fx, interpolatorDmx_fx ); // 2*(q_cldfb+min_q_shift)-31 + IF( LT_16( q_temp[qidx], q_proto_power_smooth[qidx] ) ) + { + proto_power_smooth_fx[l] = L_add( L_shr( proto_power_smooth_fx[l], sub( q_proto_power_smooth[qidx], q_temp[qidx] ) ), temp ); // q_temp + move32(); + } + ELSE + { + proto_power_smooth_fx[l] = L_add( proto_power_smooth_fx[l], L_shr( temp, sub( q_temp[qidx], q_proto_power_smooth[qidx] ) ) ); // q_proto_power_smooth + move32(); + } + + p_proto_buffer_fx[2 * l] = Madd_32_16( Mpy_32_16_1( re1, interpolatorSpaced_fx ), Real_aux_fx, interpolatorDmx_fx ); // q_cldfb+min_q_shift + move32(); + p_proto_buffer_fx[2 * l + 1] = Madd_32_16( Mpy_32_16_1( im1, interpolatorSpaced_fx ), Imag_aux_fx, interpolatorDmx_fx ); // q_cldfb+min_q_shift + move32(); + } + } + ELSE IF( ( EQ_16( stereo_type_detect->type_change_direction, MASA_STEREO_SPACED_MICS ) && EQ_16( stereo_type_detect->current_stereo_type, MASA_DUAL_MONO ) ) || + ( EQ_16( stereo_type_detect->type_change_direction, MASA_DUAL_MONO ) && EQ_16( stereo_type_detect->current_stereo_type, MASA_STEREO_SPACED_MICS ) ) ) + { + IF( L_or( LT_16( l, sub( dipole_freq_range[1], 1 ) ), GE_16( l, MASA_SUM_PROTO_START_BIN ) ) ) + { + Real_aux_fx = L_shr( Real_aux_fx, 1 ); // q_cldfb+min_q_shift + Imag_aux_fx = L_shr( Imag_aux_fx, 1 ); // q_cldfb+min_q_shift + temp = Madd_32_32( Mpy_32_32( Real_aux_fx, Real_aux_fx ), Imag_aux_fx, Imag_aux_fx ); // 2*(q_cldfb+min_q_shift)-31 + IF( LT_16( q_temp[qidx], q_proto_power_smooth[qidx] ) ) + { + proto_power_smooth_fx[l] = L_add( L_shr( proto_power_smooth_fx[l], sub( q_proto_power_smooth[qidx], q_temp[qidx] ) ), temp ); // q_temp + move32(); + } + ELSE + { + proto_power_smooth_fx[l] = L_add( proto_power_smooth_fx[l], L_shr( temp, sub( q_temp[qidx], q_proto_power_smooth[qidx] ) ) ); // q_proto_power_smooth + move32(); + } + + p_proto_buffer_fx[2 * l] = Real_aux_fx; // q_cldfb+min_q_shift + move32(); + p_proto_buffer_fx[2 * l + 1] = Imag_aux_fx; // q_cldfb+min_q_shift + move32(); + } + ELSE + { + tempSpaced_fx = Madd_32_32( Mpy_32_32( re1, re1 ), im1, im1 ); // 2*(q_cldfb+min_q_shift)-31 + + Real_aux_fx = L_shr( Real_aux_fx, 1 ); // q_cldfb+min_q_shift + Imag_aux_fx = L_shr( Imag_aux_fx, 1 ); // q_cldfb+min_q_shift + + tempDualMono_fx = Madd_32_32( Mpy_32_32( Real_aux_fx, Real_aux_fx ), Imag_aux_fx, Imag_aux_fx ); // 2*(q_cldfb+min_q_shift)-31 + + temp = Madd_32_16( Mpy_32_16_1( tempSpaced_fx, interpolatorSpaced_fx ), tempDualMono_fx, interpolatorDualMono_fx ); // 2*(q_cldfb+min_q_shift)-31 + IF( LT_16( q_temp[qidx], q_proto_power_smooth[qidx] ) ) + { + proto_power_smooth_fx[l] = L_add( L_shr( proto_power_smooth_fx[l], sub( q_proto_power_smooth[qidx], q_temp[qidx] ) ), temp ); // q_temp + move32(); + } + ELSE + { + proto_power_smooth_fx[l] = L_add( proto_power_smooth_fx[l], L_shr( temp, sub( q_temp[qidx], q_proto_power_smooth[qidx] ) ) ); // q_proto_power_smooth + move32(); + } + + p_proto_buffer_fx[2 * l] = Madd_32_16( Mpy_32_16_1( re1, interpolatorSpaced_fx ), Real_aux_fx, interpolatorDualMono_fx ); // q_cldfb+min_q_shift + move32(); + p_proto_buffer_fx[2 * l + 1] = Madd_32_16( Mpy_32_16_1( im1, interpolatorSpaced_fx ), Imag_aux_fx, interpolatorDualMono_fx ); // q_cldfb+min_q_shift + move32(); + } + } + ELSE /* MASA_STEREO_DOWNMIX <-> MASA_DUAL_MONO */ + { + /* Both use same proto but dual mono has 0.5 scaling */ + Real_aux_fx = Madd_32_16( Mpy_32_16_1( Real_aux_fx, shr( interpolatorDualMono_fx, 1 ) ), Real_aux_fx, interpolatorDmx_fx ); // q_cldfb+min_q_shift + Imag_aux_fx = Madd_32_16( Mpy_32_16_1( Imag_aux_fx, shr( interpolatorDualMono_fx, 1 ) ), Imag_aux_fx, interpolatorDmx_fx ); // q_cldfb+min_q_shift + + temp = Madd_32_32( Mpy_32_32( Real_aux_fx, Real_aux_fx ), Imag_aux_fx, Imag_aux_fx ); // 2*(q_cldfb+min_q_shift) -31 + IF( LT_16( q_temp[qidx], q_proto_power_smooth[qidx] ) ) + { + proto_power_smooth_fx[l] = L_add( L_shr( proto_power_smooth_fx[l], sub( q_proto_power_smooth[qidx], q_temp[qidx] ) ), temp ); // q_temp + move32(); + } + ELSE + { + proto_power_smooth_fx[l] = L_add( proto_power_smooth_fx[l], L_shr( temp, sub( q_temp[qidx], q_proto_power_smooth[qidx] ) ) ); // q_proto_power_smooth + move32(); + } + + p_proto_buffer_fx[2 * l] = Real_aux_fx; // q_cldfb+min_q_shift + move32(); + p_proto_buffer_fx[2 * l + 1] = Imag_aux_fx; // q_cldfb+min_q_shift + move32(); + } +#endif } ELSE IF( EQ_16( stereo_type_detect->masa_stereo_type, MASA_STEREO_SPACED_MICS ) ) { @@ -2199,7 +2424,32 @@ void protoSignalComputation2_fx( move32(); } } +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + ELSE IF( EQ_16( stereo_type_detect->masa_stereo_type, MASA_DUAL_MONO ) ) + { + Real_aux_fx = L_shr( Real_aux_fx, 1 ); // q_cldfb+min_q_shift + Imag_aux_fx = L_shr( Imag_aux_fx, 1 ); // q_cldfb+min_q_shift + temp = Madd_32_32( Mpy_32_32( Real_aux_fx, Real_aux_fx ), Imag_aux_fx, Imag_aux_fx ); // 2*(q_cldfb+min_q_shift)-31 + IF( LT_16( q_temp[qidx], q_proto_power_smooth[qidx] ) ) + { + proto_power_smooth_fx[l] = L_add( L_shr( proto_power_smooth_fx[l], sub( q_proto_power_smooth[qidx], q_temp[qidx] ) ), temp ); // q_temp + move32(); + } + ELSE + { + proto_power_smooth_fx[l] = L_add( proto_power_smooth_fx[l], L_shr( temp, sub( q_temp[qidx], q_proto_power_smooth[qidx] ) ) ); // q_proto_power_smooth + move32(); + } + + p_proto_buffer_fx[2 * l] = Real_aux_fx; // q_cldfb+min_q_shift + move32(); + p_proto_buffer_fx[2 * l + 1] = Imag_aux_fx; // q_cldfb+min_q_shift + move32(); + } + ELSE /* MASA_STEREO_DOWNMIX */ +#else ELSE +#endif { temp = Madd_32_32( Mpy_32_32( Real_aux_fx, Real_aux_fx ), Imag_aux_fx, Imag_aux_fx ); // 2*(q_cldfb+min_q_shift)-31 IF( LT_16( q_temp[qidx], q_proto_power_smooth[qidx] ) ) @@ -2222,6 +2472,7 @@ void protoSignalComputation2_fx( /* Y prototype */ IF( stereo_type_detect->interpolator > 0 ) { +#ifndef FIX_FLOAT_1578_OMASA_REND_SPIKES IF( LT_16( l, dipole_freq_range[0] ) ) { p_proto_buffer_fx[2 * ( num_freq_bands + l )] = Madd_32_16( Mpy_32_16_1( p_proto_buffer_fx[2 * l], interpolatorSpaced_fx ), L_sub( re1, re2 ), interpolatorDmx_fx ); // q_cldfb+min_q_shift @@ -2255,6 +2506,83 @@ void protoSignalComputation2_fx( proto_power_smooth_fx[l + num_freq_bands] = L_add( proto_power_smooth_fx[l + num_freq_bands], L_shr( temp, sub( q_temp[qidx], q_proto_power_smooth[qidx] ) ) ); // q_proto_power_smooth move32(); } +#else + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( EQ_16( stereo_type_detect->type_change_direction, MASA_STEREO_SPACED_MICS ) && EQ_16( stereo_type_detect->current_stereo_type, MASA_STEREO_DOWNMIX ) ) || + ( EQ_16( stereo_type_detect->type_change_direction, MASA_STEREO_DOWNMIX ) && EQ_16( stereo_type_detect->current_stereo_type, MASA_STEREO_SPACED_MICS ) ) ) + { + IF( LT_16( l, dipole_freq_range[0] ) ) + { + p_proto_buffer_fx[2 * ( num_freq_bands + l )] = Madd_32_16( Mpy_32_16_1( p_proto_buffer_fx[2 * l], interpolatorSpaced_fx ), L_sub( re1, re2 ), interpolatorDmx_fx ); // q_cldfb+min_q_shift + move32(); + p_proto_buffer_fx[2 * ( num_freq_bands + l ) + 1] = Madd_32_16( Mpy_32_16_1( p_proto_buffer_fx[2 * l + 1], interpolatorSpaced_fx ), L_sub( im1, im2 ), interpolatorDmx_fx ); // q_cldfb+min_q_shift + move32(); + } + ELSE IF( LT_16( l, dipole_freq_range[1] ) ) + { + p_proto_buffer_fx[2 * ( num_freq_bands + l )] = Madd_32_16( Mpy_32_16_1( L_sub( im1, im2 ), interpolatorSpaced_fx ), L_sub( re1, re2 ), interpolatorDmx_fx ); // q_cldfb+min_q_shift + move32(); + p_proto_buffer_fx[2 * ( num_freq_bands + l ) + 1] = Madd_32_16( Mpy_32_16_1( -L_sub( re1, re2 ), interpolatorSpaced_fx ), L_sub( im1, im2 ), interpolatorDmx_fx ); // q_cldfb+min_q_shift + move32(); + } + ELSE + { + p_proto_buffer_fx[2 * ( num_freq_bands + l )] = Madd_32_16( Mpy_32_16_1( p_proto_buffer_fx[2 * l], interpolatorSpaced_fx ), L_sub( re1, re2 ), interpolatorDmx_fx ); // q_cldfb+min_q_shift + move32(); + p_proto_buffer_fx[2 * ( num_freq_bands + l ) + 1] = Madd_32_16( Mpy_32_16_1( p_proto_buffer_fx[2 * l + 1], interpolatorSpaced_fx ), L_sub( im1, im2 ), interpolatorDmx_fx ); // q_cldfb+min_q_shift + move32(); + } + } + ELSE IF( ( EQ_16( stereo_type_detect->type_change_direction, MASA_STEREO_SPACED_MICS ) && EQ_16( stereo_type_detect->current_stereo_type, MASA_DUAL_MONO ) ) || + ( EQ_16( stereo_type_detect->type_change_direction, MASA_DUAL_MONO ) && EQ_16( stereo_type_detect->current_stereo_type, MASA_STEREO_SPACED_MICS ) ) ) + { + IF( LT_16( l, dipole_freq_range[0] ) ) + { + p_proto_buffer_fx[2 * num_freq_bands + 2 * l] = p_proto_buffer_fx[2 * l]; + move32(); + p_proto_buffer_fx[2 * num_freq_bands + 2 * l + 1] = p_proto_buffer_fx[2 * l + 1]; + move32(); + } + ELSE IF( LT_16( l, dipole_freq_range[1] ) ) + { + p_proto_buffer_fx[2 * ( num_freq_bands + l )] = Madd_32_16( Mpy_32_16_1( L_sub( im1, im2 ), interpolatorSpaced_fx ), p_proto_buffer_fx[2 * l], interpolatorDualMono_fx ); // q_cldfb+min_q_shift + move32(); + p_proto_buffer_fx[2 * ( num_freq_bands + l ) + 1] = Madd_32_16( Mpy_32_16_1( -L_sub( re1, re2 ), interpolatorSpaced_fx ), p_proto_buffer_fx[2 * l + 1], interpolatorDualMono_fx ); // q_cldfb+min_q_shift + move32(); + } + ELSE + { + p_proto_buffer_fx[2 * num_freq_bands + 2 * l] = p_proto_buffer_fx[2 * l]; + move32(); + p_proto_buffer_fx[2 * num_freq_bands + 2 * l + 1] = p_proto_buffer_fx[2 * l + 1]; + move32(); + } + } + ELSE /* MASA_STEREO_DOWNMIX <-> MASA_DUAL_MONO */ + { + p_proto_buffer_fx[2 * ( num_freq_bands + l )] = Madd_32_16( Mpy_32_16_1( p_proto_buffer_fx[2 * l], interpolatorDualMono_fx ), L_sub( re1, re2 ), interpolatorDmx_fx ); // q_cldfb+min_q_shift + move32(); + p_proto_buffer_fx[2 * ( num_freq_bands + l ) + 1] = Madd_32_16( Mpy_32_16_1( p_proto_buffer_fx[2 * l + 1], interpolatorDualMono_fx ), L_sub( im1, im2 ), interpolatorDmx_fx ); // q_cldfb+min_q_shift + move32(); + } + + temp = Madd_32_32( Mpy_32_32( p_proto_buffer_fx[2 * ( num_freq_bands + l )], p_proto_buffer_fx[2 * ( num_freq_bands + l )] ), p_proto_buffer_fx[2 * ( num_freq_bands + l ) + 1], p_proto_buffer_fx[2 * ( num_freq_bands + l ) + 1] ); // 2*(q_cldfb+min_q_shift)-31 + IF( LT_16( q_temp[qidx], q_proto_power_smooth[qidx] ) ) + { + proto_power_smooth_fx[l + num_freq_bands] = L_add( L_shr( proto_power_smooth_fx[l + num_freq_bands], sub( q_proto_power_smooth[qidx], q_temp[qidx] ) ), temp ); // q_temp + move32(); + } + ELSE + { + proto_power_smooth_fx[l + num_freq_bands] = L_add( proto_power_smooth_fx[l + num_freq_bands], L_shr( temp, sub( q_temp[qidx], q_proto_power_smooth[qidx] ) ) ); // q_proto_power_smooth + move32(); + } +#endif } ELSE IF( EQ_16( stereo_type_detect->masa_stereo_type, MASA_STEREO_SPACED_MICS ) ) { @@ -2296,7 +2624,21 @@ void protoSignalComputation2_fx( move32(); } } +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + ELSE IF( EQ_16( stereo_type_detect->masa_stereo_type, MASA_DUAL_MONO ) ) + { + /* proto = W */ + p_proto_buffer_fx[2 * ( num_freq_bands + l )] = p_proto_buffer_fx[2 * l]; // q_cldfb+min_q_shift + move32(); + p_proto_buffer_fx[2 * ( num_freq_bands + l ) + 1] = p_proto_buffer_fx[2 * l + 1]; // q_cldfb+min_q_shift + move32(); + proto_power_smooth_fx[l + num_freq_bands] = proto_power_smooth_fx[l]; // min( q_temp, *q_proto_power_smooth ) + move32(); + } + ELSE /* MASA_STEREO_DOWNMIX */ +#else ELSE +#endif { p_proto_buffer_fx[2 * ( num_freq_bands + l )] = L_sub( re1, re2 ); // q_cldfb+min_q_shift move32(); @@ -2471,6 +2813,15 @@ void protoSignalComputation2_fx( stereo_type_detect->min_sum_total_ratio_db_fx = min_sum_total_ratio_db_fx; // Q21 move32(); +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + /* Convert inst_diff to Word32 */ + inst_diff_bb_power_norm = W_norm( inst_diff_bb_power_64fx ); + stereo_type_detect->inst_diff_bb_power_fx = W_extract_h( W_shl( inst_diff_bb_power_64fx, inst_diff_bb_power_norm ) ); + move32(); + stereo_type_detect->q_inst_diff_bb_power_fx = add( shl( add( q_cldfb, s_min( min_q_shift[0], min_q_shift[1] ) ), 1 ), sub( inst_diff_bb_power_norm, 32 ) ); + move16(); +#endif + ivas_masa_stereotype_detection_fx( stereo_type_detect ); } ELSE @@ -3038,7 +3389,12 @@ void computeDirectionAngles_fx( *------------------------------------------------------------------------*/ void ivas_masa_init_stereotype_detection_fx( +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + MASA_STEREO_TYPE_DETECT *stereo_type_detect, + Word32 ivas_total_brate_fx ) +#else MASA_STEREO_TYPE_DETECT *stereo_type_detect ) +#endif { stereo_type_detect->masa_stereo_type = MASA_STEREO_DOWNMIX; move32(); @@ -3110,6 +3466,25 @@ void ivas_masa_init_stereotype_detection_fx( move32(); stereo_type_detect->subtract_target_ratio_db_fx = 0; move32(); +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + + stereo_type_detect->inst_diff_bb_power_fx = 0; + move32(); + stereo_type_detect->q_inst_diff_bb_power_fx = Q31; + move16(); + stereo_type_detect->inst_total_bb_power_fx = 0; + move32(); + stereo_type_detect->q_inst_total_bb_power_fx = Q31; + move16(); + + stereo_type_detect->max_band_diff_ene = IVAS_CLDFB_NO_CHANNELS_MAX; + move16(); + IF( LT_32( ivas_total_brate_fx, IVAS_48k ) ) + { + stereo_type_detect->max_band_diff_ene = 18; + move16(); + } +#endif return; } @@ -3138,6 +3513,12 @@ void ivas_masa_stereotype_detection_fx( Word32 lr_total_bb_temp_fx; Word32 lr_total_hi_temp_fx; Word32 temp; +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + Word16 change_to_dual_mono_selection; + Word32 diffPerSum_fx; /* Q31 */ + Word16 scale; + Word32 tau; /* Q31 */ +#endif lr_total_bb_ratio_db_fx = stereo_type_detect->lr_total_bb_ratio_db_fx; // q21 move32(); @@ -3148,6 +3529,33 @@ void ivas_masa_stereotype_detection_fx( subtract_target_ratio_db_fx = stereo_type_detect->subtract_target_ratio_db_fx; // q21 move32(); +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + /* Determine if broadband energy and ratio between difference broadband energy and broadband energy indicate + * that the signal type is dual mono */ + change_to_dual_mono_selection = 0; + move16(); + test(); + IF( LT_16( stereo_type_detect->q_inst_total_bb_power_fx, Q31 ) && GT_32( stereo_type_detect->inst_total_bb_power_fx, L_shl( 1, stereo_type_detect->q_inst_total_bb_power_fx ) ) ) /* Compare in var Q */ + { + tau = MASA_DUAL_MONO_TAU2_FX; + move32(); + IF( EQ_32( stereo_type_detect->current_stereo_type, MASA_DUAL_MONO ) ) + { + tau = MASA_DUAL_MONO_TAU1_FX; + move32(); + } + + diffPerSum_fx = BASOP_Util_Divide3232_Scale_newton( stereo_type_detect->inst_diff_bb_power_fx, stereo_type_detect->inst_total_bb_power_fx, &scale ); + diffPerSum_fx = L_shl_sat( diffPerSum_fx, add( scale, sub( stereo_type_detect->q_inst_total_bb_power_fx, stereo_type_detect->q_inst_diff_bb_power_fx ) ) ); /* Q31 */ + + IF( LT_32( diffPerSum_fx, tau ) ) /* Q31 comparison */ + { + change_to_dual_mono_selection = 1; + move16(); + } + } + +#endif /* Determine if the determined features match the spaced mic type */ change_to_spaced_selection = 0; move16(); @@ -3224,7 +3632,16 @@ void ivas_masa_stereotype_detection_fx( } ELSE { +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + IF( EQ_16( change_to_dual_mono_selection, 1 ) ) + { + stereo_type_detect->masa_stereo_type = MASA_DUAL_MONO; + move32(); + } + ELSE IF( EQ_16( change_to_spaced_selection, 1 ) ) +#else IF( EQ_16( change_to_spaced_selection, 1 ) ) +#endif { stereo_type_detect->masa_stereo_type = MASA_STEREO_SPACED_MICS; move32(); diff --git a/lib_rend/ivas_prot_rend_fx.h b/lib_rend/ivas_prot_rend_fx.h index ff893ac37..2650e6180 100644 --- a/lib_rend/ivas_prot_rend_fx.h +++ b/lib_rend/ivas_prot_rend_fx.h @@ -357,7 +357,12 @@ void computeDirectionAngles_fx( ); void ivas_masa_init_stereotype_detection_fx( +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + MASA_STEREO_TYPE_DETECT *stereo_type_detect, + Word32 ivas_total_brate_fx +#else MASA_STEREO_TYPE_DETECT *stereo_type_detect +#endif ); void ivas_masa_stereotype_detection_fx( diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index f2d1e4875..98a2b470d 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -384,6 +384,14 @@ typedef struct Word32 min_sum_total_ratio_db_fx; /* Q21 */ Word32 subtract_target_ratio_db_fx; /* Q21 */ +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + Word32 inst_diff_bb_power_fx; /* Q(q_inst_diff_bb_power_fx) */ + Word16 q_inst_diff_bb_power_fx; + Word32 inst_total_bb_power_fx; /* Q(q_inst_total_bb_power_fx) */ + Word16 q_inst_total_bb_power_fx; + Word16 max_band_diff_ene; + +#endif Word16 counter; Word16 interpolator; diff --git a/lib_rend/lib_rend_fx.c b/lib_rend/lib_rend_fx.c index a8fa97f38..3eadbada2 100644 --- a/lib_rend/lib_rend_fx.c +++ b/lib_rend/lib_rend_fx.c @@ -10572,7 +10572,11 @@ static ivas_error ivas_masa_ext_rend_dirac_rend_init( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } +#ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES + ivas_masa_init_stereotype_detection_fx( hDirACRend->masa_stereo_type_detect, IVAS_512k ); /* Use 512k to get correct path */ +#else ivas_masa_init_stereotype_detection_fx( hDirACRend->masa_stereo_type_detect ); +#endif } ELSE { -- GitLab From 5d03276092f9f85b99236fc102f3c2e9cebf5e59 Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Thu, 23 Apr 2026 14:37:14 +0300 Subject: [PATCH 2/5] Fix sanitizer bug. --- lib_rend/ivas_dirac_rend_fx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib_rend/ivas_dirac_rend_fx.c b/lib_rend/ivas_dirac_rend_fx.c index 1d294b350..10dcead10 100644 --- a/lib_rend/ivas_dirac_rend_fx.c +++ b/lib_rend/ivas_dirac_rend_fx.c @@ -1767,7 +1767,10 @@ void protoSignalComputation2_fx( #ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES interpolatorDualMono_fx = 0; move16(); - max_band_diff_ene = s_min( stereo_type_detect->max_band_diff_ene, num_freq_bands ); /* Local version for correct maximum */ + IF( stereo_type_detect != NULL ) + { + max_band_diff_ene = s_min( stereo_type_detect->max_band_diff_ene, num_freq_bands ); /* Local version for correct maximum */ + } #endif /* Calculate the max shift possible for the buffers RealBuffer_fx and ImagBuffer_fx */ -- GitLab From 892e69b2134da541784a24a3435728cf69d0bd78 Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Thu, 23 Apr 2026 14:38:54 +0300 Subject: [PATCH 3/5] Clang format --- lib_rend/ivas_dirac_rend_fx.c | 6 +++--- lib_rend/ivas_stat_rend.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib_rend/ivas_dirac_rend_fx.c b/lib_rend/ivas_dirac_rend_fx.c index 10dcead10..991fdcc21 100644 --- a/lib_rend/ivas_dirac_rend_fx.c +++ b/lib_rend/ivas_dirac_rend_fx.c @@ -2334,10 +2334,10 @@ void protoSignalComputation2_fx( } ELSE { - tempSpaced_fx = Madd_32_32( Mpy_32_32( re1, re1 ), im1, im1 ); // 2*(q_cldfb+min_q_shift)-31 + tempSpaced_fx = Madd_32_32( Mpy_32_32( re1, re1 ), im1, im1 ); // 2*(q_cldfb+min_q_shift)-31 - Real_aux_fx = L_shr( Real_aux_fx, 1 ); // q_cldfb+min_q_shift - Imag_aux_fx = L_shr( Imag_aux_fx, 1 ); // q_cldfb+min_q_shift + Real_aux_fx = L_shr( Real_aux_fx, 1 ); // q_cldfb+min_q_shift + Imag_aux_fx = L_shr( Imag_aux_fx, 1 ); // q_cldfb+min_q_shift tempDualMono_fx = Madd_32_32( Mpy_32_32( Real_aux_fx, Real_aux_fx ), Imag_aux_fx, Imag_aux_fx ); // 2*(q_cldfb+min_q_shift)-31 diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 98a2b470d..fcdd12c75 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -385,9 +385,9 @@ typedef struct Word32 subtract_target_ratio_db_fx; /* Q21 */ #ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES - Word32 inst_diff_bb_power_fx; /* Q(q_inst_diff_bb_power_fx) */ + Word32 inst_diff_bb_power_fx; /* Q(q_inst_diff_bb_power_fx) */ Word16 q_inst_diff_bb_power_fx; - Word32 inst_total_bb_power_fx; /* Q(q_inst_total_bb_power_fx) */ + Word32 inst_total_bb_power_fx; /* Q(q_inst_total_bb_power_fx) */ Word16 q_inst_total_bb_power_fx; Word16 max_band_diff_ene; -- GitLab From 038903e4ecbb99fe8f06987dfd8a81ddbb52629d Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Thu, 23 Apr 2026 14:52:32 +0300 Subject: [PATCH 4/5] Add default init --- lib_rend/ivas_dirac_rend_fx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib_rend/ivas_dirac_rend_fx.c b/lib_rend/ivas_dirac_rend_fx.c index 991fdcc21..61632cf0a 100644 --- a/lib_rend/ivas_dirac_rend_fx.c +++ b/lib_rend/ivas_dirac_rend_fx.c @@ -1767,6 +1767,9 @@ void protoSignalComputation2_fx( #ifdef FIX_FLOAT_1578_OMASA_REND_SPIKES interpolatorDualMono_fx = 0; move16(); + + max_band_diff_ene = IVAS_CLDFB_NO_CHANNELS_MAX; + move16(); IF( stereo_type_detect != NULL ) { max_band_diff_ene = s_min( stereo_type_detect->max_band_diff_ene, num_freq_bands ); /* Local version for correct maximum */ -- GitLab From e371e6880cb68b2a9006ca8b66cd0469dccc5da8 Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Mon, 27 Apr 2026 17:30:41 +0300 Subject: [PATCH 5/5] Fix some logic comparison BASOPs. --- lib_rend/ivas_dirac_rend_fx.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib_rend/ivas_dirac_rend_fx.c b/lib_rend/ivas_dirac_rend_fx.c index 61632cf0a..0743705bc 100644 --- a/lib_rend/ivas_dirac_rend_fx.c +++ b/lib_rend/ivas_dirac_rend_fx.c @@ -2266,7 +2266,8 @@ void protoSignalComputation2_fx( IF( ( EQ_16( stereo_type_detect->type_change_direction, MASA_STEREO_SPACED_MICS ) && EQ_16( stereo_type_detect->current_stereo_type, MASA_STEREO_DOWNMIX ) ) || ( EQ_16( stereo_type_detect->type_change_direction, MASA_STEREO_DOWNMIX ) && EQ_16( stereo_type_detect->current_stereo_type, MASA_STEREO_SPACED_MICS ) ) ) { - IF( L_or( LT_16( l, sub( dipole_freq_range[1], 1 ) ), GE_16( l, MASA_SUM_PROTO_START_BIN ) ) ) + test(); + IF( LT_16( l, sub( dipole_freq_range[1], 1 ) ) || GE_16( l, MASA_SUM_PROTO_START_BIN ) ) { Real_aux_fx = Madd_32_16( Mpy_32_16_1( Real_aux_fx, shr( interpolatorSpaced_fx, 1 ) ), Real_aux_fx, interpolatorDmx_fx ); // q_cldfb+min_q_shift Imag_aux_fx = Madd_32_16( Mpy_32_16_1( Imag_aux_fx, shr( interpolatorSpaced_fx, 1 ) ), Imag_aux_fx, interpolatorDmx_fx ); // q_cldfb+min_q_shift @@ -2314,7 +2315,8 @@ void protoSignalComputation2_fx( ELSE IF( ( EQ_16( stereo_type_detect->type_change_direction, MASA_STEREO_SPACED_MICS ) && EQ_16( stereo_type_detect->current_stereo_type, MASA_DUAL_MONO ) ) || ( EQ_16( stereo_type_detect->type_change_direction, MASA_DUAL_MONO ) && EQ_16( stereo_type_detect->current_stereo_type, MASA_STEREO_SPACED_MICS ) ) ) { - IF( L_or( LT_16( l, sub( dipole_freq_range[1], 1 ) ), GE_16( l, MASA_SUM_PROTO_START_BIN ) ) ) + test(); + IF( LT_16( l, sub( dipole_freq_range[1], 1 ) ) || GE_16( l, MASA_SUM_PROTO_START_BIN ) ) { Real_aux_fx = L_shr( Real_aux_fx, 1 ); // q_cldfb+min_q_shift Imag_aux_fx = L_shr( Imag_aux_fx, 1 ); // q_cldfb+min_q_shift @@ -2389,7 +2391,8 @@ void protoSignalComputation2_fx( } ELSE IF( EQ_16( stereo_type_detect->masa_stereo_type, MASA_STEREO_SPACED_MICS ) ) { - IF( L_or( LT_16( l, sub( dipole_freq_range[1], 1 ) ), GE_16( l, MASA_SUM_PROTO_START_BIN ) ) ) + test(); + IF( LT_16( l, sub( dipole_freq_range[1], 1 ) ) || GE_16( l, MASA_SUM_PROTO_START_BIN ) ) { Real_aux_fx = L_shr( Real_aux_fx, 1 ); // q_cldfb+min_q_shift Imag_aux_fx = L_shr( Imag_aux_fx, 1 ); // q_cldfb+min_q_shift -- GitLab