From 489187a154207c4261c30d302f3bc95aa16a2078 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Sun, 4 Feb 2024 07:50:03 +0530 Subject: [PATCH] Functions in ivas_mono_dmx_renderer converted to fixed point. [x]Below functions are converted: ivas_dmx_mono_renderer_open ivas_dmx_mono_renderer_close ivas_mono_downmix_render_passive ivas_mono_stereo_downmix_mcmasa ivas_apply_non_diegetic_panning (untested) --- lib_com/fft_fx.c | 26 ++-- lib_com/ivas_cnst.h | 4 + lib_com/ivas_prot_fx.h | 25 +++ lib_com/ivas_tools.c | 19 +++ lib_com/prot_fx2.h | 6 + lib_com/tools.c | 17 +++ lib_com/tools_fx.c | 2 +- lib_dec/ivas_jbm_dec.c | 182 ++++++++++++++++++++++ lib_dec/ivas_mono_dmx_renderer.c | 255 ++++++++++++++++++++++++++++++- lib_rend/ivas_stat_rend.h | 7 + 10 files changed, 526 insertions(+), 17 deletions(-) diff --git a/lib_com/fft_fx.c b/lib_com/fft_fx.c index 947dbc186..51ba8f62d 100644 --- a/lib_com/fft_fx.c +++ b/lib_com/fft_fx.c @@ -5439,17 +5439,21 @@ void rfft_fx( Word16 find_guarded_bits_fx( Word32 n ) { - return n <= 1 ? 0 : n <= 2 ? 1 - : n <= 4 ? 2 - : n <= 8 ? 3 - : n <= 16 ? 4 - : n <= 32 ? 5 - : n <= 64 ? 6 - : n <= 128 ? 7 - : n <= 256 ? 8 - : n <= 512 ? 9 - : n <= 1024 ? 10 - : 11; + return n <= 1 ? 0 : n <= 2 ? 1 + : n <= 4 ? 2 + : n <= 8 ? 3 + : n <= 16 ? 4 + : n <= 32 ? 5 + : n <= 64 ? 6 + : n <= 128 ? 7 + : n <= 256 ? 8 + : n <= 512 ? 9 + : n <= 1024 ? 10 + : n <= 2048 ? 11 + : n <= 4096 ? 12 + : n <= 8192 ? 13 + : n <= 16384 ? 14 + : 15; } Word16 L_norm_arr( Word32 *arr, Word16 size ) diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index e130f0869..70f7a5648 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -59,6 +59,10 @@ #define INV_SQRT2 7.071067811865475e-1f /* 1/sqrt(2) */ #define INV_SQRT3 0.577350269189626f /* 1/sqrt(3) */ +#ifdef IVAS_FLOAT_FIXED +#define INV_SQRT2_FX 23170 /* 1/sqrt(2) Q15*/ +#endif + #define LOG_10 2.30258509299f diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index dc9dbada5..6cf225e90 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -836,4 +836,29 @@ void stereo_decoder_tcx_fx( const Word16 tmp_plc_upmix, /* i : indicates temp upmix for PLC decision */ Word16 *q_x_ch2, Word16 *q_x_ch1 ); +void v_multc_acc_32_16( + const Word32 x[], /* i : Input vector */ + const Word16 c, /* i : Constant */ + Word32 y[], /* o : Output vector that contains y + c*x */ + const Word16 N /* i : Vector length */ +); + +void ivas_mono_stereo_downmix_mcmasa_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + Word32 *output_f_fx[], /* i/o: synthesized core-coder transport channels/mono or stereo output */ + Word16 output_frame /* i : output frame length per channel */ +); + +void ivas_apply_non_diegetic_panning_fx( + Word32 *output_f_fx[], /* i/o: core-coder transport mono channel/stereo output */ + const Word16 non_diegetic_pan_gain_fx, /* i : non-diegetic panning gain */ + const Word16 output_frame /* i : output frame length per channel */ +); + +void ivas_mono_downmix_render_passive_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + Word32 *output_f_fx[], /* i/o: synthesized core-coder transport channels/mono output */ + const Word16 output_frame /* i : output frame length */ +); + #endif diff --git a/lib_com/ivas_tools.c b/lib_com/ivas_tools.c index 170a7dc7b..3039ac303 100644 --- a/lib_com/ivas_tools.c +++ b/lib_com/ivas_tools.c @@ -1092,6 +1092,25 @@ void v_multc_acc( return; } +#ifdef IVAS_FLOAT_FIXED +void v_multc_acc_32_16( + const Word32 x[], /* i : Input vector */ + const Word16 c, /* i : Constant */ + Word32 y[], /* o : Output vector that contains y + c*x */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR ( i = 0; i < N; i++ ) + { + y[i] = L_add(y[i],Mpy_32_16_1(x[i],c)); + } + + return; +} +#endif + /*---------------------------------------------------------------------* * lls_interp_n() * diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index c686696a8..f071999ec 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -5144,6 +5144,12 @@ void v_multc_fixed( Word32 y[], /* o : Output vector that contains c*x */ const Word16 N /* i : Vector length */ ); +void v_multc_fixed_16( + const Word32 x[], /* i : Input vector */ + const Word16 c, /* i : Constant */ + Word32 y[], /* o : Output vector that contains c*x */ + const Word16 N /* i : Vector length */ +); void v_add_fixed( const Word32 x1[], /* i : Input vector 1 */ diff --git a/lib_com/tools.c b/lib_com/tools.c index 4e07856a4..1e1ba9dc7 100644 --- a/lib_com/tools.c +++ b/lib_com/tools.c @@ -1129,6 +1129,23 @@ void v_multc_fixed( return; } +void v_multc_fixed_16( + const Word32 x[], /* i : Input vector */ + const Word16 c, /* i : Constant */ + Word32 y[], /* o : Output vector that contains c*x */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR ( i = 0; i < N; i++ ) + { + y[i] = Mpy_32_16_1( x[i], c ); + } + + return; +} + /*-------------------------------------------------------------------* * squant() diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index e05a662fb..81e23737d 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -2142,7 +2142,7 @@ void v_add_32( for ( i = 0; i < N; i++ ) { - y[i] = x1[i] + x2[i]; + y[i] = L_add(x1[i] , x2[i]); } return; diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index 879fa29db..e2f880332 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -37,6 +37,7 @@ #include "rom_com.h" #include "prot.h" #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "ivas_prot_rend.h" #include "ivas_rom_com.h" #include @@ -61,6 +62,7 @@ static void ivas_jbm_dec_copy_masa_meta_to_buffer( Decoder_Struct *st_ivas ); static void ivas_jbm_masa_sf_to_slot_map( Decoder_Struct *st_ivas, const int16_t nCldfbTs ); + /*--------------------------------------------------------------------------* * ivas_jbm_dec_tc() * @@ -299,7 +301,41 @@ ivas_error ivas_jbm_dec_tc( if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) { +#ifdef IVAS_FLOAT_FIXED + Word32 *output_fx[12]; + for ( int lp = 0; lp < 12; lp++ ) + { + if ( p_output[lp] != NULL ) + { + output_fx[lp] = (Word32 *) malloc( sizeof( Word32 ) * L_FRAME48k ); + } + } + for ( int lp = 0; lp < 12; lp++ ) + { + if ( p_output[lp] != NULL ) + { + for ( int lp2 = 0; lp2 < output_frame; lp2++ ) + { + output_fx[lp][lp2] = (Word32) ( p_output[lp][lp2] * ( 1u << 11 ) ); + } + } + } + ivas_mono_downmix_render_passive_fx( st_ivas, output_fx, output_frame ); + + for ( int lp = 0; lp < 960; lp++ ) + { + p_output[0][lp] = (float) output_fx[0][lp] / ( 1u << 8 ); + } + for ( int lp = 0; lp < 12; lp++ ) + { + if ( p_output[lp] != NULL ) + { + free( output_fx[lp] ); + } + } +#else ivas_mono_downmix_render_passive( st_ivas, p_output, output_frame ); +#endif } else if ( st_ivas->ism_mode == ISM_MODE_PARAM && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) { @@ -639,7 +675,41 @@ ivas_error ivas_jbm_dec_tc( if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) { +#ifdef IVAS_FLOAT_FIXED + Word32 *p_output_fx[12]; + for ( int lp = 0; lp < 12; lp++ ) + { + if ( p_output[lp] != NULL ) + { + p_output_fx[lp] = (Word32 *) malloc( sizeof( Word32 ) * L_FRAME48k ); + } + } + for ( int lp = 0; lp < 12; lp++ ) + { + if ( p_output[lp] != NULL ) + { + for ( int lp2 = 0; lp2 < output_frame; lp2++ ) + { + p_output_fx[lp][lp2] = (Word32) ( p_output[lp][lp2] * ( 1u << 11 ) ); + } + } + } + ivas_mono_downmix_render_passive_fx( st_ivas, p_output_fx, output_frame ); + + for ( int lp = 0; lp < 960; lp++ ) + { + p_output[0][lp] = (float) p_output_fx[0][lp] / ( 1u << 8 ); + } + for ( int lp = 0; lp < 12; lp++ ) + { + if ( p_output[lp] != NULL ) + { + free( p_output_fx[lp] ); + } + } +#else ivas_mono_downmix_render_passive( st_ivas, p_output, output_frame ); +#endif } else if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) { @@ -832,7 +902,41 @@ ivas_error ivas_jbm_dec_tc( } else if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX && st_ivas->ism_mode == ISM_SBA_MODE_DISC ) { +#ifdef IVAS_FLOAT_FIXED + Word32 *p_output_fx[12]; + for ( int lp = 0; lp < 12; lp++ ) + { + if ( p_output[lp] != NULL ) + { + p_output_fx[lp] = (Word32 *) malloc( sizeof( Word32 ) * L_FRAME48k ); + } + } + for ( int lp = 0; lp < 12; lp++ ) + { + if ( p_output[lp] != NULL ) + { + for ( int lp2 = 0; lp2 < output_frame; lp2++ ) + { + p_output_fx[lp][lp2] = (Word32) ( p_output[lp][lp2] * ( 1u << 11 ) ); + } + } + } + ivas_mono_downmix_render_passive_fx( st_ivas, p_output_fx, output_frame ); + + for ( int lp = 0; lp < 960; lp++ ) + { + p_output[0][lp] = (float) p_output_fx[0][lp] / ( 1u << 8 ); + } + for ( int lp = 0; lp < 12; lp++ ) + { + if ( p_output[lp] != NULL ) + { + free( p_output_fx[lp] ); + } + } +#else ivas_mono_downmix_render_passive( st_ivas, p_output, output_frame ); +#endif /* add W */ for ( n = 0; n < nchan_out; n++ ) @@ -1174,7 +1278,45 @@ ivas_error ivas_jbm_dec_tc( if ( st_ivas->renderer_type == RENDERER_MCMASA_MONO_STEREO ) { +#ifdef IVAS_FLOAT_FIXED + Word32 *p_output_fx[12]; + for ( int lp = 0; lp < 12; lp++ ) + { + if ( p_output[lp] != NULL ) + { + + p_output_fx[lp] = (Word32 *) malloc( sizeof( Word32 ) * L_FRAME48k ); + } + } + for ( int lp = 0; lp < 12; lp++ ) + { + if ( p_output[lp] != NULL ) + { + for ( int lp2 = 0; lp2 < output_frame; lp2++ ) + { + p_output_fx[lp][lp2] = (Word32) ( p_output[lp][lp2] * ( 1u << 11 ) ); + } + } + } + ivas_mono_stereo_downmix_mcmasa_fx( st_ivas, p_output_fx, output_frame ); + + for ( int lp = 0; lp < 12; lp++ ) + { + if ( p_output[lp] != NULL ) + { + for ( int lp2 = 0; lp2 < output_frame; lp2++ ) + { + p_output[lp][lp2] = (float) p_output_fx[lp][lp2] / ( 1u << 11 ); + } + } + } + for ( int lp = 0; lp < 12; lp++ ) + { + free( p_output_fx[lp] ); + } +#else ivas_mono_stereo_downmix_mcmasa( st_ivas, p_output, output_frame ); +#endif } } } @@ -1487,7 +1629,27 @@ ivas_error ivas_jbm_dec_render( else if ( st_ivas->renderer_type == RENDERER_NON_DIEGETIC_DOWNMIX ) { *nSamplesRendered = min( st_ivas->hTcBuffer->n_samples_available, nSamplesAskedLocal ); +#ifdef IVAS_FLOAT_FIXED + Word32 *output_fx[2]; + output_fx[0] = (Word32 *) malloc( sizeof( Word32 ) * L_FRAME48k ); + output_fx[1] = (Word32 *) malloc( sizeof( Word32 ) * L_FRAME48k ); + for ( int lp = 0; lp < L_FRAME48k; lp++ ) + { + output_fx[0][lp] = (Word32) ( p_output[0][lp] * ( 1u << 11 ) ); + output_fx[1][lp] = (Word32) ( p_output[1][lp] * ( 1u << 11 ) ); + } + Word16 non_diegetic_pan_gain_fx = (Word16) ( 32767 * st_ivas->hDecoderConfig->non_diegetic_pan_gain ); + ivas_apply_non_diegetic_panning_fx( output_fx, non_diegetic_pan_gain_fx, *nSamplesRendered ); + for ( int lp = 0; lp < L_FRAME48k; lp++ ) + { + p_output[0][lp] = (float) output_fx[0][lp] / ( 1u << 11 ); + p_output[1][lp] = (float) output_fx[1][lp] / ( 1u << 11 ); + } + free( output_fx[0] ); + free( output_fx[1] ); +#else ivas_apply_non_diegetic_panning( p_output, st_ivas->hDecoderConfig->non_diegetic_pan_gain, *nSamplesRendered ); +#endif } else if ( st_ivas->renderer_type == RENDERER_PARAM_ISM || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) { @@ -1583,7 +1745,27 @@ ivas_error ivas_jbm_dec_render( } else if ( st_ivas->renderer_type == RENDERER_NON_DIEGETIC_DOWNMIX ) { +#ifdef IVAS_FLOAT_FIXED + Word32 *output_fx[2]; + output_fx[0] = (Word32 *) malloc( sizeof( Word32 ) * L_FRAME48k ); + output_fx[1] = (Word32 *) malloc( sizeof( Word32 ) * L_FRAME48k ); + for ( int lp = 0; lp < L_FRAME48k; lp++ ) + { + output_fx[0][lp] = (Word32) ( p_output[0][lp] * ( 1u << 11 ) ); + output_fx[1][lp] = (Word32) ( p_output[1][lp] * ( 1u << 11 ) ); + } + Word16 non_diegetic_pan_gain_fx = (Word16) ( 32767 * st_ivas->hDecoderConfig->non_diegetic_pan_gain ); + ivas_apply_non_diegetic_panning_fx( output_fx, non_diegetic_pan_gain_fx, *nSamplesRendered ); + for ( int lp = 0; lp < L_FRAME48k; lp++ ) + { + p_output[0][lp] = (float) output_fx[0][lp] / ( 1u << 11 ); + p_output[1][lp] = (float) output_fx[1][lp] / ( 1u << 11 ); + } + free( output_fx[0] ); + free( output_fx[1] ); +#else ivas_apply_non_diegetic_panning( p_output, st_ivas->hDecoderConfig->non_diegetic_pan_gain, *nSamplesRendered ); +#endif } else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) { diff --git a/lib_dec/ivas_mono_dmx_renderer.c b/lib_dec/ivas_mono_dmx_renderer.c index 093620963..f2682eb93 100644 --- a/lib_dec/ivas_mono_dmx_renderer.c +++ b/lib_dec/ivas_mono_dmx_renderer.c @@ -35,7 +35,10 @@ #include #include "cnst.h" #include "prot.h" +#include "prot_fx1.h" +#include "prot_fx2.h" #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" #include "ivas_rom_dec.h" @@ -47,16 +50,40 @@ *------------------------------------------------------------------------*/ #define DOWNMIX_ALPHA 0.95f /* Smoothing coefficient */ +#define DOWNMIX_ALPHA_FX 31130 /* Smoothing coefficient */ #define DOWNMIX_MAX_GAIN 4.0f /* Maximum allowed gain */ #define MONO_DOWNMIX_RENDERER_MAX_INPUT_CHANS 4 - /*------------------------------------------------------------------------- * ivas_mono_dmx_renderer_open() * * Open decoder downmix handle *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_mono_dmx_renderer_open( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + MONO_DOWNMIX_RENDERER_HANDLE hDownmix; + + IF( ( hDownmix = (MONO_DOWNMIX_RENDERER_HANDLE) malloc( sizeof( MONO_DOWNMIX_RENDERER_STRUCT ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for downmixing\n" ) ); + } + + hDownmix->inputEnergy = 0; // float + hDownmix->protoEnergy = 0; // float + hDownmix->inputEnergy_fx = 0; + hDownmix->protoEnergy_fx = 0; + hDownmix->Q_inputEner = 0; + hDownmix->Q_protoEner = 0; + + st_ivas->hMonoDmxRenderer = hDownmix; + + return IVAS_ERR_OK; +} +#else ivas_error ivas_mono_dmx_renderer_open( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ) @@ -74,7 +101,7 @@ ivas_error ivas_mono_dmx_renderer_open( return IVAS_ERR_OK; } - +#endif /*------------------------------------------------------------------------- * ivas_mono_dmx_renderer_close() @@ -82,11 +109,12 @@ ivas_error ivas_mono_dmx_renderer_open( * Close decoder downmix handle *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED void ivas_mono_dmx_renderer_close( MONO_DOWNMIX_RENDERER_HANDLE *hMonoDmxRenderer /* i/ i/o: Mono downmix structure */ ) { - if ( hMonoDmxRenderer == NULL || *hMonoDmxRenderer == NULL ) + IF( hMonoDmxRenderer == NULL || *hMonoDmxRenderer == NULL ) { return; } @@ -96,7 +124,22 @@ void ivas_mono_dmx_renderer_close( return; } +#else +void ivas_mono_dmx_renderer_close( + MONO_DOWNMIX_RENDERER_HANDLE *hMonoDmxRenderer /* i/ i/o: Mono downmix structure */ +) +{ + if ( hMonoDmxRenderer == NULL || *hMonoDmxRenderer == NULL ) + { + return; + } + free( *hMonoDmxRenderer ); + *hMonoDmxRenderer = NULL; + + return; +} +#endif /*------------------------------------------------------------------------- * ivas_mono_downmix_render_passive() @@ -141,6 +184,8 @@ void ivas_mono_downmix_render_passive( v_add( output_f[i], proto_signal, proto_signal, output_frame ); } + // dbgwrite2_txt(proto_signal, output_frame, "../proto_sig.txt"); + /* compute the input energy, proto energy after smoothing */ hDownmix->inputEnergy *= DOWNMIX_ALPHA; hDownmix->protoEnergy *= DOWNMIX_ALPHA; @@ -153,16 +198,155 @@ void ivas_mono_downmix_render_passive( hDownmix->inputEnergy += ( output_f[j][i] * output_f[j][i] ); } } - /* compute the eq factor */ eq = min( DOWNMIX_MAX_GAIN, sqrtf( hDownmix->inputEnergy / ( EPSILON + hDownmix->protoEnergy ) ) ); - /* equalize the downmix */ v_multc( proto_signal, eq, output_f[0], output_frame ); return; } +#ifdef IVAS_FLOAT_FIXED + + +void ivas_mono_downmix_render_passive_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + Word32 *output_f_fx[], /* i/o: synthesized core-coder transport channels/mono output */ + const Word16 output_frame /* i : output frame length */ +) +{ + Word16 i, j, numInputChannels; + Word32 proto_signal_fx[L_FRAME48k]; + Word16 eq_fx; + Word32 output_shr[L_FRAME48k]; + MONO_DOWNMIX_RENDERER_HANDLE hDownmix; + Word16 Q_shift, proto_shift, input_shift, norm_protoEner, norm_inputEner, proto_norm; + Word16 diff_shift, div, div_sqrt; + Word32 protoEner_pre, inputEner_pre; + numInputChannels = st_ivas->nSCE; + IF( EQ_16( (Word16) st_ivas->ivas_format, (Word16) SBA_ISM_FORMAT ) ) + { + numInputChannels = st_ivas->nchan_ism; + } + + IF( EQ_16( (Word16) st_ivas->ivas_format, (Word16) MASA_ISM_FORMAT ) ) + { + IF( EQ_16( (Word16) st_ivas->ism_mode, (Word16) ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( (Word16) st_ivas->ism_mode, (Word16) ISM_MASA_MODE_PARAM_ONE_OBJ ) ) + { + numInputChannels = add( st_ivas->nchan_transport, 1 ); + } + ELSE + { + numInputChannels = add( st_ivas->nchan_transport, st_ivas->nchan_ism ); + } + } + + hDownmix = st_ivas->hMonoDmxRenderer; + set32_fx( proto_signal_fx, 0, output_frame ); + + Word16 Output_norm = 32; + FOR( int lp = 0; lp < numInputChannels; lp++ ) + { + Word16 norm = L_norm_arr( output_f_fx[lp], output_frame ); + Output_norm = min( Output_norm, norm ); + } + Q_shift = sub( Output_norm, find_guarded_bits_fx( numInputChannels ) ); + + /* Compute the Proto Signal */ + FOR( i = 0; i < numInputChannels; i++ ) + { + v_shr_32( output_f_fx[i], output_shr, output_frame, -Q_shift ); + v_add_32( output_shr, proto_signal_fx, proto_signal_fx, output_frame ); + } + + /* compute the input energy, proto energy after smoothing */ + hDownmix->inputEnergy_fx = Mpy_32_16_1( hDownmix->inputEnergy_fx, DOWNMIX_ALPHA_FX ); + hDownmix->protoEnergy_fx = Mpy_32_16_1( hDownmix->protoEnergy_fx, DOWNMIX_ALPHA_FX ); + + proto_norm = L_norm_arr( proto_signal_fx, output_frame ); + + proto_shift = sub( proto_norm, shr( ( add( find_guarded_bits_fx( output_frame ), 1 ) ), 1 ) ); + input_shift = sub( Output_norm, shr( ( add( find_guarded_bits_fx( i_mult( output_frame, numInputChannels ) ), 1 ) ), 1 ) ); + protoEner_pre = 0; + move32(); + inputEner_pre = 0; + move32(); + FOR( i = 0; i < output_frame; i++ ) + { + Word32 proto_sh = L_shl( proto_signal_fx[i], proto_shift ); + protoEner_pre = L_add( protoEner_pre, Mpy_32_32( proto_sh, proto_sh ) ); + FOR( j = 0; j < numInputChannels; j++ ) + { + Word32 output_f_shift = L_shl( output_f_fx[j][i], input_shift ); + inputEner_pre = L_add( inputEner_pre, Mpy_32_32( output_f_shift, output_f_shift ) ); + } + } + + /* compute the eq factor */ + + IF( EQ_32( hDownmix->protoEnergy_fx, 0 ) ) + { + norm_protoEner = add( 31, hDownmix->Q_protoEner ); + } + ELSE + { + norm_protoEner = add( norm_l( hDownmix->protoEnergy_fx ), hDownmix->Q_protoEner ); + } + IF( EQ_32( hDownmix->inputEnergy_fx, 0 ) ) + { + norm_inputEner = add( 31, hDownmix->Q_inputEner ); + } + ELSE + { + norm_inputEner = add( norm_l( hDownmix->inputEnergy_fx ), hDownmix->Q_inputEner ); + } + + norm_protoEner = min( norm_protoEner, sub( shl( add( add( 11, Q_shift ), proto_shift ), 1 ), 31 ) ) - 1; + norm_inputEner = min( norm_inputEner, sub( shl( add( 11, input_shift ), 1 ), 31 ) ) - 1; + + hDownmix->protoEnergy_fx = L_shl( hDownmix->protoEnergy_fx, sub( norm_protoEner, hDownmix->Q_protoEner ) ); + hDownmix->inputEnergy_fx = L_shl( hDownmix->inputEnergy_fx, sub( norm_inputEner, hDownmix->Q_inputEner ) ); + + hDownmix->Q_protoEner = norm_protoEner; + hDownmix->Q_inputEner = norm_inputEner; + + protoEner_pre = L_shl( protoEner_pre, sub( norm_protoEner, sub( shl( add( add( 11, Q_shift ), proto_shift ), 1 ), 31 ) ) ); + inputEner_pre = L_shl( inputEner_pre, sub( norm_inputEner, sub( shl( add( 11, input_shift ), 1 ), 31 ) ) ); + + hDownmix->protoEnergy_fx = L_add( hDownmix->protoEnergy_fx, protoEner_pre ); + hDownmix->inputEnergy_fx = L_add( hDownmix->inputEnergy_fx, inputEner_pre ); + + diff_shift = sub( hDownmix->Q_inputEner, hDownmix->Q_protoEner ); + IF( GT_16( diff_shift, 0 ) ) + { + hDownmix->inputEnergy_fx = L_shr( hDownmix->inputEnergy_fx, diff_shift ); + hDownmix->Q_inputEner = sub( hDownmix->Q_inputEner, diff_shift ); + } + ELSE + { + hDownmix->protoEnergy_fx = L_shr( hDownmix->protoEnergy_fx, -diff_shift ); + hDownmix->Q_protoEner = add( hDownmix->Q_protoEner, diff_shift ); + } + IF( GE_32( hDownmix->protoEnergy_fx, L_shr( hDownmix->inputEnergy_fx, 2 ) ) ) + { + div = BASOP_Util_Divide3232_Scale( hDownmix->inputEnergy_fx, hDownmix->protoEnergy_fx, &diff_shift ); + div_sqrt = Sqrt16( div, &diff_shift ); + eq_fx = shr( div_sqrt, sub( 3, diff_shift ) ); + } + ELSE + { + eq_fx = 16384; + move16(); + } + + + /* equalize the downmix */ + v_multc_fixed_16( proto_signal_fx, eq_fx, output_f_fx[0], output_frame ); + v_shr_32( output_f_fx[0], output_f_fx[0], output_frame, Q_shift ); + + return; +} +#endif /*------------------------------------------------------------------------- * ivas_mono_stereo_downmix_mcmasa() @@ -209,6 +393,48 @@ void ivas_mono_stereo_downmix_mcmasa( return; } +#ifdef IVAS_FLOAT_FIXED +void ivas_mono_stereo_downmix_mcmasa_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + Word32 *output_f_fx[], /* i/o: synthesized core-coder transport channels/mono or stereo output */ + Word16 output_frame /* i : output frame length per channel */ +) +{ + Word16 i; + + Word32 dmx_tmp_fx[L_FRAME48k]; + + set32_fx( dmx_tmp_fx, 0, output_frame ); + + /* Dowmix center channel to L and R */ + if ( st_ivas->hDecoderConfig->nchan_out == 2 && st_ivas->hOutSetup.separateChannelEnabled ) + { + v_multc_acc_32_16( output_f_fx[st_ivas->hOutSetup.separateChannelIndex], INV_SQRT2_FX, output_f_fx[0], output_frame ); + v_multc_acc_32_16( output_f_fx[st_ivas->hOutSetup.separateChannelIndex], INV_SQRT2_FX, output_f_fx[1], output_frame ); + } + /* Mono downmix */ + else if ( st_ivas->hDecoderConfig->nchan_out == 1 ) + { + /* Downmix L and R to dmx_tmp */ + for ( i = 0; i < st_ivas->nchan_transport; i++ ) + { + v_multc_acc_32_16( output_f_fx[i], INV_SQRT2_FX, dmx_tmp_fx, output_frame ); + } + /* Add center channel */ + if ( st_ivas->hOutSetup.separateChannelEnabled ) + { + v_add_32( output_f_fx[st_ivas->hOutSetup.separateChannelIndex], dmx_tmp_fx, dmx_tmp_fx, output_frame ); + } + + /* Move to output */ + Copy32( dmx_tmp_fx, output_f_fx[0], output_frame ); + } + + return; +} + +#endif + /*------------------------------------------------------------------------- * ivas_apply_non_diegetic_panning() @@ -232,3 +458,22 @@ void ivas_apply_non_diegetic_panning( return; } + +#ifdef IVAS_FLOAT_FIXED +void ivas_apply_non_diegetic_panning_fx( + Word32 *output_f_fx[], /* i/o: core-coder transport mono channel/stereo output */ + const Word16 non_diegetic_pan_gain_fx, /* i : non-diegetic panning gain */ + const Word16 output_frame /* i : output frame length per channel */ +) +{ + Word16 pan_left_fx, pan_right_fx; + + pan_left_fx = mult( non_diegetic_pan_gain_fx, 16348 ) + 16348; + pan_right_fx = 32767 - pan_left_fx; + + v_multc_fixed( output_f_fx[0], L_shl( L_deposit_l( pan_right_fx ), 16 ), output_f_fx[1], output_frame ); + v_multc_fixed( output_f_fx[0], L_shl( L_deposit_l( pan_left_fx ), 16 ), output_f_fx[0], output_frame ); + + return; +} +#endif diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 9afb1529b..ec17065ba 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1813,6 +1813,13 @@ typedef struct ivas_mono_downmix_renderer_struct { float inputEnergy; float protoEnergy; +#ifdef IVAS_FLOAT_FIXED + Word32 inputEnergy_fx; + Word16 Q_inputEner; + Word32 protoEnergy_fx; + Word16 Q_protoEner; + +#endif } MONO_DOWNMIX_RENDERER_STRUCT, *MONO_DOWNMIX_RENDERER_HANDLE; -- GitLab