diff --git a/lib_com/cnst.h b/lib_com/cnst.h index 72152c22be6febbefc7311c9d6c23eaa8eba7ac0..c86b95e1599e2983041df221cfa6daf80624aae2 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -157,6 +157,9 @@ #define MAX16B_FLT 32767.0f #define MIN16B_FLT ( -32768.0f ) #define PCM16_TO_FLT_FAC 32768.0f +#ifdef IVAS_FLOAT_FIXED +#define PCM16_TO_FLT_FAC_FX 32768 +#endif // IVAS_FLOAT_FIXED #define MDFT_NORM_SCALING ( 1.0f / PCM16_TO_FLT_FAC ) #define MAX_FRAME_COUNTER 200 #define MAX_BITS_PER_FRAME 10240 /* Bits per frame for max. bitrate 512kbps, == IVAS_MAX_BITS_PER_FRAME */ diff --git a/lib_com/float_to_fix_ops.c b/lib_com/float_to_fix_ops.c index b3c6b63bbe1c33fab98fbcc84b9fd475a019af36..2eb615707e17ac66635698273b3a947fb04d353e 100644 --- a/lib_com/float_to_fix_ops.c +++ b/lib_com/float_to_fix_ops.c @@ -26,7 +26,20 @@ void floatToFixed_arrL(float *f, Word32 *i, Word16 Q, Word16 l) { for (int j = 0; j < l; j++) { +#if 0 i[j] = floatToFixed(f[j], Q); +#else + Word64 i64_val = floatToFixed( f[j], Q ); + IF( i64_val > MAX_32 ) + { + i64_val = MAX_32; + } + ELSE IF( i64_val < MIN_32 ) + { + i64_val = MIN_32; + } + i[j] = (Word32) i64_val; +#endif } } void floatToFixed_arr(float *f, Word16 *i, Word16 Q, Word16 l) diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 8acefc5b496dab302c6afca964f63eaa6305ce28..bbbd96debe741bd06d6a50daa52c671c6e23f4bf 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -3944,6 +3944,13 @@ void ivas_sba_getTCs( ); /*! r: SBA DirAC stereo flag */ +#ifdef IVAS_FLOAT_FIXED +Word16 ivas_sba_remapTCs_fx( + Word32 *sba_data[], /* i/o: SBA signals */ + Decoder_Struct *st_ivas, /* i/o: decoder struct */ + const Word16 output_frame /* i : frame length */ +); +#endif // IVAS_FLOAT_FIXED int16_t ivas_sba_remapTCs( float *sba_data[], /* i/o: SBA signals */ Decoder_Struct *st_ivas, /* i/o: decoder struct */ @@ -4651,6 +4658,17 @@ ivas_error ivas_sba_linear_renderer( const AUDIO_CONFIG output_config, /* i : output audio configuration */ const IVAS_OUTPUT_SETUP output_setup /* i : output format setup */ ); +#ifdef IVAS_FLOAT_FIXED +void ivas_sba_mix_matrix_determiner_fx( + SPAR_DEC_HANDLE hSpar, /* i/o: SPAR decoder handle */ + Word32 *output_fx[], /* i/o: transport/output audio channels */ + const Word16 bfi, /* i : BFI flag */ + const Word16 nchan_remapped, /* i : num channels after remapping of TCs */ + const Word16 output_frame, /* i : output frame length */ + const Word16 num_md_sub_frames, /* i : number of subframes in mixing matrix */ + Word16* Q_mixer_mat +); +#endif // IVAS_FLOAT_FIXED void ivas_sba_mix_matrix_determiner( SPAR_DEC_HANDLE hSpar, /* i/o: SPAR decoder handle */ @@ -5058,6 +5076,16 @@ void ivas_spar_setup_md_smoothing( const int16_t num_bands_out, /* i : number of output bands */ const int16_t num_md_sub_frames /* i : number of metadata subframes */ ); +#ifdef IVAS_FLOAT_FIXED +void ivas_spar_dec_gen_umx_mat_fx( + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ + const Word16 nchan_transport, /* i : number of transport channels */ + const Word16 num_bands_out, /* i : number of output bands */ + const Word16 bfi, /* i : bad frame indicator */ + const Word16 num_md_sub_frames, + Word16 * Q_mixer_mat +); +#endif // IVAS_FLOAT_FIXED void ivas_spar_dec_gen_umx_mat( ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ @@ -5763,6 +5791,16 @@ void ivas_ism_get_stereo_gains( float *left_gain, /* o : left channel gain */ float *right_gain /* o : right channel gain */ ); +#ifdef IVAS_FLOAT_FIXED +void ivas_mc2sba_fx( + IVAS_OUTPUT_SETUP hIntSetup, /* i : Format of decoder output */ + Word32 *in_buffer_td[], /* i : MC signals (on input) and the HOA3 (on output) */ + Word32 *buffer_td[], /* i/o: MC signals (on input) and the HOA3 (on output) */ + const Word16 output_frame, /* i : output frame length per channel */ + const Word16 sba_order, /* i : Ambisonic (SBA) order */ + const Word16 gain_lfe /* i : gain for LFE, 0 = ignore LFE */ +); +#endif // IVAS_FLOAT_FIXED void ivas_mc2sba( IVAS_OUTPUT_SETUP hIntSetup, /* i : Format of decoder output */ @@ -5772,6 +5810,17 @@ void ivas_mc2sba( const int16_t sba_order, /* i : SBA order */ const float gain_lfe /* i : gain for LFE, 0=ignore LFE */ ); +#ifdef IVAS_FLOAT_FIXED +void ivas_param_mc_mc2sba_cldfb_fx( + IVAS_OUTPUT_SETUP hTransSetup, /* i : transported MC Format */ + Word32 *hoa_encoder, /* i : HOA3 encoder for the transported MC format */ + const Word16 slot_idx, /* i : current slot in the subframe */ + Word32 Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: Contains the MC signals (on input) and the HOA3 (on output) */ + Word32 Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: Contains the MC signals (on input) and the HOA3 (on output) */ + const Word16 nBands, /* i : number of synth CLDFB bands */ + const Word16 gain_lfe /* i : gain applied to LFE */ +); +#endif // IVAS_FLOAT_FIXED void ivas_param_mc_mc2sba_cldfb( IVAS_OUTPUT_SETUP hTransSetup, /* i : transported MC Format */ @@ -5783,6 +5832,17 @@ void ivas_param_mc_mc2sba_cldfb( const float gain_lfe /* i : gain applied to LFE */ ); +#ifdef IVAS_FLOAT_FIXED +void ivas_ism2sba_sf_fx( + Word32 *buffer_in_fx[], /* i : TC buffer */ + Word32 *buffer_out_fx[], /* o : TD signal buffers */ + ISM_RENDERER_HANDLE hIsmRendererData, /* i/o: renderer data */ + const Word16 num_objects, /* i : number of objects */ + const Word16 n_samples_to_render, /* i : output frame length per channel */ + const Word16 offset, /* i : offset for the interpolatr */ + const Word16 sba_order /* i : Ambisonic (SBA) order */ +); +#endif // IVAS_FLOAT_FIXED void ivas_ism2sba_sf( float *buffer_in[], /* i : TC buffer */ float *buffer_out[], /* o : TD signal buffers */ diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index 0364477fc6814caa557b13ed6edcc6f6460b177a..8b972783fc29a16b502590272408e6d7250b308c 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -929,7 +929,41 @@ ivas_error ivas_jbm_dec_tc( if ( st_ivas->ivas_format == SBA_FORMAT ) { +#ifdef IVAS_FLOAT_FIXED +#if 1 + Word32* p_output_fx[12]; + Word16 Q_sba = 31; + FOR( Word16 lp = 0; lp < 12; lp++ ) + { + IF( p_output[lp] != NULL ) + { + p_output_fx[lp] = (Word32 *) malloc( sizeof( Word32 ) * L_FRAME48k ); + } + } + FOR( Word16 i = 2; i <= 3; i++ ) + { + Q_sba = s_min( Q_sba, Q_factor_arrL( p_output[i], output_frame ) ); + } + FOR( Word16 i = 2; i <= 3; i++ ) + { + floatToFixed_arrL( p_output[i], p_output_fx[i], Q_sba, output_frame ); + } +#endif + nchan_remapped = ivas_sba_remapTCs_fx(p_output_fx, st_ivas, output_frame ); + FOR( Word16 i = 2; i <= 3; i++ ) + { + fixedToFloat_arrL(p_output_fx[i], p_output[i], Q_sba, output_frame ); + } + FOR( Word16 lp = 0; lp < 12; lp++ ) + { + IF( p_output[lp] != NULL ) + { + free( p_output_fx[lp] ); + } + } +#else nchan_remapped = ivas_sba_remapTCs( p_output, st_ivas, output_frame ); +#endif // IVAS_FLOAT_FIXED if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) { @@ -1295,13 +1329,176 @@ ivas_error ivas_jbm_dec_tc( hp20_flt( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); } +#ifdef IVAS_FLOAT_FIXED +#if 1 + Word32 *p_output_fx[12]; + Word16 Q_sba = 31; + FOR( Word16 lp = 0; lp < 12; lp++ ) + { + IF( p_output[lp] != NULL ) + { + p_output_fx[lp] = (Word32 *) malloc( sizeof( Word32 ) * L_FRAME48k ); + } + } + FOR( Word16 i = sba_ch_idx + 2; i <= sba_ch_idx + 3; i++ ) + { + Q_sba = s_min( Q_sba, Q_factor_arrL( p_output[i], output_frame ) ); + } + FOR( Word16 i = sba_ch_idx + 2; i <= sba_ch_idx + 3; i++ ) + { + floatToFixed_arrL( p_output[i], p_output_fx[i], Q_sba, output_frame ); + } +#endif + nchan_remapped = ivas_sba_remapTCs_fx( &p_output_fx[sba_ch_idx], st_ivas, output_frame ); + FOR( Word16 i = sba_ch_idx + 2; i <= sba_ch_idx + 3; i++ ) + { + fixedToFloat_arrL( p_output_fx[i], p_output[i], Q_sba, output_frame ); + } + FOR( Word16 lp = 0; lp < 12; lp++ ) + { + IF( p_output[lp] != NULL ) + { + free( p_output_fx[lp] ); + } + } +#else nchan_remapped = ivas_sba_remapTCs( &p_output[sba_ch_idx], st_ivas, output_frame ); +#endif if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) { num_md_sub_frames = ivas_get_spar_dec_md_num_subframes( st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->last_active_ivas_total_brate ); +#ifdef IVAS_FLOAT_FIXED +#if 1 + Word16 ch, i; + SPAR_DEC_HANDLE hSpar = st_ivas->hSpar; + Word16 Q_p_output = 14; + Word16 num_bands_out, nchan_transport; + num_bands_out = hSpar->hFbMixer->pFb->filterbank_num_bands; + nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; + nchan_out = nchan_transport; + Word32 *output_fx[12]; + FOR( Word16 c = 0; c < nchan_transport; c++ ) + { + output_fx[c] = malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( Word32 ) ); + } + FOR( ch = 0; ch < nchan_transport; ch++ ) + { + FOR( i = 0; i < output_frame; i++ ) + { + output_fx[ch][i] = floatToFixed( p_output[sba_ch_idx + ch][i], Q_p_output ); + } + } + Word16 j, b, i_ts, num_out_ch; + num_out_ch = hSpar->hMdDec->spar_md_cfg.num_umx_chs; + Word16 Q_C_re_fx = 31, Q_P_re_fx = 31, Q_mixer_mat = 31; + Word16 num_in_ch; + num_in_ch = hSpar->hMdDec->spar_md_cfg.num_umx_chs; + FOR( i_ts = 0; i_ts < num_md_sub_frames; i_ts++ ) + { + FOR( i = 0; i < num_out_ch; i++ ) + { + FOR( j = 0; j < num_in_ch; j++ ) + { + FOR( b = 0; b < num_bands_out; b++ ) + { + Q_mixer_mat = s_min( Q_mixer_mat, Q_factor_L( hSpar->hMdDec->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] ) ); + } + } + } + } + FOR( i_ts = 0; i_ts < num_md_sub_frames; i_ts++ ) + { + FOR( i = 0; i < num_out_ch; i++ ) + { + FOR( j = 0; j < nchan_transport; j++ ) + { + FOR( b = 0; b < num_bands_out; b++ ) + { + Q_C_re_fx = s_min( Q_C_re_fx, Q_factor_L( hSpar->hMdDec->spar_coeffs.C_re[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] ) ); + } + } + } + } + FOR( i_ts = 0; i_ts < num_md_sub_frames; i_ts++ ) + { + FOR( i = 0; i < num_out_ch; i++ ) + { + FOR( j = nchan_transport; j < num_out_ch; j++ ) + { + FOR( b = 0; b < num_bands_out; b++ ) + { + Q_P_re_fx = s_min( Q_P_re_fx, Q_factor_L( hSpar->hMdDec->spar_coeffs.P_re[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] ) ); + } + } + } + } + Q_mixer_mat = s_min( Q_mixer_mat, s_min( Q_C_re_fx, Q_P_re_fx ) ); + FOR( i_ts = 0; i_ts < num_md_sub_frames; i_ts++ ) + { + FOR( i = 0; i < num_out_ch; i++ ) + { + FOR( j = 0; j < num_in_ch; j++ ) + { + FOR( b = 0; b < num_bands_out; b++ ) + { + hSpar->hMdDec->mixer_mat_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = floatToFixed( hSpar->hMdDec->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS], Q_mixer_mat ); + } + } + } + FOR( i = 0; i < num_out_ch; i++ ) + { + FOR( j = 0; j < nchan_transport; j++ ) + { + FOR( b = 0; b < num_bands_out; b++ ) + { + hSpar->hMdDec->spar_coeffs.C_re_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = floatToFixed( hSpar->hMdDec->spar_coeffs.C_re[i][j][b + i_ts * IVAS_MAX_NUM_BANDS], Q_mixer_mat ); + } + } + } + FOR( i = 0; i < num_out_ch; i++ ) + { + FOR( j = nchan_transport; j < num_out_ch; j++ ) + { + FOR( b = 0; b < num_bands_out; b++ ) + { + hSpar->hMdDec->spar_coeffs.P_re_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = floatToFixed( hSpar->hMdDec->spar_coeffs.P_re[i][j][b + i_ts * IVAS_MAX_NUM_BANDS], Q_mixer_mat ); + } + } + } + } +#endif + ivas_sba_mix_matrix_determiner_fx( st_ivas->hSpar, output_fx, st_ivas->bfi, nchan_remapped, output_frame, num_md_sub_frames ,&Q_mixer_mat); +#if 1 /*Fixed to float changes */ + FOR( i_ts = 0; i_ts < num_md_sub_frames; i_ts++ ) + { + FOR( i = 0; i < num_out_ch; i++ ) + { + FOR( j = 0; j < num_in_ch; j++ ) + { + FOR( b = 0; b < num_bands_out; b++ ) + { + hSpar->hMdDec->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = fixedToFloat( hSpar->hMdDec->mixer_mat_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS], Q_mixer_mat ); + } + } + } + } + FOR( Word16 c = 0; c < nchan_transport; c++ ) + { + FOR( j = 0; j < output_frame; j++ ) + { + p_output[sba_ch_idx+c][j] = (float) output_fx[c][j]; + } + } + FOR( Word16 c = 0; c < nchan_transport; c++ ) + { + free( output_fx[c] ); + } +#endif +#else ivas_sba_mix_matrix_determiner( st_ivas->hSpar, &p_output[sba_ch_idx], st_ivas->bfi, nchan_remapped, output_frame, num_md_sub_frames ); +#endif // IVAS_FLOAT_FIXED } else if ( st_ivas->renderer_type != RENDERER_DISABLE && !st_ivas->sba_dirac_stereo_flag ) { @@ -1398,7 +1595,43 @@ ivas_error ivas_jbm_dec_tc( { if ( ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) >= ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ) ) { +#ifdef IVAS_FLOAT_FIXED +#if 1 + Word32 *p_output_fx[12]; + FOR ( Word16 lp = 0; lp < 12; lp++ ) + { + IF ( p_output[lp] != NULL ) + { + p_output_fx[lp] = (Word32 *) malloc( sizeof( Word32 ) * L_FRAME48k ); + } + } + Word16 Q_in_buffer_td = 31, i; + FOR( i = 0; i < st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; i++ ) + { + Q_in_buffer_td = s_min( Q_in_buffer_td, Q_factor_arrL( p_output[i], output_frame ) ); + } + FOR( i = 0; i < st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; i++ ) + { + floatToFixed_arrL( p_output[i], p_output_fx[i], Q_in_buffer_td, output_frame ); + } +#endif // IVAS_FLOAT_FIXED + ivas_mc2sba_fx( st_ivas->hTransSetup, p_output_fx, p_output_fx, output_frame, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE_FX ); +#if 1 + FOR ( i = 0; i < ( st_ivas->hIntSetup.ambisonics_order + 1 ) * ( st_ivas->hIntSetup.ambisonics_order + 1 ); i++ ) + { + fixedToFloat_arrL( p_output_fx[i], p_output[i], Q_in_buffer_td - 3, output_frame ); + } + FOR( Word16 lp = 0; lp < 12; lp++ ) + { + IF ( p_output[lp] != NULL ) + { + free( p_output_fx[lp] ); + } + } +#endif +#else ivas_mc2sba( st_ivas->hTransSetup, p_output, p_output, output_frame, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE ); +#endif // IVAS_FLOAT_FIXED } } @@ -2288,7 +2521,43 @@ ivas_error ivas_jbm_dec_render( if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) { /* Convert CICP19 -> Ambisonics */ +#ifdef IVAS_FLOAT_FIXED +#if 1 + Word32 *p_output_fx[20]; + FOR( Word16 lp = 0; lp < 20; lp++ ) + { + IF ( p_output[lp] != NULL ) + { + p_output_fx[lp] = (Word32 *) malloc( sizeof( Word32 ) * L_FRAME48k ); + } + } + Word16 Q_in_buffer_td = 31, i; + FOR( i = 0; i < st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; i++ ) + { + Q_in_buffer_td = s_min( Q_in_buffer_td, Q_factor_arrL( p_output[i], *nSamplesRendered ) ); + } + FOR( i = 0; i < st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; i++ ) + { + floatToFixed_arrL( p_output[i], p_output_fx[i], Q_in_buffer_td, *nSamplesRendered ); + } +#endif // IVAS_FLOAT_FIXED + ivas_mc2sba_fx( st_ivas->hIntSetup, p_output_fx, p_output_fx, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0 ); +#if 1 + FOR( i = 0; i < (st_ivas->hOutSetup.ambisonics_order + 1 ) * (st_ivas->hOutSetup.ambisonics_order + 1 ); i++ ) + { + fixedToFloat_arrL( p_output_fx[i], p_output[i], Q_in_buffer_td - 3, *nSamplesRendered); + } + FOR( Word16 lp = 0; lp < 20; lp++ ) + { + IF( p_output[lp] != NULL ) + { + free( p_output_fx[lp] ); + } + } +#endif +#else ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0.f ); +#endif // IVAS_FLOAT_FIXED } } } @@ -2403,7 +2672,52 @@ ivas_error ivas_jbm_dec_render( else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) { /* Convert to Ambisonics; used also for ISM->HOA3->binaural rendering */ +#ifdef IVAS_FLOAT_FIXED + FOR( i = 0; i < *nSamplesRendered + st_ivas->hTcBuffer->n_samples_rendered; i++ ) + { + st_ivas->hIsmRendererData->interpolator_fx[i] = (Word16) float_to_fix16( st_ivas->hIsmRendererData->interpolator[i], 15 ); + } + FOR( i = 0; i < 15; i++ ) + { + FOR( j = 0; j < 16; j++ ) + { + st_ivas->hIsmRendererData->gains_fx[i][j] = floatToFixed( st_ivas->hIsmRendererData->gains[i][j], Q29 ); + st_ivas->hIsmRendererData->prev_gains_fx[i][j] = floatToFixed( st_ivas->hIsmRendererData->prev_gains[i][j], Q29 ); + } + } + Word32 *p_output_fx[20]; + FOR( Word16 lp = 0; lp < 20; lp++ ) + { + IF( p_output[lp] != NULL ) + { + p_output_fx[lp] = (Word32 *) malloc( sizeof( Word32 ) * L_FRAME48k ); + } + } + Word16 Q_buffer_in = 31; + FOR( i = 0; i < st_ivas->nchan_transport; i++ ) + { + Q_buffer_in = s_min( Q_buffer_in, Q_factor_arrL( st_ivas->hTcBuffer->tc[i], L_FRAME48k ) ); + } + FOR( i = 0; i < st_ivas->nchan_transport; i++ ) + { + floatToFixed_arrL( st_ivas->hTcBuffer->tc[i], st_ivas->hTcBuffer->tc_fx[i], Q_buffer_in, L_FRAME48k ); + } + ivas_ism2sba_sf_fx( st_ivas->hTcBuffer->tc_fx, p_output_fx, st_ivas->hIsmRendererData, st_ivas->nchan_transport, *nSamplesRendered, st_ivas->hTcBuffer->n_samples_rendered, st_ivas->hIntSetup.ambisonics_order ); + Word16 sba_num_chans = imult1616( add( st_ivas->hIntSetup.ambisonics_order, 1 ), add( st_ivas->hIntSetup.ambisonics_order, 1 ) ); + FOR( j = 0; j < sba_num_chans; j++ ) + { + fixedToFloat_arrL( p_output_fx[j], p_output[j], Q_buffer_in + 29 - 31, *nSamplesRendered ); + } + FOR( Word16 lp = 0; lp < 20; lp++ ) + { + IF( p_output[lp] != NULL ) + { + free( p_output_fx[lp] ); + } + } +#else ivas_ism2sba_sf( st_ivas->hTcBuffer->tc, p_output, st_ivas->hIsmRendererData, st_ivas->nchan_transport, *nSamplesRendered, st_ivas->hTcBuffer->n_samples_rendered, st_ivas->hIntSetup.ambisonics_order ); +#endif // IVAS_FLOAT_FIXED } /* Binaural rendering */ diff --git a/lib_dec/ivas_mc_param_dec.c b/lib_dec/ivas_mc_param_dec.c index 11d3aaf77aa055c85399fa7d58f85666863e66c4..e4621731c9979a7ce0a01e5958c7a72dd0687d5c 100644 --- a/lib_dec/ivas_mc_param_dec.c +++ b/lib_dec/ivas_mc_param_dec.c @@ -1849,7 +1849,36 @@ void ivas_param_mc_dec_render( if ( st_ivas->hCombinedOrientationData && st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) { +#ifdef IVAS_FLOAT_FIXED +#if 1 + IF( ( hParamMC->hoa_encoder_fx = (Word32 *) malloc(st_ivas->hTransSetup.nchan_out_woLFE * MAX_INTERN_CHANNELS * sizeof( Word32 ) ) ) == NULL ) + { + assert( 0 ); + } + Word16 Q_hoa_encoder = 31; + floatToFixed_arrL(hParamMC->hoa_encoder, hParamMC->hoa_encoder_fx, Q_hoa_encoder, st_ivas->hTransSetup.nchan_out_woLFE * MAX_INTERN_CHANNELS ); + Word32 Cldfb_RealBuffer_fx[16][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_fx[16][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + Word16 Q_Cldfb_ImagBuffer, Q_Cldfb_RealBuffer; + Q_Cldfb_ImagBuffer = Q_factor_arrL( &Cldfb_ImagBuffer[0][0][0], 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ) - 5;/*max value =MAX_INTERN_CHANNELS(=16)*Cldfb_ImagBuffer_fx*/ + Q_Cldfb_RealBuffer = Q_factor_arrL( &Cldfb_RealBuffer[0][0][0], 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ) - 5; + floatToFixed_arrL( &Cldfb_ImagBuffer[0][0][0], &Cldfb_ImagBuffer_fx[0][0][0], Q_Cldfb_ImagBuffer, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ); + floatToFixed_arrL( &Cldfb_RealBuffer[0][0][0], &Cldfb_RealBuffer_fx[0][0][0], Q_Cldfb_RealBuffer, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ); +#endif + ivas_param_mc_mc2sba_cldfb_fx( st_ivas->hTransSetup, hParamMC->hoa_encoder_fx, slot_idx, Cldfb_RealBuffer_fx, Cldfb_ImagBuffer_fx, nband_synth, GAIN_LFE_FX ); +#if 1 + + fixedToFloat_arrL( &Cldfb_ImagBuffer_fx[0][0][0], &Cldfb_ImagBuffer[0][0][0], Q_Cldfb_ImagBuffer, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ); + fixedToFloat_arrL( &Cldfb_RealBuffer_fx[0][0][0], &Cldfb_RealBuffer[0][0][0], Q_Cldfb_RealBuffer, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ); + IF(hParamMC->hoa_encoder_fx) + { + free(hParamMC->hoa_encoder_fx); + } +#endif // IVAS_FLOAT_FIXED +#else ivas_param_mc_mc2sba_cldfb( st_ivas->hTransSetup, hParamMC->hoa_encoder, slot_idx, Cldfb_RealBuffer, Cldfb_ImagBuffer, nband_synth, GAIN_LFE ); +#endif // IVAS_FLOAT_FIXED + } else { diff --git a/lib_dec/ivas_sba_rendering_internal.c b/lib_dec/ivas_sba_rendering_internal.c index 1bfbe933cd1451c6611149f9c0c82a97e7069f9f..cc5a03f6bae065ed03dec5ccc38f2959982b23e1 100644 --- a/lib_dec/ivas_sba_rendering_internal.c +++ b/lib_dec/ivas_sba_rendering_internal.c @@ -41,6 +41,7 @@ #include "wmc_auto.h" #ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" +#include "prot_fx2.h" #endif // IVAS_FLOAT_FIXED #ifdef DUMPS_ENABLED #include "debug.h" @@ -194,6 +195,84 @@ void ivas_sba2mc_cldfb_fixed( * * MC signals transformed into SBA in TD domain *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_mc2sba_fx( + IVAS_OUTPUT_SETUP hIntSetup, /* i : Format of decoder output */ + Word32 *in_buffer_td_fx[], /* i : MC signals (on input) and the HOA3 (on output) *//*Q*/ + Word32 *buffer_td_fx[], /* i/o: MC signals (on input) and the HOA3 (on output) */ + const Word16 output_frame, /* i : output frame length per channel */ + const Word16 sba_order, /* i : Ambisonic (SBA) order */ + const Word16 gain_lfe_fx /* i : gain for LFE, 0 = ignore LFE */ +) +{ + Word16 i, j, k; + Word16 idx_lfe, idx_in; + Word32 buffer_tmp_fx[16][L_FRAME48k]; + Word32 gains_fx[16]; + Word16 azimuth, elevation; + Word16 sba_num_chans; + + assert( ( LE_16(sba_order , 3) ) && "Only order up to 3 is supported!" ); + /* Init*/ + sba_num_chans = imult1616( add( sba_order, 1 ), add( sba_order, 1 ) ); + FOR( j = 0; j < sba_num_chans; j++ ) + { + set32_fx( buffer_tmp_fx[j], 0, output_frame ); + } + + /* HOA encoding*/ + idx_lfe = 0; + idx_in = 0; + move16(); + move16(); + FOR( i = 0; i < add( hIntSetup.nchan_out_woLFE, hIntSetup.num_lfe ); i++ ) + { + IF( GT_16( hIntSetup.num_lfe, 0 ) && EQ_16( i, hIntSetup.index_lfe[idx_lfe] ) ) + { + IF( GT_16( gain_lfe_fx, 0 ) ) + { + /* Add LFE to omni W with gain*/ + FOR( k = 0; k < output_frame; k++ ) + { + buffer_tmp_fx[0][k] = L_add( buffer_tmp_fx[0][k], L_shr( Mult_32_16( in_buffer_td_fx[i][k], gain_lfe_fx ), 2 ) ); /*Q+14-15-2==Q-3*/ + } + } + + IF( LT_16( idx_lfe, sub( hIntSetup.num_lfe, 1 ) ) ) + { + idx_lfe++; + } + } + ELSE + { + azimuth = (Word16) L_shr( hIntSetup.ls_azimuth_fx[idx_in], 22 ); + elevation = (Word16) L_shr( hIntSetup.ls_elevation_fx[idx_in], 22 ); + idx_in++; + ivas_dirac_dec_get_response_fixed( + azimuth, + elevation, + gains_fx, /*Q-29*/ + sba_order ); + /* get HOA response for direction (ACN/SN3D)*/ + + FOR( j = 0; j < sba_num_chans; j++ ) + { + FOR( k = 0; k < output_frame; k++ ) + { + buffer_tmp_fx[j][k] = L_add( buffer_tmp_fx[j][k], L_shr( Mult_32_32( in_buffer_td_fx[i][k], gains_fx[j] ), 1 ) ); /*Q+29-31-1==Q-3*/ + } + } + } + } + + FOR( j = 0; j < sba_num_chans; j++ ) + { + Copy32( buffer_tmp_fx[j], buffer_td_fx[j], output_frame ); + } + + return; +} +#endif // IVAS_FLOAT_FIXED void ivas_mc2sba( IVAS_OUTPUT_SETUP hIntSetup, /* i : Format of decoder output */ @@ -278,6 +357,79 @@ void ivas_mc2sba( * MC signals transformed into SBA in CLDFB domain * used for binaural rendering with head rotation *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_param_mc_mc2sba_cldfb_fx( + IVAS_OUTPUT_SETUP hTransSetup, /* i : transported MC Format */ + Word32 *hoa_encoder_fx, /* i : HOA3 encoder for the transported MC format */ + const Word16 slot_idx, /* i : current slot in the subframe */ + Word32 Cldfb_RealBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: Contains the MC signals (on input) and the HOA3 (on output) */ + Word32 Cldfb_ImagBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: Contains the MC signals (on input) and the HOA3 (on output) */ + const Word16 nBands, /* i : number of synth CLDFB bands */ + const Word16 gain_lfe_fx /* i : gain applied to LFE */ +) +{ + Word16 idx_ch, idx_band; + Word16 idx_lfe, idx_in, idx_out; + Word32 Cldfb_RealBuffer_tmp_fx[MAX_INTERN_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_tmp_fx[MAX_INTERN_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word32 *gains_fx; + Word16 sba_num_chans; + + /* Init*/ + sba_num_chans = MAX_INTERN_CHANNELS; + move16(); + FOR( idx_ch = 0; idx_ch < sba_num_chans; idx_ch++ ) + { + set32_fx( Cldfb_RealBuffer_tmp_fx[idx_ch], 0, CLDFB_NO_CHANNELS_MAX ); + set32_fx( Cldfb_ImagBuffer_tmp_fx[idx_ch], 0, CLDFB_NO_CHANNELS_MAX ); + } + + idx_lfe = 0; + idx_in = 0; + move16(); + move16(); + + FOR ( idx_ch = 0; idx_ch < add(hTransSetup.nchan_out_woLFE , hTransSetup.num_lfe); idx_ch++ ) + { + IF ( GT_16( hTransSetup.num_lfe , 0 ) && EQ_16( idx_ch , hTransSetup.index_lfe[idx_lfe] ) ) + { + IF( GT_32( gain_lfe_fx, 0 ) ) + { + /* Add LFE to Omni Channel i.e. W (Just first Band) */ + Cldfb_RealBuffer_tmp_fx[0][0] = L_add_sat( Cldfb_RealBuffer_tmp_fx[0][0], Mult_32_16( L_shl( Cldfb_RealBuffer_fx[idx_ch][slot_idx][0], 1 ), gain_lfe_fx ) ); + Cldfb_ImagBuffer_tmp_fx[0][0] = L_add_sat( Cldfb_ImagBuffer_tmp_fx[0][0], Mult_32_16( L_shl( Cldfb_ImagBuffer_fx[idx_ch][slot_idx][0], 1 ), gain_lfe_fx ) ); + } + + IF ( LT_16(idx_lfe , sub( hTransSetup.num_lfe , 1 )) ) + { + idx_lfe++; + } + } + ELSE + { + gains_fx = hoa_encoder_fx + imult1616( idx_in, sba_num_chans );/*Pointer addition*/ + FOR( idx_out = 0; idx_out < sba_num_chans; idx_out++ ) + { + FOR( idx_band = 0; idx_band < nBands; idx_band++ ) + { + Cldfb_RealBuffer_tmp_fx[idx_out][idx_band] = L_add( Cldfb_RealBuffer_tmp_fx[idx_out][idx_band], Mult_32_32( ( *gains_fx ), Cldfb_RealBuffer_fx[idx_ch][slot_idx][idx_band] ) ); + Cldfb_ImagBuffer_tmp_fx[idx_out][idx_band] = L_add( Cldfb_ImagBuffer_tmp_fx[idx_out][idx_band], Mult_32_32( ( *gains_fx ), Cldfb_ImagBuffer_fx[idx_ch][slot_idx][idx_band] ) ); + } + gains_fx++; + } + idx_in++; + } + } + FOR ( idx_ch = 0; idx_ch < sba_num_chans; idx_ch++ ) + { + Copy32( Cldfb_RealBuffer_tmp_fx[idx_ch], Cldfb_RealBuffer_fx[idx_ch][slot_idx], nBands ); + Copy32( Cldfb_ImagBuffer_tmp_fx[idx_ch], Cldfb_ImagBuffer_fx[idx_ch][slot_idx], nBands ); + } + + return; +} + +#endif // IVAS_FLOAT_FIXED void ivas_param_mc_mc2sba_cldfb( IVAS_OUTPUT_SETUP hTransSetup, /* i : transported MC Format */ @@ -355,6 +507,49 @@ void ivas_param_mc_mc2sba_cldfb( *-------------------------------------------------------------------*/ /*! r: SBA DirAC stereo flag */ +#ifdef IVAS_FLOAT_FIXED +Word16 ivas_sba_remapTCs_fx( + Word32 *sba_data_fx[], /* i/o: SBA signals */ + Decoder_Struct *st_ivas, /* i/o: decoder struct */ + const Word16 output_frame /* i : frame length */ +) +{ + Word16 nchan_remapped; + nchan_remapped = st_ivas->nchan_transport; + move16(); + IF ( EQ_16(nchan_remapped , 3) ) + { + nchan_remapped++; + IF (EQ_16(nchan_remapped , 4) ) + { + Copy32( sba_data_fx[2], sba_data_fx[3], output_frame ); + } + } + IF ( GT_16(st_ivas->nchan_transport , 3) ) + { + Word16 i = 0; + move16(); + Word32 temp_fx; + + /*convert WYXZ downmix to WYZX*/ + FOR ( i = 0; i < output_frame; i++ ) + { + temp_fx = sba_data_fx[2][i]; + move32(); + sba_data_fx[2][i] = sba_data_fx[3][i]; + move32(); + sba_data_fx[3][i] = temp_fx; + move32(); + IF ( EQ_16(st_ivas->nchan_transport , 3) ) + { + sba_data_fx[2][i] = 0; + move32(); + } + } + } + return ( nchan_remapped ); +} +#endif // IVAS_FLOAT_FIXED int16_t ivas_sba_remapTCs( float *sba_data[], /* i/o: SBA signals */ Decoder_Struct *st_ivas, /* i/o: decoder struct */ @@ -405,6 +600,59 @@ int16_t ivas_sba_remapTCs( * * ISM transformed into SBA in TD domain. *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_ism2sba_sf_fx( + Word32 *buffer_in_fx[], /* i : TC buffer *//*Q_buffer_in*/ + Word32 *buffer_out_fx[], /* o : TD signal buffers */ + ISM_RENDERER_HANDLE hIsmRendererData, /* i/o: renderer data */ + const Word16 num_objects, /* i : number of objects */ + const Word16 n_samples_to_render, /* i : output frame length per channel */ + const Word16 offset, /* i : offset for the interpolatr */ + const Word16 sba_order /* i : Ambisonic (SBA) order */ +) +{ + Word16 i, j, k; + Word32 buffer_tmp_fx[HOA3_CHANNELS][L_FRAME48k]; + Word16 *g2_fx, g1_fx; + Word32 *tc_fx, *out_fx, gain_fx, prev_gain_fx; + Word16 sba_num_chans; + + assert( ( sba_order <= 3 ) && "Only order up to 3 is supported!" ); + assert( hIsmRendererData != NULL && "hIsmRendererData not allocated!" ); + /* Init*/ + sba_num_chans = imult1616(add( sba_order , 1 ) , add( sba_order , 1 )); + FOR ( j = 0; j < sba_num_chans; j++ ) + { + set32_fx( buffer_tmp_fx[j], 0, n_samples_to_render ); + } + FOR ( i = 0; i < num_objects; i++ ) + { + FOR ( j = 0; j < sba_num_chans; j++ ) + { + g2_fx = hIsmRendererData->interpolator_fx + offset;/*Pointer addition*/ + tc_fx = buffer_in_fx[i] + offset;/*Pointer addition*/ + out_fx = buffer_tmp_fx[j]; + gain_fx = hIsmRendererData->gains_fx[i][j]; + move32(); + prev_gain_fx = hIsmRendererData->prev_gains_fx[i][j]; + move32(); + FOR( k = 0; k < n_samples_to_render; k++ ) + { + g1_fx = sub(32767 , *g2_fx); + *( out_fx ) += Mult_32_32( ( Mult_32_16( gain_fx, ( *( g2_fx ) ) ) + Mult_32_16( prev_gain_fx, g1_fx ) ), ( *( tc_fx ) ) );/*Q_buffer_in + 29 - 31*/ + g2_fx++; + tc_fx++; + out_fx++; + } + } + } + FOR ( j = 0; j < sba_num_chans; j++ ) + { + Copy32( buffer_tmp_fx[j], buffer_out_fx[j], n_samples_to_render ); + } + return; +} +#endif // IVAS_FLOAT_FIXED void ivas_ism2sba_sf( float *buffer_in[], /* i : TC buffer */ @@ -523,6 +771,63 @@ ivas_error ivas_sba_linear_renderer( * * Determine SBA mixing matrices *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_sba_mix_matrix_determiner_fx( + SPAR_DEC_HANDLE hSpar, /* i/o: SPAR decoder handle */ + Word32 *output_fx[], /* i/o: transport/output audio channels */ + const Word16 bfi, /* i : BFI flag */ + const Word16 nchan_remapped, /* i : num channels after remapping of TCs */ + const Word16 output_frame, /* i : output frame length */ + const Word16 num_md_sub_frames, /* i : number of subframes in mixing matrix*/ + Word16 *Q_mixer_mat ) +{ + Word16 i, ch; + Word16 num_bands_out, nchan_transport, nchan_out; + Word16 Q_p_output = 14; + Word32 temp_fx; + /* Convert numeric range */ + FOR( ch = 0; ch < nchan_remapped; ch++ ) + { + FOR( i = 0; i < output_frame; i++ ) + { + temp_fx = output_fx[ch][i]; + temp_fx = L_shr( temp_fx + L_shl( 1, Q_p_output - 1 ), Q_p_output ); + + IF( GT_32( temp_fx, MAX16B ) ) + { + temp_fx = MAX16B; + } + ELSE IF( LT_32( temp_fx, ( -1 * PCM16_TO_FLT_FAC_FX ) ) ) + { + temp_fx = ( -1 * PCM16_TO_FLT_FAC_FX ); + } + temp_fx = Mult_32_32( MAX_32 / PCM16_TO_FLT_FAC_FX, L_shl( temp_fx, Q_p_output ) ); + output_fx[ch][i] = temp_fx; + } + } + /* AGC */ + nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; + nchan_out = nchan_transport; + ivas_agc_dec_process_fx( hSpar->hAgcDec, ( output_fx ), ( output_fx ), nchan_transport, output_frame ); +#ifdef DUMPS_ENABLED + dbgwrite_txt( &output[0][0], output_frame, "fix_ivas_agc_dec_process_output.txt", NULL ); +#endif // DUMPS_ENABLED + + /* Convert numeric range back */ + FOR( ch = 0; ch < nchan_out; ch++ ) + { + FOR( i = 0; i < output_frame; i++ ) + { + output_fx[ch][i] = Mult_32_32( L_shl_sat( output_fx[ch][i], 4 ), L_shl_sat( PCM16_TO_FLT_FAC_FX, 16 ) ); /*Q-0*/ + } + } + + /* Mixing matrix determiner */ + num_bands_out = hSpar->hFbMixer->pFb->filterbank_num_bands; + ivas_spar_dec_gen_umx_mat_fx( hSpar->hMdDec, nchan_transport, num_bands_out, bfi, num_md_sub_frames, Q_mixer_mat ); + return; +} +#endif // IVAS_FLOAT_FIXED void ivas_sba_mix_matrix_determiner( SPAR_DEC_HANDLE hSpar, /* i/o: SPAR decoder handle */ @@ -608,7 +913,106 @@ void ivas_sba_mix_matrix_determiner( /* Mixing matrix determiner */ num_bands_out = hSpar->hFbMixer->pFb->filterbank_num_bands; +#ifdef IVAS_FLOAT_FIXED +#if 1 /*Float to fixed changes */ + Word16 j, b, i_ts, num_out_ch; + num_out_ch = hSpar->hMdDec->spar_md_cfg.num_umx_chs; + Word16 Q_C_re_fx = 31, Q_P_re_fx = 31, Q_mixer_mat = 31; + Word16 num_in_ch; + num_in_ch = hSpar->hMdDec->spar_md_cfg.num_umx_chs; + FOR ( i_ts = 0; i_ts < num_md_sub_frames; i_ts++ ) + { + FOR( i = 0; i < num_out_ch; i++ ) + { + FOR( j = 0; j < num_in_ch; j++ ) + { + FOR( b = 0; b < num_bands_out; b++ ) + { + Q_mixer_mat = s_min( Q_mixer_mat, Q_factor_L( hSpar->hMdDec->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] ) ); + } + } + } + } + FOR ( i_ts = 0; i_ts < num_md_sub_frames; i_ts++ ) + { + FOR ( i = 0; i < num_out_ch; i++ ) + { + FOR ( j = 0; j < nchan_transport; j++ ) + { + FOR ( b = 0; b < num_bands_out; b++ ) + { + Q_C_re_fx = s_min( Q_C_re_fx, Q_factor_L( hSpar->hMdDec->spar_coeffs.C_re[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] ) ); + } + } + } + } + FOR ( i_ts = 0; i_ts < num_md_sub_frames; i_ts++ ) + { + FOR ( i = 0; i < num_out_ch; i++ ) + { + FOR ( j = nchan_transport; j < num_out_ch; j++ ) + { + FOR ( b = 0; b < num_bands_out; b++ ) + { + Q_P_re_fx = s_min( Q_P_re_fx, Q_factor_L( hSpar->hMdDec->spar_coeffs.P_re[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] ) ); + } + } + } + } + Q_mixer_mat = s_min( Q_mixer_mat, s_min( Q_C_re_fx, Q_P_re_fx ) ); + FOR ( i_ts = 0; i_ts < num_md_sub_frames; i_ts++ ) + { + FOR( i = 0; i < num_out_ch; i++ ) + { + FOR( j = 0; j < num_in_ch; j++ ) + { + FOR( b = 0; b < num_bands_out; b++ ) + { + hSpar->hMdDec->mixer_mat_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = floatToFixed( hSpar->hMdDec->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS], Q_mixer_mat ); + } + } + } + FOR ( i = 0; i < num_out_ch; i++ ) + { + FOR( j = 0; j < nchan_transport; j++ ) + { + FOR( b = 0; b < num_bands_out; b++ ) + { + hSpar->hMdDec->spar_coeffs.C_re_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = floatToFixed( hSpar->hMdDec->spar_coeffs.C_re[i][j][b + i_ts * IVAS_MAX_NUM_BANDS], Q_mixer_mat ); + } + } + } + FOR( i = 0; i < num_out_ch; i++ ) + { + FOR( j = nchan_transport; j < num_out_ch; j++ ) + { + FOR( b = 0; b < num_bands_out; b++ ) + { + hSpar->hMdDec->spar_coeffs.P_re_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = floatToFixed( hSpar->hMdDec->spar_coeffs.P_re[i][j][b + i_ts * IVAS_MAX_NUM_BANDS], Q_mixer_mat ); + } + } + } + } +#endif + ivas_spar_dec_gen_umx_mat_fx( hSpar->hMdDec, nchan_transport, num_bands_out, bfi, num_md_sub_frames ,&Q_mixer_mat); +#if 1 /*Fixed to float changes */ + FOR( i_ts = 0; i_ts < num_md_sub_frames; i_ts++ ) + { + FOR( i = 0; i < num_out_ch; i++ ) + { + FOR( j = 0; j < num_in_ch; j++ ) + { + FOR( b = 0; b < num_bands_out; b++ ) + { + hSpar->hMdDec->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = fixedToFloat( hSpar->hMdDec->mixer_mat_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS], Q_mixer_mat ); + } + } + } + } +#endif +#else ivas_spar_dec_gen_umx_mat( hSpar->hMdDec, nchan_transport, num_bands_out, bfi, num_md_sub_frames ); +#endif // IVAS_FLOAT_FIXED return; } diff --git a/lib_dec/ivas_spar_md_dec.c b/lib_dec/ivas_spar_md_dec.c index 94bf2d8f424b45a5eac62a5b626d3cf3b028b050..ee8d7d19ac4a168991ee85659cf2e53b7efa38a3 100644 --- a/lib_dec/ivas_spar_md_dec.c +++ b/lib_dec/ivas_spar_md_dec.c @@ -39,6 +39,9 @@ #include #include "wmc_auto.h" #include "ivas_stat_dec.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx2.h" +#endif // IVAS_FLOAT_FIXED /*------------------------------------------------------------------------------------------* @@ -71,6 +74,10 @@ static void ivas_mat_col_rearrange( float in_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_ static void ivas_spar_dec_compute_ramp_down_post_matrix( ivas_spar_md_dec_state_t *hMdDec, const int16_t num_bands, const int16_t bfi, const int16_t num_md_sub_frames ); +#ifdef IVAS_FLOAT_FIXED +static void ivas_spar_dec_compute_ramp_down_post_matrix_fx(ivas_spar_md_dec_state_t *hMdDec, const Word16 num_bands, const Word16 bfi, const Word16 num_md_sub_frames,Word16 *Q_mixer_mat); +#endif // IVAS_FLOAT_FIXED + static void ivas_spar_md_fill_invalid_bands( ivas_spar_dec_matrices_t *pSpar_coeffs, ivas_spar_dec_matrices_t *pSpar_coeffs_prev, const int16_t *valid_bands, int16_t *base_band_age, const int16_t num_bands, const int16_t numch_out, const int16_t num_md_sub_frames ); static void ivas_spar_md_fill_invalid_bandcoeffs( ivas_band_coeffs_t *pBand_coeffs, ivas_band_coeffs_t *pBand_coeffs_prev, const int16_t *valid_bands, int16_t *base_band_age, int16_t *first_valid_frame, const int16_t num_bands ); @@ -145,6 +152,45 @@ ivas_error ivas_spar_md_dec_matrix_open( } } #endif +#ifdef IVAS_FLOAT_FIXED + if ( ( hMdDec->spar_coeffs.C_re_fx = (Word32 ***) malloc( num_channels * sizeof(Word32 ** ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); + } + for ( i = 0; i < num_channels; i++ ) + { + if ( ( hMdDec->spar_coeffs.C_re_fx[i] = (Word32 **) malloc( num_channels * sizeof(Word32 * ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); + } + for ( j = 0; j < num_channels; j++ ) + { + if ( ( hMdDec->spar_coeffs.C_re_fx[i][j] = (Word32 *) malloc( num_md_sub_frames * IVAS_MAX_NUM_BANDS * sizeof(Word32) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); + } + } + } + + if ( ( hMdDec->spar_coeffs.P_re_fx = (Word32 ***) malloc( num_channels * sizeof(Word32 ** ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); + } + for ( i = 0; i < num_channels; i++ ) + { + if ( ( hMdDec->spar_coeffs.P_re_fx[i] = (Word32 **) malloc( num_channels * sizeof(Word32 * ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); + } + for ( j = 0; j < num_channels; j++ ) + { + if ( ( hMdDec->spar_coeffs.P_re_fx[i][j] = (Word32 *) malloc( num_md_sub_frames * IVAS_MAX_NUM_BANDS * sizeof(Word32) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); + } + } + } +#endif // IVAS_FLOAT_FIXED if ( ( hMdDec->spar_coeffs.C_re = (float ***) malloc( num_channels * sizeof( float ** ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); @@ -449,6 +495,32 @@ void ivas_spar_md_dec_matrix_close( free( hMdDecoder->mixer_mat_fx ); } #endif +#ifdef IVAS_FLOAT_FIXED + if ( hMdDecoder->spar_coeffs.C_re_fx != NULL ) + { + for ( i = 0; i < num_channels; i++ ) + { + for ( j = 0; j < num_channels; j++ ) + { + free( hMdDecoder->spar_coeffs.C_re_fx[i][j] ); + } + free( hMdDecoder->spar_coeffs.C_re_fx[i] ); + } + free( hMdDecoder->spar_coeffs.C_re_fx ); + } + if ( hMdDecoder->spar_coeffs.P_re_fx != NULL ) + { + for ( i = 0; i < num_channels; i++ ) + { + for ( j = 0; j < num_channels; j++ ) + { + free( hMdDecoder->spar_coeffs.P_re_fx[i][j] ); + } + free( hMdDecoder->spar_coeffs.P_re_fx[i] ); + } + free( hMdDecoder->spar_coeffs.P_re_fx ); + } +#endif // IVAS_FLOAT_FIXED if ( hMdDecoder->spar_coeffs.C_re != NULL ) { @@ -1422,6 +1494,64 @@ static void ivas_mat_col_rearrange( * * generates upmix matrix *-----------------------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_spar_dec_gen_umx_mat_fx( + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ + const Word16 nchan_transport, /* i : number of transport channels */ + const Word16 num_bands_out, /* i : number of output bands */ + const Word16 bfi, /* i : bad frame indicator */ + const Word16 num_md_sub_frames, + Word16 *Q_mixer_mat ) +{ + Word16 i, j, b, i_ts, num_out_ch; + num_out_ch = hMdDec->spar_md_cfg.num_umx_chs; + move16(); + FOR ( i_ts = 0; i_ts < num_md_sub_frames; i_ts++ ) + { + IF ( EQ_16(hMdDec->td_decorr_flag , 1) ) + { + FOR ( i = 0; i < num_out_ch; i++ ) + { + FOR ( j = 0; j < nchan_transport; j++ ) + { + FOR ( b = 0; b < num_bands_out; b++ ) + { + hMdDec->mixer_mat_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = hMdDec->spar_coeffs.C_re_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS]; + move32(); + } + } + } + FOR ( i = 0; i < num_out_ch; i++ ) + { + FOR ( j = nchan_transport; j < num_out_ch; j++ ) + { + FOR ( b = 0; b < num_bands_out; b++ ) + { + hMdDec->mixer_mat_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = hMdDec->spar_coeffs.P_re_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS]; + move32(); + } + } + } + } + ELSE + { + FOR ( i = 0; i < num_out_ch; i++ ) + { + FOR ( j = 0; j < nchan_transport; j++ ) + { + FOR ( b = 0; b < num_bands_out; b++ ) + { + hMdDec->mixer_mat_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = hMdDec->spar_coeffs.C_re_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS]; + move32(); + } + } + } + } + } + ivas_spar_dec_compute_ramp_down_post_matrix_fx( hMdDec, num_bands_out, bfi, num_md_sub_frames, Q_mixer_mat ); + return; +} +#endif // IVAS_FLOAT_FIXED void ivas_spar_dec_gen_umx_mat( ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ @@ -2261,10 +2391,80 @@ static void ivas_spar_md_fill_invalid_bandcoeffs( /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_dec_compute_ramp_down_post_matrix() + * Function ivas_spar_dec_compute_ramp_down_post_matrix_fx() * * *-----------------------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void ivas_spar_dec_compute_ramp_down_post_matrix_fx( + ivas_spar_md_dec_state_t *hMdDec, + const Word16 num_bands_out, + const Word16 bfi, + const Word16 num_md_sub_frames, + Word16 *Q_mixer_mat ) +{ + Word16 num_in_ch, num_out_ch, i, j, b; + num_in_ch = hMdDec->spar_md_cfg.num_umx_chs; + num_out_ch = hMdDec->spar_md_cfg.num_umx_chs; + move16(); + move16(); + IF ( EQ_16(bfi , 0 )) + { + hMdDec->spar_plc_num_lost_frames = 0; + move16(); + } + ELSE + { + IF (EQ_16(hMdDec->td_decorr_flag , 0) ) + { + assert( 0 ); + } + + hMdDec->spar_plc_num_lost_frames =add(hMdDec->spar_plc_num_lost_frames, 1); + hMdDec->spar_plc_num_lost_frames = s_min( hMdDec->spar_plc_num_lost_frames, 100 ); /*hMdDec->spar_plc_num_lost_frames is always <=100*/ + + IF ( GT_16(hMdDec->spar_plc_num_lost_frames , ivas_spar_dec_plc_num_frames_keep) ) /*if control enters then ivas_spar_dec_plc_num_frames_keep<100 */ + { + Word16 num_fade_frames; + Word16 gain_dB; + Word32 gain_fx; + Word32 post_matrix_fx[IVAS_SPAR_MAX_CH]; + Word16 Q_post_matrix; + Word16 Q_gain; + Word16 norm_nff; /*norm of num_fade_frames*/ + num_fade_frames = s_max( sub(hMdDec->spar_plc_num_lost_frames , ivas_spar_dec_plc_num_frames_keep), 0 ); + norm_nff = norm_s( num_fade_frames ); + gain_dB = -imult1616(s_min( num_fade_frames, ivas_spar_dec_plc_max_num_frames_ramp_down ) , ivas_spar_dec_plc_per_frame_ramp_down_gain_dB); /*abs(gain_dB)<99*/ /*Q(gain_dB)=7Q24*/ + Word16 exp_gain = 0; /*stores exponent for gain_fx*/ + gain_fx = BASOP_util_Pow2( Mult_32_16( imult3216(13421773/*=2^28/20*/, gain_dB ), 27213/*=log2(10)*2^13*/ ), 5, &exp_gain ); + Q_gain = 31 - exp_gain; + FOR ( i = 0; i < IVAS_SPAR_MAX_CH; i++ ) + { + post_matrix_fx[i] = add( shl( 1, norm_nff ), mult( s_min( mult( shl( num_fade_frames, norm_nff ), div_s( 1, ivas_spar_dec_plc_num_frames_fade_out ) ), shl( 1, norm_nff ) ), shl( sub( ivas_spar_dec_plc_spatial_target[i], 1 ), 15 ) ) ); /*Q=norm_nff*/ + post_matrix_fx[i] = Mult_32_16( gain_fx, (Word16)post_matrix_fx[i] ); /*Q_gain+norm_nff-15*/ + } + Q_post_matrix = Q_gain + norm_nff - 15; + /* apply the post matrix */ + FOR ( Word16 i_ts = 0; i_ts < num_md_sub_frames; i_ts++ ) + { + FOR ( i = 0; i < num_out_ch; i++ ) + { + FOR ( j = 0; j < num_in_ch; j++ ) + { + FOR ( b = 0; b < num_bands_out; b++ ) + { + hMdDec->mixer_mat_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = Mult_32_32( hMdDec->mixer_mat_fx[i][j][b + i_ts * IVAS_MAX_NUM_BANDS], post_matrix_fx[i] ); + } + } + } + } + *Q_mixer_mat = Q_post_matrix + *Q_mixer_mat - 31; + } + } + + return; +} +#endif // IVAS_FLOAT_FIXED static void ivas_spar_dec_compute_ramp_down_post_matrix( ivas_spar_md_dec_state_t *hMdDec, diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index 5053c03efc8838f7474520cbb636605a05c772da..f344a46d8faf385d475973d3be0ad6a4a9b65f80 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -751,6 +751,9 @@ typedef struct ivas_param_mc_dec_data_structure /*sub-modules*/ HANDLE_DIRAC_DECORR_PARAMS h_freq_domain_decorr_ap_params; HANDLE_DIRAC_DECORR_STATE h_freq_domain_decorr_ap_state; +#ifdef IVAS_FLOAT_FIXED + Word32 *hoa_encoder_fx; +#endif // IVAS_FLOAT_FIXED float *hoa_encoder; @@ -791,6 +794,10 @@ typedef struct ivas_spar_dec_matrices_t { float ***C_re; float ***P_re; +#ifdef IVAS_FLOAT_FIXED + Word32 ***C_re_fx; + Word32 ***P_re_fx; +#endif // DEBUG } ivas_spar_dec_matrices_t; diff --git a/lib_rend/ivas_mcmasa_ana.c b/lib_rend/ivas_mcmasa_ana.c index 4565242952f45851a9d5d375d691f7259814463e..f5107381b3f8243dd64396bdf403a6c74b699d24 100644 --- a/lib_rend/ivas_mcmasa_ana.c +++ b/lib_rend/ivas_mcmasa_ana.c @@ -41,9 +41,7 @@ #include "ivas_stat_rend.h" #include "ivas_rom_com.h" #include "wmc_auto.h" -#ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" -#endif /*------------------------------------------------------------------------- * Local constants