From 03cc507f5f8f3911aabb2bcd088d1167d478a4de Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Tue, 23 Jan 2024 14:25:52 +0530 Subject: [PATCH] Functions in ivas_masa_dec converted to fixed point. [x] Functions in ivas_masa_dec converted to fixed point. [x] Some changes in calling and sub-functions included. --- lib_com/cnst.h | 1 + lib_com/ivas_cnst.h | 7 + lib_com/ivas_masa_com.c | 267 ++++++++++++++ lib_com/ivas_prot_fx.h | 47 +++ lib_com/ivas_rom_com_fx.c | 25 +- lib_com/ivas_rom_com_fx.h | 2 + lib_dec/ivas_init_dec.c | 17 + lib_dec/ivas_jbm_dec.c | 418 +++++++++++++++++++++- lib_dec/ivas_masa_dec.c | 727 ++++++++++++++++++++++++++++++++++++++ lib_dec/ivas_mcmasa_dec.c | 9 + lib_dec/ivas_mct_dec.c | 13 + lib_dec/ivas_stat_dec.h | 4 + lib_rend/ivas_stat_rend.h | 32 ++ 13 files changed, 1567 insertions(+), 2 deletions(-) diff --git a/lib_com/cnst.h b/lib_com/cnst.h index 84ea9e34b..a54977870 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -718,6 +718,7 @@ enum #define CLDFB_NO_COL_MAX_SWITCH_BFI 10 /* CLDFB resampling - max number of CLDFB col. for switching, BFI */ #define CLDFB_OVRLP_MIN_SLOTS 3 /* CLDFB resampling - minimize processing to minimum required for transition frame ACELP->TCX/HQ */ #define INV_CLDFB_BANDWIDTH ( 1.f / 800.f ) +#define INV_CLDFB_BANDWIDTH_Q31 ( 2684355l ) #define L_FILT_2OVER3 12 #define L_FILT_2OVER3_LP 3 diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index f16b68324..40c781089 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1291,6 +1291,13 @@ typedef enum #define MCMASA_LFE_THETA 1.3f #define MCMASA_LFE_SYNTH_ALPHA 0.95f /* Smoothing coefficient for LFE synthesis */ +#define MCMASA_LFE_ALPHA_Q15 (21954) +#define MCMASA_LFE_BETA_Q15 (2949) +#define MCMASA_LFE_BETA_Q14 (1474) +#define MCMASA_LFE_THETA_Q14 (21299) +#define MCMASA_LFE_QLOW_Q12 (-26624) +#define MCMASA_LFE_DELTA_Q11 (2048) + #define NUM_ELEVATED_SPEAKERS 4 #define MCMASA_MIN_SPEAKERS_SEPARATE_CENTER 4 diff --git a/lib_com/ivas_masa_com.c b/lib_com/ivas_masa_com.c index 4c519ae45..9da241603 100644 --- a/lib_com/ivas_masa_com.c +++ b/lib_com/ivas_masa_com.c @@ -40,6 +40,9 @@ #include "ivas_rom_com.h" #include "ivas_stat_dec.h" #include "wmc_auto.h" +#include "ivas_rom_com_fx.h" +#include "prot_fx2.h" + /*--------------------------------------------------------------- * Local constants @@ -155,6 +158,123 @@ void ivas_masa_set_elements( return; } +void ivas_masa_set_elements_fx( + const Word32 ivas_total_brate, /* i : IVAS total bitrate */ + const Word16 mc_mode, /* i : MC format mode */ + const Word16 nchan_transport, /* i : number of MASA input/transport channels */ + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ + Word16 *element_mode, /* o : element mode */ + Word16 *nSCE, /* o : number of SCEs */ + Word16 *nCPE, /* o : number of CPEs */ + const Word16 ivas_format, /* i : IVAS format */ + const ISM_MODE ism_mode, /* i : ISM mode */ + const Word32 ism_total_brate /* i : initial ISM total bitrate */ +) +{ + Word16 tmp, tmp_e; + + IF ( EQ_16( nchan_transport, 2 ) ) + { + test(); + test(); + IF ( GE_32( ivas_total_brate, MCMASA_SEPARATE_BRATE ) && EQ_16( mc_mode, MC_MODE_MCMASA ) ) + { + *nCPE = 1; + move16(); + *nSCE = 1; + move16(); + + *element_mode = IVAS_SCE; /* This is needed for the initialization phase to initialize codec mode to SCE, since it is written first to the file*/ + move16(); + } + ELSE IF ( EQ_16( ivas_format, MASA_ISM_FORMAT ) && NE_16( ism_mode, ISM_MODE_NONE ) ) + { + *nCPE = 1; + move16(); + + IF ( EQ_16( *element_mode, -1 ) ) + { + *element_mode = IVAS_CPE_DFT; /* To have it initialized in case it was not already. */ + move16(); + } + IF ( GT_32( ivas_total_brate, MIN_BRATE_MDCT_STEREO ) ) + { + *element_mode = IVAS_CPE_MDCT; + move16(); + test(); + test(); + test(); + IF ( ( EQ_16( ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) && LT_32( L_sub( ivas_total_brate, ism_total_brate ), MIN_BRATE_MDCT_STEREO ) ) + { + *element_mode = IVAS_CPE_DFT; + move16(); + } + } + } + ELSE + { + *nCPE = 1; + move16(); + *nSCE = 0; + move16(); + + IF ( GT_32( ivas_total_brate, MIN_BRATE_MDCT_STEREO ) ) + { + *element_mode = IVAS_CPE_MDCT; + move16(); + } + } + tmp = BASOP_Util_Divide3216_Scale(ivas_total_brate, FRAMES_PER_SEC, &tmp_e); + hQMetaData->bits_frame_nominal = shr(tmp, negate(add(1, tmp_e))); // Q0 + IF ( EQ_16(ivas_format, MASA_ISM_FORMAT) && ( EQ_16(ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ) || EQ_16(ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ) || EQ_16(ism_mode,ISM_MASA_MODE_DISC) ) ) + { + tmp = BASOP_Util_Divide3216_Scale(ism_total_brate, FRAMES_PER_SEC, &tmp_e); + tmp = shr(tmp, negate(add(1, tmp_e))); // Q0 + hQMetaData->bits_frame_nominal = sub(hQMetaData->bits_frame_nominal, tmp); + } + } + ELSE IF ( GE_16( nchan_transport, 1 ) ) + { + *nCPE = 0; + move16(); + *nSCE = 1; + move16(); + + IF ( EQ_32( ivas_total_brate, IVAS_13k2 ) ) + { + hQMetaData->bits_frame_nominal = ACELP_9k60 / FRAMES_PER_SEC; + move16(); + } + ELSE IF ( LE_32( ivas_total_brate, IVAS_16k4 ) ) + { + hQMetaData->bits_frame_nominal = ACELP_13k20 / FRAMES_PER_SEC; + move16(); + } + ELSE IF ( LE_32( ivas_total_brate, IVAS_24k4 ) ) + { + hQMetaData->bits_frame_nominal = ACELP_16k40 / FRAMES_PER_SEC; + move16(); + } + ELSE IF ( LE_32( ivas_total_brate, IVAS_32k ) ) + { + hQMetaData->bits_frame_nominal = ACELP_24k40 / FRAMES_PER_SEC; + move16(); + } + ELSE + { + hQMetaData->bits_frame_nominal = (Word16) ( ivas_total_brate / FRAMES_PER_SEC ); + move16(); + } + *element_mode = IVAS_SCE; + move16(); + } + ELSE + { + assert( !"MASA number of transport channels must be 1, or 2" ); + } + + return; +} /*--------------------------------------------------------------- * generate_gridEq() @@ -196,6 +316,30 @@ void generate_gridEq( return; } +#ifdef IVAS_FLOAT_FIXED +void generate_gridEq_fx( + SPHERICAL_GRID_DATA *data /* o : data structure for grid */ +) +{ + /***************************************************************/ + /* NOTE: created LUT from float code. The lookup table depends */ + /* on the following macros: */ + /* - MASA_NO_CIRCLES */ + /* - MASA_NO_POINTS_EQUATOR */ + /* - MASA_ANGLE_AT_EQUATOR */ + /* - MASA_NTOT2_FAC */ + /* - MASA_ASIN_OFFSET */ + /***************************************************************/ + + Copy( gridEq_Table, data->no_phi, NO_THETA16_MAX ); + + data->no_theta = NO_THETA16_MAX; + move16(); + + return; +} +#endif + /*--------------------------------------------------------------- * ivas_masa_set_coding_config() @@ -462,6 +606,129 @@ void masa_sample_rate_band_correction( return; } +#ifdef IVAS_FLOAT_FIXED +void masa_sample_rate_band_correction_fx( + MASA_CODEC_CONFIG *config, /* i/o: MASA codec config */ + Word16 *band_mapping, /* i/o: Band mapping used and modified */ + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: QMetadata structure for modification */ + const UWord8 maxBand, /* i : max band */ + UWord8 is_encoder, /* i : signals if called at encoder */ + MASA_DECODER_EXT_OUT_META_HANDLE hExtOutMeta /* i/o: MASA decoder metadata ext out buffer */ +) +{ + UWord8 band, sf; + Word16 highBand; + UWord8 numBands48k; + + numBands48k = config->numCodingBands; + + FOR ( band = 1; band < config->numCodingBands + 1; band++ ) + { + highBand = band_mapping[band]; + + IF ( GE_16( highBand, (Word16)maxBand ) ) + { + config->numCodingBands = band; + hQMetaData->numCodingBands = band; + + IF ( is_encoder ) + { + test(); + IF ( GT_16( hQMetaData->q_direction->cfg.nbands, (Word16)band ) ) + { + hQMetaData->q_direction->cfg.nbands = band; + } + IF ( EQ_16( (Word16) hQMetaData->no_directions, 2 ) && GT_16( hQMetaData->q_direction[1].cfg.nbands, (Word16)band ) ) + { + hQMetaData->q_direction[1].cfg.nbands = band; + } + } + + band_mapping[band] = maxBand; + + BREAK; + } + } + + /* Set rest of the bands to zero in qmetadata. */ + FOR ( ; band < numBands48k; band++ ) + { + FOR ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + { +#if 1 /* TODO: remove float code */ + hQMetaData->q_direction[0].band_data[band].azimuth[sf] = 0.0f; + hQMetaData->q_direction[0].band_data[band].elevation[sf] = 0.0f; + hQMetaData->q_direction[0].band_data[band].energy_ratio[sf] = 0.0f; +#endif + hQMetaData->q_direction[0].band_data[band].azimuth_fx[sf] = 0; + move32(); + hQMetaData->q_direction[0].band_data[band].elevation_fx[sf] = 0; + move32(); + hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[sf] = 0; + move32(); + + IF ( hQMetaData->coherence_flag && hQMetaData->q_direction[0].coherence_band_data != NULL ) + { + hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[sf] = 0u; + } + + IF ( EQ_16( (Word16) hQMetaData->no_directions, 2 ) ) + { +#if 1 /* TODO: remove float code */ + hQMetaData->q_direction[1].band_data[band].azimuth[sf] = 0.0f; + hQMetaData->q_direction[1].band_data[band].elevation[sf] = 0.0f; + hQMetaData->q_direction[1].band_data[band].energy_ratio[sf] = 0.0f; +#endif + hQMetaData->q_direction[1].band_data[band].azimuth_fx[sf] = 0; + move32(); + hQMetaData->q_direction[1].band_data[band].elevation_fx[sf] = 0; + move32(); + hQMetaData->q_direction[1].band_data[band].energy_ratio_fx[sf] = 0; + move32(); + + IF ( hQMetaData->coherence_flag && hQMetaData->q_direction[1].coherence_band_data != NULL ) + { + hQMetaData->q_direction[1].coherence_band_data[band].spread_coherence[sf] = 0u; + } + } + + IF ( hQMetaData->coherence_flag && hQMetaData->surcoh_band_data != NULL ) + { + hQMetaData->surcoh_band_data[band].surround_coherence[sf] = 0u; + } + } + + IF ( EQ_16( (Word16) hQMetaData->no_directions, 2 ) ) + { + hQMetaData->twoDirBands[band] = 0; + } + } + + IF ( hExtOutMeta != NULL ) + { + /* in decoder, zero the EXT out MASA meta buffer */ + FOR ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + { + FOR ( band = hQMetaData->numCodingBands; band < MASA_FREQUENCY_BANDS; band++ ) + { + hExtOutMeta->directionIndex[0][sf][band] = SPH_IDX_FRONT; + hExtOutMeta->directToTotalRatio[0][sf][band] = 0u; + hExtOutMeta->spreadCoherence[0][sf][band] = 0u; + + hExtOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT; + hExtOutMeta->directToTotalRatio[1][sf][band] = 0u; + hExtOutMeta->spreadCoherence[1][sf][band] = 0u; + + hExtOutMeta->surroundCoherence[sf][band] = 0u; + hExtOutMeta->diffuseToTotalRatio[sf][band] = UINT8_MAX; + } + } + } + + return; +} +#endif + /*------------------------------------------------------------------------- * index_theta_phi_16() diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 43abf9c1c..179700c3e 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -45,6 +45,53 @@ #include "ivas_stat_com.h" #include "ivas_error_utils.h" +ivas_error ivas_masa_dec_open_fx( + Decoder_Struct *st_ivas /* i/o: IVAS decoder handle */ +); + +void ivas_masa_dec_close_fx( + MASA_DECODER_HANDLE *hMasa /* i/o: MASA metadata structure */ +); + +void generate_gridEq_fx( + SPHERICAL_GRID_DATA *data /* o : data structure for grid */ +); + +void masa_sample_rate_band_correction_fx( + MASA_CODEC_CONFIG *config, /* i/o: MASA codec config */ + Word16 *band_mapping, /* i/o: Band mapping used and modified */ + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: QMetadata structure for modification */ + const UWord8 maxBand, /* i : max band */ + UWord8 is_encoder, /* i : signals if called at encoder */ + MASA_DECODER_EXT_OUT_META_HANDLE hExtOutMeta /* i/o: MASA decoder metadata ext out buffer */ +); + +void ivas_masa_set_elements_fx( + const Word32 ivas_total_brate, /* i : codec total bitrate */ + const Word16 mc_mode, /* i : MC format mode */ + const Word16 nchan_transport, /* i : number of MASA input/transport channels */ + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ + Word16 *element_mode, /* o : element mode */ + Word16 *nSCE, /* o : number of SCEs */ + Word16 *nCPE, /* o : number of CPEs */ + const Word16 ivas_format, /* i : IVAS format */ + const ISM_MODE ism_mode, /* i : ISM mode */ + const Word32 ism_total_brate /* i : initial ISM total bitrate */ +); + +Word16 ivas_jbm_dec_get_num_tc_channels_fx( + Decoder_Struct *st_ivas /* i : IVAS decoder handle */ +); + +ivas_error ivas_jbm_dec_tc_buffer_open_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const TC_BUFFER_MODE tc_buffer_mode, /* i : buffer mode */ + const Word16 nchan_transport_jbm, /* i : number of real transport channels */ + const Word16 nchan_transport_internal, /* i : number of totally buffered channels */ + const Word16 nchan_full, /* i : number of channels to fully store */ + const Word16 n_samples_granularity /* i : granularity of the renderer/buffer */ +); + void ivas_dct_windowing_fx( const Word16 fade_len, const Word16 full_len, diff --git a/lib_com/ivas_rom_com_fx.c b/lib_com/ivas_rom_com_fx.c index 1b2be9afd..8bbe1709a 100644 --- a/lib_com/ivas_rom_com_fx.c +++ b/lib_com/ivas_rom_com_fx.c @@ -288,8 +288,31 @@ const Word32 ism_azimuth_borders_fx[4] = -754974720, -587202560, 566231040, 754974720 }; -const Word32 ism_elevation_borders_fx[4] = +const Word32 ism_elevation_borders_fx[4] = { -377487360, -293601280, 272639760, 377487360 }; + +const Word16 gridEq_Table[NO_THETA16_MAX] = { + 430, 423, 422, 422, 422, 422, 421, 421, 420, 420, 419, 418, 417, 417, 416, + 414, 414, 412, 412, 409, 409, 407, 406, 404, 402, 401, 399, 397, 395, 394, + 391, 389, 387, 385, 383, 380, 378, 375, 373, 370, 368, 365, 362, 359, 356, + 354, 350, 347, 344, 341, 338, 334, 331, 328, 324, 321, 317, 313, 310, 306, + 302, 299, 294, 291, 287, 282, 279, 274, 270, 266, 262, 258, 253, 249, 244, + 240, 235, 231, 226, 222, 217, 212, 208, 202, 198, 194, 188, 183, 179, 173, + 169, 163, 159, 153, 148, 144, 138, 133, 127, 123, 117, 112, 107, 102, 96, + 91, 85, 81, 75, 69, 64, 59, 53, 48, 43, 37, 32, 26, 21, 15, 10, 1 +}; + +const Word16 McMASA_LFEGain_vectors_fx_q13[64] = { + 3112, 2703, 1556, 1638, -1310, -1802, -2867, -2785, + 4096, 4096, 4096, 4096, -6553, -3276, 8355, 819, + -4096, -4096, -4096, -4096, -4587, -983, -6389, 11141, + -8355, 9666, -4669, 2703, 5898, -9256, 7946, -5079, + -7454, 7618, 8192, -9011, 14172, -1884, -6389, -6881, + 7782, -13107, -2785, 7618, 7127, 3850, -15564, 4259, + 5488, 11632, -7946, -10158, 6799, 4751, 4997, -16711, + -6553, -12943, 6717, 11632, -17530, 2129, 6881, 8355 +}; + /* clang-format on */ diff --git a/lib_com/ivas_rom_com_fx.h b/lib_com/ivas_rom_com_fx.h index 797c39020..3d0fdff06 100644 --- a/lib_com/ivas_rom_com_fx.h +++ b/lib_com/ivas_rom_com_fx.h @@ -51,6 +51,8 @@ extern const Word16 ivas_cos_twiddle_80_fx[ IVAS_80_PT_LEN >> 1 ]; extern const Word16 dft_trigo_12k8_fx[STEREO_DFT_N_12k8_ENC / 4 + 1]; extern const Word16 dft_trigo_32k_fx[STEREO_DFT_N_32k_ENC / 4 + 1]; extern const Word16 dft_trigo_48k_fx[STEREO_DFT_N_MAX_ENC / 4 + 1]; +extern const Word16 gridEq_Table[NO_THETA16_MAX]; +extern const Word16 McMASA_LFEGain_vectors_fx_q13[64]; extern const Word16 ivas_divde_255[256]; diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 1094935ef..74702e66f 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -41,6 +41,7 @@ #include #include #include "wmc_auto.h" +#include "ivas_prot_fx.h" /*-------------------------------------------------------------------* @@ -1155,7 +1156,11 @@ ivas_error ivas_init_decoder( return error; } +#ifdef IVAS_FLOAT_FIXED + IF ( ( error = ivas_masa_dec_open_fx( st_ivas ) ) != IVAS_ERR_OK ) +#else IF ( ( error = ivas_masa_dec_open( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1375,7 +1380,11 @@ ivas_error ivas_init_decoder( } } +#ifdef IVAS_FLOAT_FIXED + IF ( ( error = ivas_masa_dec_open_fx( st_ivas ) ) != IVAS_ERR_OK ) +#else IF ( ( error = ivas_masa_dec_open( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1540,7 +1549,11 @@ ivas_error ivas_init_decoder( return error; } +#ifdef IVAS_FLOAT_FIXED + IF ( ( error = ivas_masa_dec_open_fx( st_ivas ) ) != IVAS_ERR_OK ) +#else IF ( ( error = ivas_masa_dec_open( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -2286,7 +2299,11 @@ void ivas_destroy_dec( } /* MASA decoder structure */ +#ifdef IVAS_FLOAT_FIXED + ivas_masa_dec_close_fx( &( st_ivas->hMasa ) ); +#else ivas_masa_dec_close( &( st_ivas->hMasa ) ); +#endif /* Qmetadata handle */ ivas_qmetadata_close( &st_ivas->hQMetaData ); diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index e04ba01ff..3c7387b42 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -47,7 +47,6 @@ #endif // DUMPS_ENABLED #include "prot_fx1.h" #include "prot_fx2.h" -#include "ivas_prot_fx.h" /*-----------------------------------------------------------------------* * Local function prototypes @@ -2205,6 +2204,169 @@ int16_t ivas_jbm_dec_get_num_tc_channels( } +#ifdef IVAS_FLOAT_FIXED +Word16 ivas_jbm_dec_get_num_tc_channels_fx( + Decoder_Struct *st_ivas /* i : IVAS decoder handle */ +) +{ + Word16 num_tc; + Word32 ivas_total_brate; + AUDIO_CONFIG output_config; + + + IF ( EQ_16( st_ivas->renderer_type, RENDERER_DISABLE ) ) + { + num_tc = st_ivas->hDecoderConfig->nchan_out; + move16(); + } + ELSE + { + num_tc = st_ivas->nchan_transport; + move16(); + } + output_config = st_ivas->hDecoderConfig->output_config; + move16(); + + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + move32(); + + test(); test(); test(); + IF ( EQ_16( st_ivas->ivas_format, MONO_FORMAT ) ) + { + num_tc = st_ivas->hDecoderConfig->nchan_out; + move16(); + } + ELSE IF ( EQ_16( st_ivas->ivas_format, STEREO_FORMAT ) && EQ_16( st_ivas->hDecoderConfig->nchan_out, 1 ) ) + { + num_tc = 1; + move16(); + } + ELSE IF ( EQ_16( st_ivas->ivas_format, ISM_FORMAT ) ) + { + IF ( EQ_16( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) ) + { + num_tc = 1; + move16(); + } + } + ELSE IF ( EQ_16( st_ivas->ivas_format, SBA_FORMAT ) || EQ_16( st_ivas->ivas_format, MASA_FORMAT ) ) + { + test(); test(); test(); test(); test(); + IF ( st_ivas->sba_dirac_stereo_flag ) + { + num_tc = CPE_CHANNELS; + move16(); + } + ELSE IF ( EQ_16( st_ivas->ivas_format, MASA_FORMAT ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) && ( GT_32( ivas_total_brate, IVAS_SID_5k2 ) || ( LE_32( ivas_total_brate, IVAS_SID_5k2 ) && GT_16( st_ivas->nCPE, 0 ) && st_ivas->hCPE[0] != NULL && EQ_16( st_ivas->hCPE[0]->nchan_out, 1 ) ) ) ) + { + num_tc = 1; /* Only one channel transported */ + move16(); + } + + test(); test(); test(); test(); test(); + IF ( EQ_16( st_ivas->ivas_format, MASA_FORMAT ) && EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) && EQ_16( st_ivas->nchan_transport, 2 ) && LT_32( st_ivas->hDecoderConfig->ivas_total_brate, MASA_STEREO_MIN_BITRATE ) && GT_32( st_ivas->hDecoderConfig->ivas_total_brate, IVAS_SID_5k2 ) ) + { + num_tc = CPE_CHANNELS; + move16(); + } + IF ( EQ_16( st_ivas->ivas_format, SBA_FORMAT ) ) + { + IF ( EQ_16( num_tc, 3 ) ) + { + num_tc = add( num_tc, 1 ); + } + } + } + ELSE IF( EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) + { + IF( NE_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) + { + test(); + IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) + { + num_tc = add( num_tc, 1 ); + } + ELSE IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) + { + num_tc = add( num_tc, st_ivas->nchan_ism ); + } + } + } + ELSE IF ( EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) ) + { + test(); test(); + IF ( st_ivas->sba_dirac_stereo_flag ) + { + num_tc = CPE_CHANNELS; + move16(); + } + IF ( ( st_ivas->sba_planar && GE_16( num_tc, 3 ) ) || EQ_16( num_tc, 3 ) ) + { + num_tc = add( num_tc, 1 ); + } + IF ( EQ_16( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) + { + num_tc = add( num_tc, st_ivas->nchan_ism ); + } + } + ELSE IF ( EQ_16( st_ivas->ivas_format, MC_FORMAT ) ) + { + IF ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_MONO ) ) + { + num_tc = 1; + move16(); + } + ELSE IF ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_STEREO ) ) + { + num_tc = 2; + move16(); + } + ELSE IF ( EQ_16( st_ivas->mc_mode, MC_MODE_MCT ) ) + { + /* do all static dmx already in the TC decoder if less channels than transported... */ + test(); test(); test(); test(); test(); + IF ( NE_16( st_ivas->transport_config, st_ivas->intern_config ) && ( EQ_16( st_ivas->intern_config, IVAS_AUDIO_CONFIG_FOA ) || EQ_16( st_ivas->intern_config, IVAS_AUDIO_CONFIG_HOA2 ) || EQ_16( st_ivas->intern_config, IVAS_AUDIO_CONFIG_HOA3 ) ) ) + { + IF ( GE_16( add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ), add( st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hIntSetup.num_lfe ) ) ) + { + num_tc = add( st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hIntSetup.num_lfe ); + } + } + ELSE IF ( ( EQ_16( st_ivas->renderer_type, RENDERER_MC ) || EQ_16( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) && GE_16( add(st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe), add(st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe))) + { + num_tc = add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ); + } + } + ELSE IF ( EQ_16( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) ) + { + num_tc = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS; + move16(); + } + ELSE IF ( EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) ) + { + IF ( st_ivas->hOutSetup.separateChannelEnabled ) + { + num_tc = add( num_tc, st_ivas->nchan_ism ); + } + IF ( st_ivas->hOutSetup.separateChannelEnabled && ( EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1 ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_7_1 ) || + EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1_4 ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_7_1_4 ) || + EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1_2 ) || ( EQ_16( output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && GT_16( st_ivas->hOutSetup.num_lfe, 0 ) ) ) ) + { + /* LFE is synthesized in TD with the TCs*/ + num_tc = add( num_tc, st_ivas->nchan_ism ); + } + } + } + ELSE IF ( EQ_16( st_ivas->ivas_format, MONO_FORMAT ) && EQ_16( st_ivas->renderer_type, RENDERER_NON_DIEGETIC_DOWNMIX ) ) + { + num_tc = MAX_OUTPUT_CHANNELS_IN_DIEGETIC_PAN; + move16(); + } + + return num_tc; +} +#endif + /*--------------------------------------------------------------------------* * ivas_jbm_dec_copy_tc() * @@ -2358,6 +2520,14 @@ ivas_error ivas_jbm_dec_tc_buffer_open( { hTcBuffer->tc[ch_idx] = NULL; } +#ifdef IVAS_FLOAT_FIXED + hTcBuffer->tc_buffer_fx = NULL; + + FOR ( ch_idx = 0; ch_idx < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; ch_idx++ ) + { + hTcBuffer->tc_fx[ch_idx] = NULL; + } +#endif } else { @@ -2379,6 +2549,14 @@ ivas_error ivas_jbm_dec_tc_buffer_open( if ( nsamp_to_allocate == 0 ) { +#ifdef IVAS_FLOAT_FIXED + hTcBuffer->tc_buffer_fx = NULL; + + FOR ( ch_idx = 0; ch_idx < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; ch_idx++ ) + { + hTcBuffer->tc_fx[ch_idx] = NULL; + } +#endif hTcBuffer->tc_buffer = NULL; for ( ch_idx = 0; ch_idx < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; ch_idx++ ) @@ -2395,26 +2573,222 @@ ivas_error ivas_jbm_dec_tc_buffer_open( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM TC Buffer\n" ) ); } set_zero( hTcBuffer->tc_buffer, nsamp_to_allocate ); +#ifdef IVAS_FLOAT_FIXED + IF ( ( hTcBuffer->tc_buffer_fx = (Word16 *) malloc( nsamp_to_allocate * sizeof( Word16 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM TC Buffer\n" ) ); + } + set16_fx( hTcBuffer->tc_buffer_fx, 0, nsamp_to_allocate ); +#endif offset = 0; for ( ch_idx = 0; ch_idx < hTcBuffer->nchan_buffer_full; ch_idx++ ) { hTcBuffer->tc[ch_idx] = &hTcBuffer->tc_buffer[offset]; +#ifdef IVAS_FLOAT_FIXED + hTcBuffer->tc_fx[ch_idx] = &hTcBuffer->tc_buffer_fx[offset]; +#endif offset += n_samp_full; } for ( ; ch_idx < hTcBuffer->nchan_transport_internal; ch_idx++ ) { hTcBuffer->tc[ch_idx] = &hTcBuffer->tc_buffer[offset]; +#ifdef IVAS_FLOAT_FIXED + hTcBuffer->tc_fx[ch_idx] = &hTcBuffer->tc_buffer_fx[offset]; +#endif offset += n_samp_residual; } for ( ; ch_idx < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; ch_idx++ ) { hTcBuffer->tc[ch_idx] = NULL; +#ifdef IVAS_FLOAT_FIXED + hTcBuffer->tc_fx[ch_idx] = NULL; +#endif } } else { hTcBuffer->tc_buffer = NULL; +#ifdef IVAS_FLOAT_FIXED + hTcBuffer->tc_buffer_fx = NULL; +#endif + } + } + } + + st_ivas->hTcBuffer = hTcBuffer; + + return IVAS_ERR_OK; +} + +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_jbm_dec_tc_buffer_open_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const TC_BUFFER_MODE tc_buffer_mode, /* i : buffer mode */ + const Word16 nchan_transport_jbm, /* i : number of real transport channels */ + const Word16 nchan_transport_internal, /* i : number of totally buffered channels */ + const Word16 nchan_full, /* i : number of channels to fully store */ + const Word16 n_samples_granularity /* i : granularity of the renderer/buffer */ +) +{ + Word16 nsamp_to_allocate; + DECODER_TC_BUFFER_HANDLE hTcBuffer; + Word16 nMaxSlotsPerSubframe; + Word16 nchan_residual; + Word16 ch_idx; + Word16 tmp, tmp_e; + Word32 tmp32; + + /*-----------------------------------------------------------------* + * prepare library opening + *-----------------------------------------------------------------*/ + + IF ( ( hTcBuffer = (DECODER_TC_BUFFER_HANDLE) malloc( sizeof( DECODER_TC_BUFFER ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM TC Buffer\n" ) ); + } + + hTcBuffer->tc_buffer_mode = tc_buffer_mode; + hTcBuffer->nchan_transport_jbm = nchan_transport_jbm; + move16(); + hTcBuffer->nchan_transport_internal = nchan_transport_internal; + move16(); + hTcBuffer->nchan_buffer_full = nchan_full; + move16(); + nchan_residual = sub(nchan_transport_internal, nchan_full); + hTcBuffer->n_samples_granularity = n_samples_granularity; + move16(); + hTcBuffer->n_samples_available = 0; + move16(); + hTcBuffer->n_samples_buffered = 0; + move16(); + hTcBuffer->n_samples_rendered = 0; + move16(); + hTcBuffer->slots_rendered = 0; + move16(); + hTcBuffer->subframes_rendered = 0; + move16(); + hTcBuffer->n_samples_discard = 0; + move16(); + hTcBuffer->n_samples_flushed = 0; + move16(); + hTcBuffer->nb_subframes = MAX_PARAM_SPATIAL_SUBFRAMES; + move16(); + nsamp_to_allocate = 0; + move16(); + + tmp32 = L_mult0(FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES, hTcBuffer->n_samples_granularity); + tmp = BASOP_Util_Divide3232_Scale(st_ivas->hDecoderConfig->output_Fs, tmp32, &tmp_e); + nMaxSlotsPerSubframe = shr(tmp, sub(15, tmp_e)); // Q0 + + hTcBuffer->num_slots = mult0(nMaxSlotsPerSubframe, MAX_PARAM_SPATIAL_SUBFRAMES); + + set16_fx( hTcBuffer->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set16_fx( hTcBuffer->subframe_nbslots, nMaxSlotsPerSubframe, MAX_PARAM_SPATIAL_SUBFRAMES ); + + IF ( EQ_16( hTcBuffer->tc_buffer_mode, TC_BUFFER_MODE_NONE ) ) + { +#if 1 /* TODO: remove float code */ + hTcBuffer->tc_buffer = NULL; + + FOR(ch_idx = 0; ch_idx < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; ch_idx++) + { + hTcBuffer->tc[ch_idx] = NULL; + } +#endif + hTcBuffer->tc_buffer_fx = NULL; + + FOR ( ch_idx = 0; ch_idx < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; ch_idx++ ) + { + hTcBuffer->tc_fx[ch_idx] = NULL; + } + } + ELSE + { + Word16 n_samp_full, n_samp_residual; + Word32 offset; + IF ( st_ivas->hDecoderConfig->Opt_tsm ) + { + n_samp_full = ( NS2SA( st_ivas->hDecoderConfig->output_Fs, MAX_JBM_L_FRAME_NS ) + hTcBuffer->n_samples_granularity - 1 ); + n_samp_residual = sub(hTcBuffer->n_samples_granularity, 1); + } + ELSE + { + tmp = BASOP_Util_Divide3232_Scale(st_ivas->hDecoderConfig->output_Fs, FRAMES_PER_SEC, &tmp_e); + n_samp_full = shr(tmp, sub(15, tmp_e)); // Q0 + n_samp_residual = 0; + move16(); + } + + nsamp_to_allocate = mult0( hTcBuffer->nchan_buffer_full, n_samp_full ); + nsamp_to_allocate = add( nsamp_to_allocate, mult0( nchan_residual, n_samp_residual ) ); + + IF ( EQ_16( nsamp_to_allocate, 0 ) ) + { +#if 1 /* TODO: remove float code */ + hTcBuffer->tc_buffer = NULL; + + FOR ( ch_idx = 0; ch_idx < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; ch_idx++ ) + { + hTcBuffer->tc[ch_idx] = NULL; + } +#endif + hTcBuffer->tc_buffer_fx = NULL; + + FOR ( ch_idx = 0; ch_idx < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; ch_idx++ ) + { + hTcBuffer->tc_fx[ch_idx] = NULL; + } + } + ELSE + { + IF ( st_ivas->hDecoderConfig->Opt_tsm ) + { +#if 1 /* TODO: remove float memory allocation */ + IF ( ( hTcBuffer->tc_buffer = (float *) malloc( nsamp_to_allocate * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM TC Buffer\n" ) ); + } + set_zero( hTcBuffer->tc_buffer, nsamp_to_allocate ); +#endif + IF ( ( hTcBuffer->tc_buffer_fx = (Word16 *) malloc( nsamp_to_allocate * sizeof( Word16 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM TC Buffer\n" ) ); + } + set16_fx( hTcBuffer->tc_buffer_fx, 0, nsamp_to_allocate ); + + offset = 0; + move16(); + FOR ( ch_idx = 0; ch_idx < hTcBuffer->nchan_buffer_full; ch_idx++ ) + { +#if 1 /* TODO: remove float code */ + hTcBuffer->tc[ch_idx] = &hTcBuffer->tc_buffer[offset]; +#endif + hTcBuffer->tc_fx[ch_idx] = &hTcBuffer->tc_buffer_fx[offset]; + offset = L_add(offset, n_samp_full); + } + FOR ( ; ch_idx < hTcBuffer->nchan_transport_internal; ch_idx++ ) + { +#if 1 /* TODO: remove float code */ + hTcBuffer->tc[ch_idx] = &hTcBuffer->tc_buffer[offset]; +#endif + hTcBuffer->tc_fx[ch_idx] = &hTcBuffer->tc_buffer_fx[offset]; + offset = L_add(offset, n_samp_residual); + } + FOR ( ; ch_idx < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; ch_idx++ ) + { +#if 1 /* TODO: remove float code */ + hTcBuffer->tc[ch_idx] = NULL; +#endif + hTcBuffer->tc_fx[ch_idx] = NULL; + } + } + ELSE + { +#if 1 /* TODO: remove float code */ + hTcBuffer->tc_buffer = NULL; +#endif + hTcBuffer->tc_buffer_fx = NULL; } } } @@ -2423,6 +2797,7 @@ ivas_error ivas_jbm_dec_tc_buffer_open( return IVAS_ERR_OK; } +#endif /*--------------------------------------------------------------------------* @@ -2478,6 +2853,13 @@ ivas_error ivas_jbm_dec_tc_buffer_reconfigure( free( hTcBuffer->tc_buffer ); hTcBuffer->tc_buffer = NULL; } +#ifdef IVAS_FLOAT_FIXED + IF( ( hTcBuffer )->tc_buffer_fx != NULL ) + { + free( ( hTcBuffer )->tc_buffer_fx ); + ( hTcBuffer )->tc_buffer_fx = NULL; + } +#endif if ( st_ivas->hDecoderConfig->Opt_tsm ) { @@ -2499,6 +2881,13 @@ ivas_error ivas_jbm_dec_tc_buffer_reconfigure( { hTcBuffer->tc[ch_idx] = NULL; } +#ifdef IVAS_FLOAT_FIXED + hTcBuffer->tc_buffer_fx = NULL; + FOR ( ch_idx = 0; ch_idx < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; ch_idx++ ) + { + hTcBuffer->tc_fx[ch_idx] = NULL; + } +#endif } else { @@ -2509,26 +2898,45 @@ ivas_error ivas_jbm_dec_tc_buffer_reconfigure( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM TC Buffer\n" ) ); } set_zero( hTcBuffer->tc_buffer, nsamp_to_allocate ); +#ifdef IVAS_FLOAT_FIXED + if ( ( hTcBuffer->tc_buffer_fx = (Word16 *) malloc( nsamp_to_allocate * sizeof( Word16 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM TC Buffer\n" ) ); + } + set16_fx( hTcBuffer->tc_buffer_fx, 0, nsamp_to_allocate ); +#endif offset = 0; for ( ch_idx = 0; ch_idx < hTcBuffer->nchan_buffer_full; ch_idx++ ) { hTcBuffer->tc[ch_idx] = &hTcBuffer->tc_buffer[offset]; +#ifdef IVAS_FLOAT_FIXED + hTcBuffer->tc_fx[ch_idx] = &hTcBuffer->tc_buffer_fx[offset]; +#endif offset += n_samp_full; } for ( ; ch_idx < hTcBuffer->nchan_transport_internal; ch_idx++ ) { hTcBuffer->tc[ch_idx] = &hTcBuffer->tc_buffer[offset]; +#ifdef IVAS_FLOAT_FIXED + hTcBuffer->tc_fx[ch_idx] = &hTcBuffer->tc_buffer_fx[offset]; +#endif offset += n_samp_residual; } for ( ; ch_idx < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; ch_idx++ ) { hTcBuffer->tc[ch_idx] = NULL; +#ifdef IVAS_FLOAT_FIXED + hTcBuffer->tc_fx[ch_idx] = NULL; +#endif } } else { hTcBuffer->tc_buffer = NULL; +#ifdef IVAS_FLOAT_FIXED + hTcBuffer->tc_buffer_fx = NULL; +#endif } } @@ -2601,6 +3009,14 @@ void ivas_jbm_dec_tc_buffer_close( ( *phTcBuffer )->tc_buffer = NULL; } +#ifdef IVAS_FLOAT_FIXED + IF( ( *phTcBuffer )->tc_buffer_fx != NULL ) + { + free( ( *phTcBuffer )->tc_buffer_fx ); + ( *phTcBuffer )->tc_buffer_fx = NULL; + } +#endif + free( *phTcBuffer ); *phTcBuffer = NULL; } diff --git a/lib_dec/ivas_masa_dec.c b/lib_dec/ivas_masa_dec.c index 822d2ef96..8870a16a3 100644 --- a/lib_dec/ivas_masa_dec.c +++ b/lib_dec/ivas_masa_dec.c @@ -43,6 +43,10 @@ #include "wmc_auto.h" #include "prot_fx1.h" #include "prot_fx2.h" +#include "ivas_prot_fx.h" +#include "prot_fx1.h" +#include "ivas_rom_com_fx.h" + /*-----------------------------------------------------------------------* * Local constants @@ -66,12 +70,24 @@ static void restore_lowbitrate_masa( IVAS_QMETADATA_HANDLE hQMetaData, const int static ivas_error init_lfe_synth_data( Decoder_Struct *st_ivas, MASA_DECODER_HANDLE hMasa ); +#ifdef IVAS_FLOAT_FIXED +static ivas_error init_lfe_synth_data_fx( Decoder_Struct *st_ivas, MASA_DECODER_HANDLE hMasa ); +#endif + static void compute_foa_cov_matrix( float foaCov[FOA_CHANNELS][FOA_CHANNELS], float inCov[FOA_CHANNELS][FOA_CHANNELS], float mixMtx[FOA_CHANNELS][FOA_CHANNELS] ); static int16_t decode_lfe_to_total_energy_ratio( MCMASA_LFE_SYNTH_DATA_HANDLE hMasaLfeSynth, uint16_t *bitstream, int16_t *index, const int32_t ivas_total_brate ); +#ifdef IVAS_FLOAT_FIXED +static Word16 decode_lfe_to_total_energy_ratio_fx( MCMASA_LFE_SYNTH_DATA_HANDLE hMasaLfeSynth, uint16_t *bitstream, int16_t *index, const int32_t ivas_total_brate ); +#endif + static ivas_error ivas_masa_dec_config( Decoder_Struct *st_ivas ); +#ifdef IVAS_FLOAT_FIXED +static ivas_error ivas_masa_dec_config_fx( Decoder_Struct *st_ivas ); +#endif + static int16_t ivas_decode_masaism_metadata( IVAS_QMETADATA_HANDLE hQMetaData, MASA_DECODER_HANDLE hMasa, MASA_ISM_DATA_HANDLE hMasaIsmData, const int16_t nchan_ism, uint16_t *bit_stream, int16_t *next_bit_pos, const int16_t idx_separated_object, const int16_t ism_imp, const int16_t dirac_bs_md_write_idx, const int16_t dirac_md_buffer_length ); static void decode_index_slice( int16_t index, int16_t *ratio_idx_ism, const int16_t nchan_ism, const int16_t K ); @@ -281,11 +297,27 @@ ivas_error ivas_masa_decode( if ( st_ivas->mc_mode == MC_MODE_MCMASA ) { +#ifdef IVAS_FLOAT_FIXED + for ( int j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + hMasa->hMasaLfeSynth->lfeToTotalEnergyRatio_fx[j] = float_to_fix16( hMasa->hMasaLfeSynth->lfeToTotalEnergyRatio[j], Q14 ); + } + *nb_bits_read = add( *nb_bits_read, decode_lfe_to_total_energy_ratio_fx( hMasa->hMasaLfeSynth, st->bit_stream, &st->next_bit_pos, ivas_total_brate ) ); + for ( int j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + hMasa->hMasaLfeSynth->lfeToTotalEnergyRatio[j] = fix16_to_float( hMasa->hMasaLfeSynth->lfeToTotalEnergyRatio_fx[j], Q14 ); + } +#else *nb_bits_read += decode_lfe_to_total_energy_ratio( hMasa->hMasaLfeSynth, st->bit_stream, &st->next_bit_pos, ivas_total_brate ); +#endif } /* Once we know incoming configuration, we can config decoder further based on bitrate etc. */ +#ifdef IVAS_FLOAT_FIXED + IF ( ( error = ivas_masa_dec_config_fx( st_ivas ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_masa_dec_config( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -438,12 +470,20 @@ ivas_error ivas_masa_decode( if ( hQMetaData->q_direction == NULL ) { /* replicate ivas_masa_dec_config() in case that first good received frame is SID frame */ +#ifdef IVAS_FLOAT_FIXED + IF ( ( error = ivas_masa_dec_config_fx( st_ivas ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_masa_dec_config( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } +#ifdef IVAS_FLOAT_FIXED + ivas_masa_set_elements_fx( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE, st_ivas->ivas_format, st_ivas->ism_mode, 0 ); +#else ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE, st_ivas->ivas_format, st_ivas->ism_mode, 0 ); +#endif hQMetaData->metadata_max_bits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC; @@ -517,7 +557,11 @@ ivas_error ivas_masa_decode( { if ( hQMetaData->q_direction == NULL ) { +#ifdef IVAS_FLOAT_FIXED + IF ( ( error = ivas_masa_dec_config_fx( st_ivas ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_masa_dec_config( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -556,7 +600,11 @@ ivas_error ivas_masa_decode( { if ( hQMetaData->q_direction == NULL ) { +#ifdef IVAS_FLOAT_FIXED + if ( ( error = ivas_masa_dec_config_fx( st_ivas ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_masa_dec_config( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -755,6 +803,125 @@ ivas_error ivas_masa_dec_open( return error; } +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_masa_dec_open_fx( + Decoder_Struct *st_ivas /* i/o: IVAS decoder handle */ +) +{ + MASA_DECODER_HANDLE hMasa; + ivas_error error; + Word16 i; + Word32 ism_total_brate; + + error = IVAS_ERR_OK; + + IF ( ( hMasa = (MASA_DECODER_HANDLE) malloc( sizeof( MASA_DECODER ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + + ism_total_brate = 0; + move32(); + + test(); test(); test(); test(); + IF ( EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) && GT_16( st_ivas->nSCE, 0 ) && ( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) ) + { + FOR ( i = 0; i < st_ivas->nSCE; i++ ) + { + ism_total_brate = L_add(ism_total_brate, st_ivas->hSCE[i]->element_brate); + } + } + + ivas_masa_set_elements_fx( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE, st_ivas->ivas_format, st_ivas->ism_mode, ism_total_brate ); + + Copy( DirAC_block_grouping, hMasa->config.block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); + Copy( MASA_band_grouping_24, hMasa->config.band_grouping, MASA_FREQUENCY_BANDS + 1 ); + hMasa->config.numberOfDirections = 1; + hMasa->config.joinedSubframes = FALSE; + + /* Create spherical grid only for external output */ + IF ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) + { + IF ( ( hMasa->data.sph_grid16 = (SPHERICAL_GRID_DATA *) malloc( sizeof( SPHERICAL_GRID_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + + generate_gridEq_fx( hMasa->data.sph_grid16 ); + + IF ( ( hMasa->data.extOutMeta = (MASA_DECODER_EXT_OUT_META *) malloc( sizeof( MASA_DECODER_EXT_OUT_META ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + } + ELSE + { + hMasa->data.sph_grid16 = NULL; + hMasa->data.extOutMeta = NULL; + } + + IF ( EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) ) + { + error = init_lfe_synth_data_fx( st_ivas, hMasa ); + } + ELSE + { + hMasa->hMasaLfeSynth = NULL; + } + + st_ivas->hMasa = hMasa; + + /* allocate transport channels*/ + test(); test(); test(); test(); + IF ( st_ivas->hTcBuffer == NULL && NE_16( st_ivas->renderer_type, RENDERER_DISABLE ) && NE_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) && NE_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) && NE_16( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) ) + { + Word16 nchan_to_allocate, nchan_transport; + TC_BUFFER_MODE buffer_mode; + + buffer_mode = TC_BUFFER_MODE_RENDERER; + move16(); + test(); + test(); + test(); + IF ( EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) && ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_STEREO ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_MONO ) ) ) + { + buffer_mode = TC_BUFFER_MODE_BUFFER; + move16(); + } + ELSE IF ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) + { + buffer_mode = TC_BUFFER_MODE_BUFFER; + move16(); + } + + nchan_transport = ivas_jbm_dec_get_num_tc_channels_fx( st_ivas ); + nchan_to_allocate = nchan_transport; + move16(); + + test(); + test(); + IF ( EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_16( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) ) + { + nchan_transport = 1; + move16(); + nchan_to_allocate = 1; + move16(); + } + ELSE IF ( EQ_16( st_ivas->nchan_transport, 1 ) && EQ_16( st_ivas->renderer_type, RENDERER_DIRAC ) ) + { + /* addtl channel for CNG */ + nchan_to_allocate = add( nchan_to_allocate, 1 ); + } + + IF ( ( error = ivas_jbm_dec_tc_buffer_open_fx( st_ivas, buffer_mode, nchan_transport, nchan_to_allocate, nchan_to_allocate, NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return error; +} +#endif /*-----------------------------------------------------------------------* * ivas_masa_dec_close() @@ -820,6 +987,87 @@ void ivas_masa_dec_close( return; } +#ifdef IVAS_FLOAT_FIXED +void ivas_masa_dec_close_fx( + MASA_DECODER_HANDLE *hMasa_out /* i/o: MASA metadata structure */ +) +{ + MASA_DECODER_HANDLE hMasa; + + IF ( hMasa_out == NULL || *hMasa_out == NULL ) + { + return; + } + + hMasa = *hMasa_out; + + /* Free spherical grid memory if in use */ + IF ( hMasa->data.sph_grid16 != NULL ) + { + free( hMasa->data.sph_grid16 ); + hMasa->data.sph_grid16 = NULL; + } + + IF ( hMasa->data.extOutMeta != NULL ) + { + free( hMasa->data.extOutMeta ); + hMasa->data.extOutMeta = NULL; + } + + IF ( hMasa->hMasaLfeSynth != NULL ) + { +#if 1 /* TODO: Remove float free */ + IF ( hMasa->hMasaLfeSynth->lfeSynthRingBuffer != NULL ) + { + free( hMasa->hMasaLfeSynth->lfeSynthRingBuffer ); + hMasa->hMasaLfeSynth->lfeSynthRingBuffer = NULL; + } + IF ( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2 != NULL ) + { + free( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2 ); + hMasa->hMasaLfeSynth->lfeSynthRingBuffer2 = NULL; + } + IF ( hMasa->hMasaLfeSynth->delayBuffer_syncLp != NULL ) + { + free( hMasa->hMasaLfeSynth->delayBuffer_syncLp ); + hMasa->hMasaLfeSynth->delayBuffer_syncLp = NULL; + } + IF ( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC != NULL ) + { + free( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC ); + hMasa->hMasaLfeSynth->delayBuffer_syncDirAC = NULL; + } +#endif + IF ( hMasa->hMasaLfeSynth->lfeSynthRingBuffer_fx != NULL ) + { + free( hMasa->hMasaLfeSynth->lfeSynthRingBuffer_fx ); + hMasa->hMasaLfeSynth->lfeSynthRingBuffer_fx = NULL; + } + IF ( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2_fx != NULL ) + { + free( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2_fx ); + hMasa->hMasaLfeSynth->lfeSynthRingBuffer2_fx = NULL; + } + IF ( hMasa->hMasaLfeSynth->delayBuffer_syncLp_fx != NULL ) + { + free( hMasa->hMasaLfeSynth->delayBuffer_syncLp_fx ); + hMasa->hMasaLfeSynth->delayBuffer_syncLp_fx = NULL; + } + IF ( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx != NULL ) + { + free( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx ); + hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx = NULL; + } + free( hMasa->hMasaLfeSynth ); + hMasa->hMasaLfeSynth = NULL; + } + + free( *hMasa_out ); + *hMasa_out = NULL; + + return; +} +#endif /*-------------------------------------------------------------------* * ivas_masa_dec_config() @@ -927,6 +1175,124 @@ static ivas_error ivas_masa_dec_config( return error; } +#ifdef IVAS_FLOAT_FIXED +static ivas_error ivas_masa_dec_config_fx( + Decoder_Struct *st_ivas /* i/o: IVAS decoder handle */ +) +{ + Word16 i; + MASA_DECODER_HANDLE hMasa; + UWord8 maxBand; + Word16 maxBin; + ivas_error error; + Word32 ivas_total_brate; + Word32 ism_total_brate; + error = IVAS_ERR_OK; + hMasa = st_ivas->hMasa; + + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + ism_total_brate = 0; + move16(); + + test(); + test(); + test(); + test(); + IF ( EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) && GT_16( st_ivas->nSCE, 0 ) && ( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) ) + { + FOR ( i = 0; i < st_ivas->nSCE; i++ ) + { + ism_total_brate = L_add(ism_total_brate, st_ivas->hSCE[i]->element_brate); + } + } + + ivas_masa_set_elements_fx( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE, st_ivas->ivas_format, st_ivas->ism_mode, ism_total_brate ); + + IF ( EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) + { + ivas_masa_set_coding_config( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hCPE[0]->element_brate, st_ivas->nchan_transport, MC_MODE_NONE ); + } + ELSE + { + ivas_masa_set_coding_config( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ); + } + + test(); + test(); + IF ( ( EQ_16( st_ivas->ivas_format, MASA_FORMAT ) || EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) && EQ_32( st_ivas->hDecoderConfig->ivas_total_brate, IVAS_512k ) ) + { + hMasa->config.mergeRatiosOverSubframes = 0; + + /* initialize spherical grid */ + IF ( hMasa->data.sph_grid16 == NULL ) + { + IF ( ( hMasa->data.sph_grid16 = (SPHERICAL_GRID_DATA *) malloc( sizeof( SPHERICAL_GRID_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA data handle\n" ) ); + } + generate_gridEq_fx( hMasa->data.sph_grid16 ); + } + } + st_ivas->hQMetaData->metadata_max_bits = hMasa->config.max_metadata_bits; + move16(); + st_ivas->hQMetaData->bandMap = hMasa->data.band_mapping; + move16(); + st_ivas->hQMetaData->nchan_transport = st_ivas->nchan_transport; + move16(); + + /* TODO: use fixed version of this function call */ + IF ( ( error = ivas_qmetadata_allocate_memory( st_ivas->hQMetaData, hMasa->config.numCodingBands, hMasa->config.numberOfDirections, hMasa->config.useCoherence ) ) != IVAS_ERR_OK ) + { + return error; + } + + st_ivas->hQMetaData->numTwoDirBands = st_ivas->hMasa->config.numTwoDirBands; + st_ivas->hQMetaData->useLowerRes = 0; + move16(); + + FOR ( i = 0; i < st_ivas->hQMetaData->no_directions; i++ ) + { + st_ivas->hQMetaData->q_direction[i].cfg.nbands = hMasa->config.numCodingBands; + st_ivas->hQMetaData->q_direction[i].cfg.nblocks = hMasa->config.joinedSubframes == TRUE ? 1 : 4; + + test(); + IF ( EQ_16( st_ivas->ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) ) + { + st_ivas->hQMetaData->q_direction[i].cfg.mc_ls_setup = ivas_mc_map_output_config_to_mc_ls_setup( st_ivas->transport_config ); + } + ELSE + { + st_ivas->hQMetaData->q_direction[i].cfg.mc_ls_setup = MC_LS_SETUP_INVALID; + } + } + + ivas_set_qmetadata_maxbit_req( st_ivas->hQMetaData, st_ivas->ivas_format ); + + /* Find maximum band usable */ + maxBin = (Word16) Mpy_32_32( st_ivas->hDecoderConfig->output_Fs, INV_CLDFB_BANDWIDTH_Q31 ); + maxBand = 0; + move16(); + WHILE ( maxBand <= MASA_FREQUENCY_BANDS && LE_16( MASA_band_grouping_24[maxBand], maxBin ) ) + { + maxBand++; + } + maxBand--; + + IF ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) + { + /* need to apply the sampling rate correction also for the EXT output MASA meta buffer */ + masa_sample_rate_band_correction_fx( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hQMetaData, maxBand, 0, hMasa->data.extOutMeta ); + } + ELSE + { + masa_sample_rate_band_correction_fx( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hQMetaData, maxBand, 0, NULL ); + } + + return error; +} + +#endif + /*-------------------------------------------------------------------* * ivas_masa_prerender() @@ -1228,6 +1594,221 @@ static ivas_error init_lfe_synth_data( return IVAS_ERR_OK; } +#ifdef IVAS_FLOAT_FIXED +static ivas_error init_lfe_synth_data_fx( + Decoder_Struct *st_ivas, /* i : IVAS decoder struct */ + MASA_DECODER_HANDLE hMasa /* i/o: MASA decoder structure */ +) +{ + Word32 output_Fs; + AUDIO_CONFIG output_config; + + output_Fs = st_ivas->hDecoderConfig->output_Fs; + move16(); + output_config = st_ivas->hDecoderConfig->output_config; + move32(); + + IF ( ( hMasa->hMasaLfeSynth = (MCMASA_LFE_SYNTH_DATA_HANDLE) malloc( sizeof( MCMASA_LFE_SYNTH_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + +#if 1 /* TODO: remove float code. */ + hMasa->hMasaLfeSynth->transportEneSmooth = 0.0f; + hMasa->hMasaLfeSynth->protoLfeEneSmooth = 0.0f; + hMasa->hMasaLfeSynth->targetEneLfeSmooth = 0.0f; + hMasa->hMasaLfeSynth->targetEneTransSmooth = 0.0f; +#endif + + hMasa->hMasaLfeSynth->transportEneSmooth_fx = 0; + move16(); + hMasa->hMasaLfeSynth->protoLfeEneSmooth_fx = 0; + move16(); + hMasa->hMasaLfeSynth->targetEneLfeSmooth_fx = 0; + move16(); + hMasa->hMasaLfeSynth->targetEneTransSmooth_fx = 0; + move16(); + +#if 1 /* TODO: remove float code. */ + set_zero( hMasa->hMasaLfeSynth->lfeToTotalEnergyRatio, MAX_PARAM_SPATIAL_SUBFRAMES ); +#endif + set16_fx( hMasa->hMasaLfeSynth->lfeToTotalEnergyRatio_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + hMasa->hMasaLfeSynth->lfeGainPrevIndex = 0; + move16(); + + test(); test(); test(); test(); test(); + test(); test(); test(); test(); test(); test(); + IF ( st_ivas->hOutSetup.separateChannelEnabled && + ( EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1 ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_7_1 ) || + EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1_2 ) || + EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1_4 ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_7_1_4 ) || + EQ_16( output_config, IVAS_AUDIO_CONFIG_FOA ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_HOA2 ) || + EQ_16( output_config, IVAS_AUDIO_CONFIG_HOA3 ) || + ( EQ_16( output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && GT_16( st_ivas->hOutSetup.num_lfe, 0 ) ) ) ) + { + Word16 bufferSize; + Word16 i; + Word16 slot_size; + Word16 tmp, tmp_e; + + /* Ring buffer for the filterbank of the LFE synthesis. + * The filterbank is using moving average lowpass filter with the crossover of 120 Hz. */ + tmp = BASOP_Util_Divide3232_Scale(output_Fs, FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES, &tmp_e); + bufferSize = shr(tmp, sub(15, tmp_e)); // Q0 + +#if 1 /* TODO: remove float code. */ + IF ( ( hMasa->hMasaLfeSynth->lfeSynthRingBuffer = ( float * )malloc( bufferSize * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + set_zero( hMasa->hMasaLfeSynth->lfeSynthRingBuffer, bufferSize ); +#endif + IF ( ( hMasa->hMasaLfeSynth->lfeSynthRingBuffer_fx = ( Word16 * )malloc( bufferSize * sizeof( Word16 ) ) ) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n")); + } + set16_fx( hMasa->hMasaLfeSynth->lfeSynthRingBuffer_fx, 0, bufferSize ); + + hMasa->hMasaLfeSynth->ringBufferLoPointer = 0; + move16(); + hMasa->hMasaLfeSynth->ringBufferHiPointer = shr(bufferSize, 1); +#if 1 /* TODO: remove float code. */ + hMasa->hMasaLfeSynth->lowpassSum = 0.0f; +#endif + hMasa->hMasaLfeSynth->lowpassSum_fx = 0; + move16(); + hMasa->hMasaLfeSynth->ringBufferSize = bufferSize; + move16(); + + /* Ring buffer for additional lowpass filter for the LFE signal. + * Moving average lowpass filter with the crossover of 240 Hz. */ + bufferSize = shr( bufferSize, 1 ); + +#if 1 /* TODO: remove float code. */ + IF ( ( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2 = (float *) malloc( bufferSize * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + set_zero( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2, bufferSize ); +#endif + IF ( ( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2_fx = (Word16 *) malloc( bufferSize * sizeof( Word16 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + set16_fx( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2_fx, 0, bufferSize ); + + hMasa->hMasaLfeSynth->ringBufferLoPointer2 = 0; +#if 1 /* TODO: remove float code. */ + hMasa->hMasaLfeSynth->lowpassSum2 = 0.0f; +#endif + hMasa->hMasaLfeSynth->lowpassSum2_fx = 0; + move16(); + hMasa->hMasaLfeSynth->ringBufferSize2 = bufferSize; + move16(); + + /* Delay buffer for matching the delay of the lowpass filter */ + bufferSize = shr(bufferSize, 1); /* The delay of the moving average lowpass filter is bufferSize / 2 */ +#if 1 /* TODO: remove float code. */ + IF ( ( hMasa->hMasaLfeSynth->delayBuffer_syncLp = (float *) malloc( bufferSize * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + set_zero( hMasa->hMasaLfeSynth->delayBuffer_syncLp, bufferSize ); +#endif + IF ( ( hMasa->hMasaLfeSynth->delayBuffer_syncLp_fx = (Word16 *) malloc( bufferSize * sizeof( Word16 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + set16_fx( hMasa->hMasaLfeSynth->delayBuffer_syncLp_fx, 0, bufferSize ); + hMasa->hMasaLfeSynth->delayBuffer_syncLp_size = bufferSize; + move16(); + + /* Delay buffer for syncing with DirAC rendering */ + bufferSize = sub(sub(NS2SA( output_Fs, IVAS_FB_DEC_DELAY_NS ), shr(hMasa->hMasaLfeSynth->ringBufferSize, 1)), shr(hMasa->hMasaLfeSynth->ringBufferSize2, 1)); +#if 1 /* TODO: remove float code. */ + IF ( ( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC = (float *) malloc( bufferSize * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + set_zero( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC, bufferSize ); +#endif + IF ( ( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx = (Word16 *) malloc( bufferSize * sizeof( Word16 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + set16_fx( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx, 0, bufferSize ); + hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_size = bufferSize; + move16(); + + /* Interpolation between slots */ +#if 1 /* TODO: remove float code. */ + hMasa->hMasaLfeSynth->lfeGainPrev = 0.0f; + hMasa->hMasaLfeSynth->transportGainPrev = 1.0f; +#endif + hMasa->hMasaLfeSynth->lfeGainPrev_fx = 0; + move16(); + hMasa->hMasaLfeSynth->transportGainPrev_fx = ONE_IN_Q14; + move16(); + + tmp = BASOP_Util_Divide3232_Scale(output_Fs, FRAMES_PER_SEC * CLDFB_NO_COL_MAX, &tmp_e); + slot_size = shr(tmp, sub(15, tmp_e)); // Q0 + + FOR ( i = 0; i < slot_size; i++ ) + { + hMasa->hMasaLfeSynth->interpolator_fx[i] = div_s( add( i, 1 ), slot_size ); +#if 1 + /* TODO: remove float code */ + hMasa->hMasaLfeSynth->interpolator[i] = fix16_to_float(hMasa->hMasaLfeSynth->interpolator_fx[i], Q15); +#endif + } + } + ELSE IF ( st_ivas->hOutSetup.separateChannelEnabled && EQ_16( output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && EQ_16(st_ivas->hOutSetup.num_lfe, 0) ) + { + Word16 bufferSize; + + /* Delay buffer for syncing with DirAC rendering */ + bufferSize = NS2SA( output_Fs, IVAS_FB_DEC_DELAY_NS ); +#if 1 /* TODO: remove float code. */ + if ( ( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC = (float *) malloc( bufferSize * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + set_zero( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC, bufferSize ); +#endif + IF ( ( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx = (Word16 *) malloc( bufferSize * sizeof( Word16 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + set16_fx( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx, 0, bufferSize ); + hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_size = bufferSize; + move16(); + +#if 1 /* TODO: remove float code. */ + hMasa->hMasaLfeSynth->lfeSynthRingBuffer = NULL; + hMasa->hMasaLfeSynth->lfeSynthRingBuffer2 = NULL; + hMasa->hMasaLfeSynth->delayBuffer_syncLp = NULL; +#endif + hMasa->hMasaLfeSynth->lfeSynthRingBuffer_fx = NULL; + hMasa->hMasaLfeSynth->lfeSynthRingBuffer2_fx = NULL; + hMasa->hMasaLfeSynth->delayBuffer_syncLp_fx = NULL; + } + ELSE + { +#if 1 /* TODO: remove float code. */ + hMasa->hMasaLfeSynth->lfeSynthRingBuffer = NULL; + hMasa->hMasaLfeSynth->lfeSynthRingBuffer2 = NULL; + hMasa->hMasaLfeSynth->delayBuffer_syncLp = NULL; + hMasa->hMasaLfeSynth->delayBuffer_syncDirAC = NULL; +#endif + hMasa->hMasaLfeSynth->lfeSynthRingBuffer_fx = NULL; + hMasa->hMasaLfeSynth->lfeSynthRingBuffer2_fx = NULL; + hMasa->hMasaLfeSynth->delayBuffer_syncLp_fx = NULL; + hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx = NULL; + } + + return IVAS_ERR_OK; +} +#endif /*! r: Number of bits read */ static int16_t decode_lfe_to_total_energy_ratio( @@ -1346,6 +1927,148 @@ static int16_t decode_lfe_to_total_energy_ratio( return lfeBitsRead; } +#ifdef IVAS_FLOAT_FIXED +static Word16 decode_lfe_to_total_energy_ratio_fx( + MCMASA_LFE_SYNTH_DATA_HANDLE hMasaLfeSynth, /* i/o: McMASA LFE structure */ + UWord16 *bitstream, /* i : bitstream */ + Word16 *index, /* i/o: bitstream position */ + const Word32 ivas_total_brate /* i : total bitrate */ +) +{ + Word16 i; + Word16 lfeToTotalEnergyRatioIndices[3]; + Word16 VQBits; + Word16 log2LFEaverage_fx; + Word16 lfeToTotalEnergyRatioTemp_fx; + UWord16 byteBuffer; + Word16 lfeBitsRead; + + lfeBitsRead = 0; + move16(); + byteBuffer = bitstream[( *index )--]; + lfeBitsRead = add( lfeBitsRead, 1 ); + lfeToTotalEnergyRatioIndices[0] = byteBuffer; /* First LFE index */ + move16(); + + IF( EQ_32( ivas_total_brate, IVAS_13k2 ) ) /* 1-bit adaptive LFE gain quantizer at 13.2 kbps */ + { + lfeToTotalEnergyRatioTemp_fx = hMasaLfeSynth->lfeToTotalEnergyRatio_fx[3]; // Q14 /* Take memory from the last subframe */ + move16(); + IF( EQ_16( lfeToTotalEnergyRatioIndices[0], 1 ) ) + { + IF( EQ_16( hMasaLfeSynth->lfeGainPrevIndex, 1 ) ) + { + Word16 lfe_beta_theta = mult( MCMASA_LFE_THETA_Q14, MCMASA_LFE_BETA_Q15 ); // Q 14 + 15 - 15 = Q14 + lfeToTotalEnergyRatioTemp_fx = add( lfeToTotalEnergyRatioTemp_fx, lfe_beta_theta ); /* larger "bump-up" energy */ + } + ELSE + { + lfeToTotalEnergyRatioTemp_fx = add( lfeToTotalEnergyRatioTemp_fx, MCMASA_LFE_BETA_Q14 ); /* "bump-up" energy */ + } + } + ELSE + { + lfeToTotalEnergyRatioTemp_fx = mult( lfeToTotalEnergyRatioTemp_fx, MCMASA_LFE_ALPHA_Q15 ); // Q14 + } + IF( GT_16( lfeToTotalEnergyRatioTemp_fx, ONE_IN_Q14 ) ) + { + lfeToTotalEnergyRatioTemp_fx = ONE_IN_Q14; + move16(); + } + hMasaLfeSynth->lfeGainPrevIndex = lfeToTotalEnergyRatioIndices[0]; + move16(); + FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i] = lfeToTotalEnergyRatioTemp_fx; /* will always be less than 16384 */ + move16(); + } + } + ELSE /* Bitrates >= 16.4 kbps */ + { + IF( EQ_16( lfeToTotalEnergyRatioIndices[0], 0 ) ) + { + FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i] = 0; + move16(); + } + } + ELSE + { + byteBuffer = bitstream[( *index )--] << 2; + byteBuffer += bitstream[( *index )--] << 1; + byteBuffer += bitstream[( *index )--]; + lfeBitsRead = add( lfeBitsRead, 3 ); + lfeToTotalEnergyRatioIndices[1] = byteBuffer; /* Scalar index */ + move16(); + log2LFEaverage_fx = usdequant_fx( lfeToTotalEnergyRatioIndices[1], MCMASA_LFE_QLOW_Q12, MCMASA_LFE_DELTA_Q11 ); + + /* 16.4 kbps sends only scalar gain, above it VQ is used */ + IF( GE_32( ivas_total_brate, IVAS_24k4 ) ) + { + /* Depending on average (scalar) gain more bits are sent for VQ LFE gain */ + SWITCH( lfeToTotalEnergyRatioIndices[1] ) + { + case 0: + case 1: + VQBits = 0; + break; + case 2: + VQBits = 1; + break; + case 3: + VQBits = 2; + break; + case 4: + VQBits = 3; + break; + default: + VQBits = 4; + } + byteBuffer = 0; + move16(); + FOR( i = 0; i < VQBits; i++ ) + { + byteBuffer += bitstream[( *index )--] << ( sub( sub( VQBits, 1 ), i ) ); + lfeBitsRead = add( lfeBitsRead, 1 ); + } + lfeToTotalEnergyRatioIndices[2] = byteBuffer; /* VQ index */ + move16(); + } + + FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + Word16 tmp16, exp; + Word32 tmp32; + IF( EQ_32( ivas_total_brate, IVAS_16k4 ) ) + { + tmp32 = BASOP_util_Pow2( L_deposit_h( log2LFEaverage_fx ), 15 - Q12, &exp ); /* Q(31 - exp)*/ + tmp16 = round_fx( tmp32 ); /* Q(31-exp) -> Q(15 - exp) */ + hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i] = shr_sat( tmp16, sub( 1, exp ) ); /* should saturate. Q(15 - exp) - (1 - exp)->Q14 */ + move16(); + } + ELSE + { + tmp16 = shr( McMASA_LFEGain_vectors_fx_q13[4 * lfeToTotalEnergyRatioIndices[2] + i], 1 ); /* Q12 */ + tmp16 = add( log2LFEaverage_fx, tmp16 ); /* Q12 */ + tmp32 = BASOP_util_Pow2( L_deposit_h( tmp16 ), 15 - Q12, &exp ); /* Q(31 - exp) */ + tmp16 = round_fx( tmp32 ); /* Q(31-exp) -> Q(15 - exp) */ + hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i] = shr_sat( tmp16, sub( 1, exp ) ); /* should saturate. Q(15 - exp) - (1 - exp) -> Q14 */ + move16(); + } + + hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i] = s_min( hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i], ONE_IN_Q14 ); + move16(); + hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i] = s_max( hMasaLfeSynth->lfeToTotalEnergyRatio_fx[i], 0 ); + move16(); + } + } + } + + return lfeBitsRead; +} +#endif + /*-------------------------------------------------------------------* * ivas_masa_dec_reconfigure() @@ -1513,7 +2236,11 @@ ivas_error ivas_masa_dec_reconfigure( } } +#ifdef IVAS_FLOAT_FIXED + ivas_masa_set_elements_fx( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &tmp, &tmp, &tmp, st_ivas->ivas_format, st_ivas->ism_mode, ism_total_brate ); +#else ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &tmp, &tmp, &tmp, st_ivas->ivas_format, st_ivas->ism_mode, ism_total_brate ); +#endif if ( st_ivas->ivas_format == MASA_FORMAT ) { diff --git a/lib_dec/ivas_mcmasa_dec.c b/lib_dec/ivas_mcmasa_dec.c index 832572ded..63ad353a1 100644 --- a/lib_dec/ivas_mcmasa_dec.c +++ b/lib_dec/ivas_mcmasa_dec.c @@ -37,6 +37,7 @@ #include "ivas_prot_rend.h" #include "prot.h" #include "wmc_auto.h" +#include "ivas_prot_fx.h" /*------------------------------------------------------------------------- @@ -55,7 +56,11 @@ ivas_error ivas_mcmasa_dec_reconfig( ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; /* close the old MASA instance */ +#ifdef IVAS_FLOAT_FIXED + ivas_masa_dec_close_fx( &( st_ivas->hMasa ) ); +#else ivas_masa_dec_close( &( st_ivas->hMasa ) ); +#endif /* get new McMASA settings */ ivas_mcmasa_setNumTransportChannels( &( st_ivas->nchan_transport ), &( st_ivas->element_mode_init ), ivas_total_brate ); @@ -68,7 +73,11 @@ ivas_error ivas_mcmasa_dec_reconfig( ivas_output_init( &( st_ivas->hIntSetup ), st_ivas->intern_config ); ivas_mcmasa_set_separate_channel_mode( &( st_ivas->hIntSetup.separateChannelEnabled ), &( st_ivas->hIntSetup.separateChannelIndex ), ivas_total_brate ); +#ifdef IVAS_FLOAT_FIXED + if ( ( error = ivas_masa_dec_open_fx( st_ivas ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_masa_dec_open( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index 80d0d8829..5cbf4f943 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -42,6 +42,7 @@ #include "ivas_prot_rend.h" #include "ivas_rom_com.h" #include "wmc_auto.h" +#include "ivas_prot_fx.h" /*-----------------------------------------------------------------------* @@ -788,7 +789,11 @@ static ivas_error ivas_mc_dec_reconfig( } /* De-allocate McMasa-related handles */ +#ifdef IVAS_FLOAT_FIXED + ivas_masa_dec_close_fx( &( st_ivas->hMasa ) ); +#else ivas_masa_dec_close( &( st_ivas->hMasa ) ); +#endif ivas_qmetadata_close( &st_ivas->hQMetaData ); if ( st_ivas->hDirAC != NULL ) @@ -826,7 +831,11 @@ static ivas_error ivas_mc_dec_reconfig( ivas_ls_setup_conversion_close( &st_ivas->hLsSetUpConversion ); } +#ifdef IVAS_FLOAT_FIXED + ivas_masa_dec_close_fx( &( st_ivas->hMasa ) ); +#else ivas_masa_dec_close( &( st_ivas->hMasa ) ); +#endif ivas_qmetadata_close( &st_ivas->hQMetaData ); /* init LS conversion if the renderer type asks for it */ @@ -868,7 +877,11 @@ static ivas_error ivas_mc_dec_reconfig( } /* De-allocate McMasa-related handles */ +#ifdef IVAS_FLOAT_FIXED + ivas_masa_dec_close_fx( &( st_ivas->hMasa ) ); +#else ivas_masa_dec_close( &( st_ivas->hMasa ) ); +#endif ivas_qmetadata_close( &st_ivas->hQMetaData ); if ( st_ivas->hDirAC != NULL ) diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index 01e6d2b05..46faa1a15 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -964,6 +964,10 @@ typedef struct decoder_tc_buffer_structure { float *tc_buffer; /* the buffer itself */ float *tc[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; /* pointers into the buffer to the beginning of each tc */ // VE2SB: TBV +#ifdef IVAS_FLOAT_FIXED + Word16 *tc_buffer_fx; /* the buffer itself */ + Word16 *tc_fx[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; /* pointers into the buffer to the beginning of each tc */ // VE2SB: TBV +#endif TC_BUFFER_MODE tc_buffer_mode; /* mode of the buffer (no buffering, render buffering, out buffering) */ int16_t nchan_transport_jbm; /* number of TCs after TC decoding */ int16_t nchan_transport_internal; /* total number of TC buffer channels, can include e.g. TD decorr data */ diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 9740a14a1..3abaaf07a 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -356,32 +356,64 @@ typedef struct typedef struct ivas_mcmasa_lfe_synth_struct { float lfeToTotalEnergyRatio[MAX_PARAM_SPATIAL_SUBFRAMES]; +#ifdef IVAS_FLOAT_FIXED + Word16 lfeToTotalEnergyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES]; // Q14 +#endif int16_t lfeGainPrevIndex; float transportEneSmooth; float protoLfeEneSmooth; float targetEneLfeSmooth; float targetEneTransSmooth; +#ifdef IVAS_FLOAT_FIXED + Word16 transportEneSmooth_fx; + Word16 protoLfeEneSmooth_fx; + Word16 targetEneLfeSmooth_fx; + Word16 targetEneTransSmooth_fx; +#endif float *lfeSynthRingBuffer; +#ifdef IVAS_FLOAT_FIXED + Word16 *lfeSynthRingBuffer_fx; +#endif int16_t ringBufferLoPointer; int16_t ringBufferHiPointer; float lowpassSum; +#ifdef IVAS_FLOAT_FIXED + Word16 lowpassSum_fx; +#endif int16_t ringBufferSize; float *lfeSynthRingBuffer2; +#ifdef IVAS_FLOAT_FIXED + Word16 *lfeSynthRingBuffer2_fx; +#endif int16_t ringBufferLoPointer2; float lowpassSum2; +#ifdef IVAS_FLOAT_FIXED + Word16 lowpassSum2_fx; +#endif int16_t ringBufferSize2; float *delayBuffer_syncLp; +#ifdef IVAS_FLOAT_FIXED + Word16 *delayBuffer_syncLp_fx; +#endif int16_t delayBuffer_syncLp_size; float *delayBuffer_syncDirAC; +#ifdef IVAS_FLOAT_FIXED + Word16 *delayBuffer_syncDirAC_fx; +#endif int16_t delayBuffer_syncDirAC_size; float lfeGainPrev; float transportGainPrev; float interpolator[CLDFB_NO_CHANNELS_MAX]; +#ifdef IVAS_FLOAT_FIXED + Word16 lfeGainPrev_fx; + Word16 transportGainPrev_fx; /* Q14 */ + Word16 interpolator_fx[CLDFB_NO_CHANNELS_MAX]; /* Q15 */ +#endif } MCMASA_LFE_SYNTH_DATA, *MCMASA_LFE_SYNTH_DATA_HANDLE; -- GitLab