diff --git a/apps/decoder.c b/apps/decoder.c index 0d1c164360836052caa45f4049e12e0531de1e18..a4ae839ac65dcb9078693be53a44daa4ce530994 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -457,9 +457,14 @@ int main( *------------------------------------------------------------------------------------------*/ #ifdef SPLIT_REND_WITH_HEAD_ROT +#ifdef SPLIT_REND_LCLD_5MS + asked_frame_size = arg.renderFramesize; +#endif if ( arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { +#ifndef SPLIT_REND_LCLD_5MS asked_frame_size = arg.renderFramesize; +#endif if ( ( error = IVAS_DEC_EnableSplitRendering( hIvasDec ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nConfigure failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); @@ -472,11 +477,12 @@ int main( goto cleanup; } +#ifndef SPLIT_REND_LCLD_5MS if ( arg.renderFramesize != asked_frame_size ) { fprintf( stderr, "\nChanged render framesize, only 20ms are allowed for split rendering!\n" ); } - +#endif arg.enableHeadRotation = true; } #endif @@ -630,6 +636,7 @@ int main( } #ifdef SPLIT_REND_WITH_HEAD_ROT +#ifndef SPLIT_REND_LCLD_5MS if ( arg.renderFramesize == IVAS_RENDER_FRAMESIZE_5MS && ( renderConfig.split_rend_config.poseCorrectionMode == IVAS_SPLIT_REND_POSE_CORRECTION_MODE_NONE || renderConfig.split_rend_config.dof == 0 ) ) { @@ -647,7 +654,7 @@ int main( } #endif - +#endif if ( RenderConfigReader_read( renderConfigReader, arg.renderConfigFilename, &renderConfig ) != IVAS_ERR_OK ) { fprintf( stderr, "Failed to read renderer configuration from file %s\n\n", arg.renderConfigFilename ); @@ -660,6 +667,30 @@ int main( goto cleanup; } +#ifdef SPLIT_REND_LCLD_5MS +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( asked_frame_size != IVAS_RENDER_FRAMESIZE_20MS && ( renderConfig.split_rend_config.poseCorrectionMode == IVAS_SPLIT_REND_POSE_CORRECTION_MODE_NONE || + renderConfig.split_rend_config.dof == 0 ) ) + { + arg.renderFramesize = asked_frame_size; + } + else + { + arg.renderFramesize = IVAS_RENDER_FRAMESIZE_20MS; + } + + if ( ( error = IVAS_DEC_SetRenderFramesize( hIvasDec, arg.renderFramesize ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( arg.renderFramesize != asked_frame_size ) + { + fprintf( stderr, "\nChanged render framesize, only 20ms are allowed for non-0dof split rendering!\n" ); + } +#endif +#endif + if ( arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { if ( ( error = RenderConfigReader_getAcousticEnvironment( renderConfigReader, arg.acousticEnvironmentId, &renderConfig.roomAcoustics ) ) == IVAS_ERR_OK ) diff --git a/apps/renderer.c b/apps/renderer.c index e064e07f6bf959594ee44e5bc5b101a8611c9117..23058b1c00a982d10932f124a1d6c69162b550de 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -1903,7 +1903,8 @@ int main( #ifdef SPLIT_REND_WITH_HEAD_ROT for ( i = 0; i < args.inConfig.numBinBuses; ++i ) { - if ( splitBinNeedsNewFrame ) +#ifdef SPLIT_REND_LCLD_5MS + if ( numSamplesRead > 0 ) { if ( ( error = IVAS_REND_GetInputNumChannels( hIvasRend, splitBinIds[i], &numChannels ) ) != IVAS_ERR_OK ) { @@ -1917,7 +1918,24 @@ int main( fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); exit( -1 ); } + } +#endif + if ( splitBinNeedsNewFrame ) + { +#ifndef SPLIT_REND_LCLD_5MS + if ( ( error = IVAS_REND_GetInputNumChannels( hIvasRend, splitBinIds[i], &numChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.binBuses[i].inputChannelIndex, numChannels ); + if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, splitBinIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } +#endif if ( ( error = IVAS_REND_FeedSplitBinauralBitstream( hIvasRend, splitBinIds[i], &bitsBuffer ) ) != IVAS_ERR_OK ) { fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); @@ -2217,6 +2235,9 @@ cleanup: } split_rend_reader_writer_close( &hSplitRendFileReadWrite ); +#ifdef SPLIT_REND_LCLD_5MS + SplitRendBFIFileReader_close( &splitRendBFIReader ); +#endif #endif for ( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i ) @@ -2229,6 +2250,7 @@ cleanup: RotationFileReader_close( &headRotReader ); RotationFileReader_close( &externalOrientationFileReader ); RotationFileReader_close( &referenceRotReader ); + Vector3PairFileReader_close( &referenceVectorReader ); destroy_td_hrtf( hHrtfTD ); destroy_SetOfHRTF( hSetOfHRTF ); diff --git a/lib_com/options.h b/lib_com/options.h index e6eeefe4f40f8153471ab4acd2814404dd02682b..2841eb66b10c53c7b012e09e7ad7d963268f76ad 100755 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -134,6 +134,8 @@ /*#define SPLIT_REND_WITH_HEAD_ROT_DEBUG*/ /* debugging switch for split rendering */ /*#define SPLIT_POSE_CORRECTION_DEBUG*/ /* debugging switch for split rendering pose correction */ /*#define SPLIT_MD_CODING_DEBUG*/ /* debugging switch for split rendering metadata coding */ +/*#define DEBUG_WRITE_PREDICTORS*/ /* debugging switch for LCDL predictors*/ +/*#define DEBUG_WRITE_MS_PRED*/ /* debugging switch for LCLD mid-side prediction*/ #endif /* DEBUGGING */ @@ -179,6 +181,11 @@ #define NONBE_FIX_986_MC_BW_SWITCHING /* FhG: fix crash in bw and br switching with MC */ #define NONBE_FIX_975_JBM_USAN /* FhG: Fix issue #975, USAN in JBM decoding ad 13.2kbps */ #define NONBE_FIX_982_OMASA_DELAY_COMP_5MS /* FhG : issue #982 : 5ms and 20ms output different for OMASA */ + +#ifdef SPLIT_REND_WITH_HEAD_ROT +#define SPLIT_REND_LCLD_5MS /* Dlb: LCLD 5ms framing operation */ +#endif + /* ##################### End NON-BE switches ########################### */ /* ################## End DEVELOPMENT switches ######################### */ diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index b4c542fb892c4550129a8d92e65bbcee07f333c4..f8a863b49df41cf2dea90176de21856ebd83a9af 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -247,10 +247,17 @@ static ivas_error ivas_dec_init_split_rend( } } +#ifdef SPLIT_REND_LCLD_5MS + if ( ( error = ivas_split_rend_choose_default_codec( &st_ivas->hRenderConfig->split_rend_config.codec, &st_ivas->hRenderConfig->split_rend_config.codec_frame_size_ms, cldfb_in_flag, pcm_out_flag, (int16_t) st_ivas->hDecoderConfig->render_framesize ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_split_rend_choose_default_codec( &st_ivas->hRenderConfig->split_rend_config.codec, &st_ivas->hRenderConfig->split_rend_config.codec_frame_size_ms, cldfb_in_flag, pcm_out_flag ) ) != IVAS_ERR_OK ) { return error; } +#endif #ifdef SPLIT_REND_WITH_HEAD_ROT if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV && st_ivas->ivas_format == SBA_ISM_FORMAT ) @@ -259,8 +266,11 @@ static ivas_error ivas_dec_init_split_rend( } #endif +#ifdef SPLIT_REND_LCLD_5MS + error = ivas_split_renderer_open( &st_ivas->hSplitBinRend.splitrend, &st_ivas->hRenderConfig->split_rend_config, st_ivas->hDecoderConfig->output_Fs, cldfb_in_flag, pcm_out_flag, (int16_t) st_ivas->hDecoderConfig->render_framesize ); +#else error = ivas_split_renderer_open( &st_ivas->hSplitBinRend.splitrend, &st_ivas->hRenderConfig->split_rend_config, st_ivas->hDecoderConfig->output_Fs, cldfb_in_flag, pcm_out_flag, st_ivas->hDecoderConfig->render_framesize == IVAS_RENDER_FRAMESIZE_5MS ); - +#endif return error; } #endif @@ -2515,7 +2525,9 @@ void ivas_initialize_handles_dec( st_ivas->hSplitBinRend.hMultiBinCldfbData = NULL; st_ivas->hSplitBinRend.hSplitRendBits = NULL; st_ivas->hSplitBinRend.hCldfbDataOut = NULL; +#ifndef SPLIT_REND_LCLD_5MS st_ivas->hSplitBinRend.tdDataOut = NULL; +#endif st_ivas->hSplitBinRend.numTdSamplesPerChannelCached = 0; ivas_init_split_rend_handles( &st_ivas->hSplitBinRend.splitrend ); #endif @@ -2665,11 +2677,12 @@ void ivas_destroy_dec( free( st_ivas->hSplitBinRend.hCldfbDataOut ); st_ivas->hSplitBinRend.hCldfbDataOut = NULL; } - +#ifndef SPLIT_REND_LCLD_5MS if ( st_ivas->hSplitBinRend.tdDataOut != NULL ) { free( st_ivas->hSplitBinRend.tdDataOut ); } +#endif #endif /* Parametric binaural renderer handle */ diff --git a/lib_dec/ivas_mc_paramupmix_dec.c b/lib_dec/ivas_mc_paramupmix_dec.c index 30bc1de1eaa7b0f9827b6aee2c0801576bfd2f17..2ff77228f829165ce1238bcb4f7a8465b563ee4e 100644 --- a/lib_dec/ivas_mc_paramupmix_dec.c +++ b/lib_dec/ivas_mc_paramupmix_dec.c @@ -66,11 +66,15 @@ const int16_t MC_PARAMUPMIX_CHIDX2[MC_PARAMUPMIX_COMBINATIONS] = { 2, 3, 6, 7 }; static void ps_pred_process_sf( MC_PARAMUPMIX_DEC_HANDLE hMCParamUpmix, DECODER_TC_BUFFER_HANDLE hTcBuffer, float qmf_mod_re[JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float qmf_mod_im[JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float qmf_side_re[JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float qmf_side_im[JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float *param_interpol, const int16_t ch, const int16_t slots_rendered ); +#ifndef SPLIT_REND_LCLD_5MS #ifdef SPLIT_REND_WITH_HEAD_ROT static void ivas_mc_paramupmix_dec_sf( Decoder_Struct *st_ivas, float *output_f[MAX_OUTPUT_CHANNELS], const int16_t slot_index_start ); #else static void ivas_mc_paramupmix_dec_sf( Decoder_Struct *st_ivas, float *output_f[MAX_OUTPUT_CHANNELS] ); #endif +#else +static void ivas_mc_paramupmix_dec_sf( Decoder_Struct *st_ivas, float *output_f[MAX_OUTPUT_CHANNELS] ); +#endif static void ivas_param_upmix_dec_decorr_subframes( Decoder_Struct *st_ivas, const int16_t nSamplesForRendering ); @@ -230,8 +234,10 @@ void ivas_mc_paramupmix_dec_render( int16_t slots_to_render, first_sf, last_sf, subframe_idx; uint16_t slot_size, ch; float *output_f_local[MAX_OUTPUT_CHANNELS]; +#ifndef SPLIT_REND_LCLD_5MS #ifdef SPLIT_REND_WITH_HEAD_ROT int16_t slot_index_start; +#endif #endif MC_PARAMUPMIX_DEC_HANDLE hMCParamUpmix; @@ -267,18 +273,22 @@ void ivas_mc_paramupmix_dec_render( assert( slots_to_render == 0 ); #endif { - +#ifndef SPLIT_REND_LCLD_5MS #ifdef SPLIT_REND_WITH_HEAD_ROT slot_index_start = 0; +#endif #endif for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) { int16_t n_samples_sf = slot_size * st_ivas->hTcBuffer->subframe_nbslots[subframe_idx]; - +#ifndef SPLIT_REND_LCLD_5MS #ifdef SPLIT_REND_WITH_HEAD_ROT ivas_mc_paramupmix_dec_sf( st_ivas, output_f_local, slot_index_start ); slot_index_start += st_ivas->hTcBuffer->subframe_nbslots[subframe_idx]; +#else + ivas_mc_paramupmix_dec_sf( st_ivas, output_f_local ); +#endif #else ivas_mc_paramupmix_dec_sf( st_ivas, output_f_local ); #endif @@ -654,7 +664,7 @@ static void ps_pred_process_sf( return; } - +#ifndef SPLIT_REND_LCLD_5MS static void ivas_mc_paramupmix_dec_sf( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ #ifdef SPLIT_REND_WITH_HEAD_ROT @@ -664,6 +674,12 @@ static void ivas_mc_paramupmix_dec_sf( float *output_f[MAX_OUTPUT_CHANNELS] /* i/o: synthesized core-coder transport channels */ #endif ) +#else +static void ivas_mc_paramupmix_dec_sf( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + float *output_f[MAX_OUTPUT_CHANNELS] /* i/o: synthesized core-coder transport channels */ +) +#endif { int16_t i, ch, slot_idx, k; float *pPcm_temp[MC_PARAMUPMIX_COMBINATIONS * 2]; /* decorrelated and undecorrelated*/ @@ -678,6 +694,9 @@ static void ivas_mc_paramupmix_dec_sf( #ifdef SPLIT_REND_WITH_HEAD_ROT float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; +#ifdef SPLIT_REND_LCLD_5MS + int16_t slot_index_start; +#endif #else float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; @@ -687,6 +706,11 @@ static void ivas_mc_paramupmix_dec_sf( assert( hMCParamUpmix ); push_wmops( "ivas_mc_paramupmix_dec_sf" ); +#ifdef SPLIT_REND_WITH_HEAD_ROT +#ifdef SPLIT_REND_LCLD_5MS + slot_index_start = st_ivas->hTcBuffer->slots_rendered; +#endif +#endif for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ ) { pPcm_temp[2 * i] = output_f[i + 4]; /* un-decorrelated */ diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index cc9a8850beecc4607805182dedd71de6fd35114e..f1f5a7eaa83f57e215e0a776fb4f28f71e92eded 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -979,7 +979,9 @@ typedef struct IVAS_SPLIT_REND_BITS_HANDLE hSplitRendBits; /*scratch buffer for frame by frame processing*/ SPLIT_REND_WRAPPER splitrend; IVAS_DEC_SPLIT_REND_CLDFB_OUT_DATA_HANDLE hCldfbDataOut; /*buffer to store cldfb data before binauralization*/ - float *tdDataOut; /*buffer to store TD data before binauralization*/ +#ifndef SPLIT_REND_LCLD_5MS + float *tdDataOut; /*buffer to store TD data before binauralization*/ +#endif int16_t numTdSamplesPerChannelCached; } IVAS_DEC_SPLIT_REND_WRAPPER; diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 94468ef6bf0edbd40d43e7eb8680f311fd50f78d..d8e7300c7a06064462493ebb006d575e5cf8bcfe 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -1037,14 +1037,21 @@ ivas_error IVAS_DEC_GetSplitBinauralBitstream( Decoder_Struct *st_ivas; AUDIO_CONFIG output_config; int32_t output_Fs; +#ifndef SPLIT_REND_LCLD_5MS float *writePtr; float *readPtr, *readEnd; +#endif float *pOutput[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES]; float output[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES][L_FRAME48k]; float pcmBuf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES * L_FRAME48k]; +#ifdef SPLIT_REND_LCLD_5MS + float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; +#else int16_t numSamplesPerChannelCacheSize; - int16_t numSamplesPerChannelToDecode; int16_t numSamplesPerChannelToSplitEncode; +#endif + int16_t numSamplesPerChannelToDecode; int16_t i, j; ivas_error error; IVAS_DEC_SPLIT_REND_WRAPPER *hSplitBinRend; @@ -1052,6 +1059,9 @@ ivas_error IVAS_DEC_GetSplitBinauralBitstream( int16_t pcm_out_flag; int16_t td_input; int16_t numPoses; +#ifdef SPLIT_REND_LCLD_5MS + int16_t slots_rendered, slots_rendered_new; +#endif int16_t ro_md_flag; error = IVAS_ERR_OK; @@ -1070,6 +1080,15 @@ ivas_error IVAS_DEC_GetSplitBinauralBitstream( numPoses = hSplitBinRend->splitrend.multiBinPoseData.num_poses; +#ifdef SPLIT_REND_LCLD_5MS + if ( st_ivas->hDecoderConfig->render_framesize != IVAS_RENDER_FRAMESIZE_20MS && + ( hIvasDec->st_ivas->hRenderConfig->split_rend_config.poseCorrectionMode == IVAS_SPLIT_REND_POSE_CORRECTION_MODE_NONE || + hIvasDec->st_ivas->hRenderConfig->split_rend_config.dof == 0 ) ) + { + numSamplesPerChannelToDecode = (int16_t) ( output_Fs / FRAMES_PER_SEC / MAX_PARAM_SPATIAL_SUBFRAMES ); + numSamplesPerChannelToDecode *= (int16_t) st_ivas->hDecoderConfig->render_framesize; + } +#else if ( st_ivas->hDecoderConfig->render_framesize == IVAS_RENDER_FRAMESIZE_5MS && hIvasDec->st_ivas->hRenderConfig->split_rend_config.codec == IVAS_SPLIT_REND_CODEC_LC3PLUS && ( hIvasDec->st_ivas->hRenderConfig->split_rend_config.poseCorrectionMode == IVAS_SPLIT_REND_POSE_CORRECTION_MODE_NONE || hIvasDec->st_ivas->hRenderConfig->split_rend_config.dof == 0 ) ) @@ -1091,12 +1110,29 @@ ivas_error IVAS_DEC_GetSplitBinauralBitstream( numSamplesPerChannelToSplitEncode = (int16_t) ( output_Fs / FRAMES_PER_SEC ); numSamplesPerChannelCacheSize = 0; } - +#endif if ( output_config != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && output_config != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { return IVAS_ERR_WRONG_PARAMS; } +#ifdef SPLIT_REND_LCLD_5MS + if ( st_ivas->hTcBuffer == NULL || hIvasDec->hasBeenFedFrame ) + { + slots_rendered = 0; + } + else + { + slots_rendered = st_ivas->hTcBuffer->n_samples_rendered / st_ivas->hTcBuffer->n_samples_granularity; + } + + + /* Decode and render */ + if ( ( error = IVAS_DEC_GetSamples( hIvasDec, numSamplesPerChannelToDecode, IVAS_DEC_PCM_FLOAT, pcmBuf, nOutSamples, needNewFrame ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( numSamplesPerChannelToDecode == numSamplesPerChannelToSplitEncode || hSplitBinRend->numTdSamplesPerChannelCached == 0 ) { /* Decode and render */ @@ -1137,9 +1173,14 @@ ivas_error IVAS_DEC_GetSplitBinauralBitstream( } hSplitBinRend->numTdSamplesPerChannelCached -= numSamplesPerChannelToSplitEncode; } +#endif - /* change buffer layout */ +/* change buffer layout */ +#ifdef SPLIT_REND_LCLD_5MS + for ( i = 0; i < numSamplesPerChannelToDecode; ++i ) +#else for ( i = 0; i < numSamplesPerChannelToSplitEncode; ++i ) +#endif { for ( j = 0; j < BINAURAL_CHANNELS * numPoses; ++j ) { @@ -1151,6 +1192,26 @@ ivas_error IVAS_DEC_GetSplitBinauralBitstream( pOutput[i] = output[i]; } +#ifdef SPLIT_REND_LCLD_5MS + if ( st_ivas->hTcBuffer == NULL ) + { + slots_rendered_new = 0; + } + else + { + slots_rendered_new = st_ivas->hTcBuffer->n_samples_rendered / st_ivas->hTcBuffer->n_samples_granularity; + } + + for ( i = 0; i < BINAURAL_CHANNELS * numPoses; ++i ) + { + for ( j = slots_rendered; j < slots_rendered_new; ++j ) + { + mvr2r( hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[i][j], Cldfb_RealBuffer_Binaural[i][j - slots_rendered], CLDFB_NO_CHANNELS_MAX ); + mvr2r( hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[i][j], Cldfb_ImagBuffer_Binaural[i][j - slots_rendered], CLDFB_NO_CHANNELS_MAX ); + } + } +#endif + max_band = (int16_t) ( ( BINAURAL_MAXBANDS * output_Fs ) / 48000 ); pcm_out_flag = ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0; td_input = st_ivas->renderer_type != RENDERER_BINAURAL_FASTCONV && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC; @@ -1170,9 +1231,15 @@ ivas_error IVAS_DEC_GetSplitBinauralBitstream( st_ivas->hRenderConfig->split_rend_config.codec, st_ivas->hRenderConfig->split_rend_config.codec_frame_size_ms, hSplitBinRend->hSplitRendBits, +#ifdef SPLIT_REND_LCLD_5MS + Cldfb_RealBuffer_Binaural, + Cldfb_ImagBuffer_Binaural, +#else hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural, hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural, +#endif max_band, pOutput, 1, !td_input, pcm_out_flag, ro_md_flag ) ) != IVAS_ERR_OK ) + { return error; } @@ -1183,18 +1250,30 @@ ivas_error IVAS_DEC_GetSplitBinauralBitstream( if ( st_ivas->hDecoderConfig->render_framesize == IVAS_RENDER_FRAMESIZE_5MS ) { #ifndef DISABLE_LIMITER +#ifdef SPLIT_REND_LCLD_5MS + ivas_limiter_dec( st_ivas->hLimiter, pOutput, st_ivas->hDecoderConfig->nchan_out, numSamplesPerChannelToDecode, st_ivas->BER_detect ); +#else ivas_limiter_dec( st_ivas->hLimiter, pOutput, st_ivas->hDecoderConfig->nchan_out, numSamplesPerChannelToSplitEncode, st_ivas->BER_detect ); +#endif #endif } else { +#ifdef SPLIT_REND_LCLD_5MS + ivas_limiter_dec( st_ivas->hLimiter, pOutput, st_ivas->hDecoderConfig->nchan_out, numSamplesPerChannelToDecode, st_ivas->BER_detect ); +#else ivas_limiter_dec( st_ivas->hLimiter, pOutput, st_ivas->hDecoderConfig->nchan_out, numSamplesPerChannelToSplitEncode, st_ivas->BER_detect ); +#endif } #ifdef DEBUGGING st_ivas->noClipping += #endif - ivas_syn_output( pOutput, numSamplesPerChannelToSplitEncode, st_ivas->hDecoderConfig->nchan_out, (int16_t *) pcmBuf_out ); +#ifdef SPLIT_REND_LCLD_5MS + ivas_syn_output( pOutput, numSamplesPerChannelToDecode, st_ivas->hDecoderConfig->nchan_out, (int16_t *) pcmBuf_out ); +#else + ivas_syn_output( pOutput, numSamplesPerChannelToSplitEncode, st_ivas->hDecoderConfig->nchan_out, (int16_t *) pcmBuf_out ); +#endif } free( st_ivas->hSplitBinRend.hMultiBinCldfbData ); @@ -3634,6 +3713,13 @@ ivas_error IVAS_DEC_GetSplitRendBits( splitRendBits->pose_correction = hIvasDec->st_ivas->hSplitBinRend.hSplitRendBits->pose_correction; splitRendBits->codec_frame_size_ms = hIvasDec->st_ivas->hSplitBinRend.hSplitRendBits->codec_frame_size_ms; +#ifdef SPLIT_REND_LCLD_5MS + /* data consumed, free it */ + free( hIvasDec->st_ivas->hSplitBinRend.hSplitRendBits ); + hIvasDec->st_ivas->hSplitBinRend.hSplitRendBits = NULL; +#endif + + return IVAS_ERR_OK; } diff --git a/lib_rend/ivas_MSPred.c b/lib_rend/ivas_MSPred.c index 209b106853518a9dd732b7b7273410d7de6d7d0d..3986526c45b596a094f44a1f3cb0583295ab90b0 100644 --- a/lib_rend/ivas_MSPred.c +++ b/lib_rend/ivas_MSPred.c @@ -61,15 +61,6 @@ static int32_t _round( int32_t quantPhase( float phase ) { -#ifdef SIMPLE_PHASE - int32_t phaseQ; - if ( phase < 0.0f ) - { - phase += 2.0f * _PI_; - } - phaseQ = _round( phase * SIMPLE_PHASE_QUANT_FACTOR ); - phaseQ = ( phaseQ > SIMPLE_PHASE_MAX_VAL ? SIMPLE_PHASE_MIN_VAL : phaseQ ); -#else int32_t phaseQ; phaseQ = _round( phase * PHASE_QUANT_FACTOR ); @@ -77,83 +68,9 @@ int32_t quantPhase( { phaseQ = PHASE_MIN_VAL; } -#endif return phaseQ; } -#ifdef SIMPLE_PHASE -/*-------------------------------------------------------------------* - * Function rot_pm_pi() - * - * - *-------------------------------------------------------------------*/ - -void rot_pm_pi( - float *pr, - float *pi ) -{ - /* (-1 + j0) */ - *pr = -( *pr ); - *pi = -( *pi ); - - return; -} - - -/*-------------------------------------------------------------------* - * Function ApplyInversePredictros() - * - * - *-------------------------------------------------------------------*/ - -void rot_p_pi_2( - float *pr, - float *pi ) -{ - /* (0 + j) */ - float r = *pr; - - *pr = -( *pi ); - *pi = r; - - return; -} - -/*-------------------------------------------------------------------* - * Function rot_zero() - * - * - *-------------------------------------------------------------------*/ - -void rot_zero( - float *pr, - float *pi ) -{ - *pr = *pr; - *pi = *pi; - - return; -} - -/*-------------------------------------------------------------------* - * Function rot_m_pi_2() - * - * - *-------------------------------------------------------------------*/ - -void rot_m_pi_2( - float *pr, - float *pi ) -{ - /* (0 - j) */ - float r = *pr; - - *pr = *pi; - *pi = -r; - - return; -} -#endif /*-------------------------------------------------------------------* * Function cplxmult() @@ -233,11 +150,7 @@ int32_t quantPred( float dequantPhase( const int32_t phaseQ ) { -#ifdef SIMPLE_PHASE - return (float) phaseQ / SIMPLE_PHASE_QUANT_FACTOR; -#else return (float) phaseQ / PHASE_QUANT_FACTOR; -#endif } @@ -468,9 +381,7 @@ int32_t CountMSBits( /* Differential Coding of Phase Data*/ PrepEncode( piPhaseCopy, piMSFlags, iNumBands ); PrepEncode( piPredCopy, piMSFlags, iNumBands ); -#ifndef SIMPLE_PHASE EncodePhase( piPhaseCopy, iNumMSBands, PHASE_DIFF_DIM ); -#endif EncodePredCoef( piPredCopy, iNumMSBands ); iBitsWritten += 1; /* iMSPredAll */ @@ -486,16 +397,12 @@ int32_t CountMSBits( iBitsWritten++; /*anyNonZero Phase*/ if ( anyNonZero ) { -#ifdef SIMPLE_PHASE - iBitsWritten += iNumMSBands * SIMPLE_PHASE_BITS; -#else iBitsWritten += PHASE_BAND0_BITS; for ( b = 1; b < iNumMSBands; b++ ) { int32_t tabIdx = piPhaseCopy[b] - ENV_DELTA_MIN; iBitsWritten += c_aaiRMSEnvHuffEnc[tabIdx][0]; } -#endif } anyNonZero = 0; /* prediction */ for ( b = 0; b < iNumMSBands; b++ ) diff --git a/lib_rend/ivas_PredDecoder.c b/lib_rend/ivas_PredDecoder.c index 6aaccbb091bdf6f7f884f585ef0bef64067c8ee8..1fe552f3fae10051d4dd040c63aa3d14d46a819f 100644 --- a/lib_rend/ivas_PredDecoder.c +++ b/lib_rend/ivas_PredDecoder.c @@ -40,7 +40,6 @@ #include "ivas_lcld_rom_tables.h" #include "wmc_auto.h" - /*-------------------------------------------------------------------* * Function CreatePredictionDecoder() * @@ -53,6 +52,9 @@ ivas_error CreatePredictionDecoder( const int32_t iNumBlocks ) { int16_t n; +#ifdef SPLIT_REND_LCLD_5MS + int16_t m; +#endif PredictionDecoder *psPredictionDecoder = NULL; if ( ( psPredictionDecoder = (PredictionDecoder *) malloc( sizeof( PredictionDecoder ) ) ) == NULL ) @@ -62,11 +64,15 @@ ivas_error CreatePredictionDecoder( psPredictionDecoder->iChannels = iChannels; psPredictionDecoder->iNumBlocks = iNumBlocks; - +#ifdef SPLIT_REND_LCLD_5MS + psPredictionDecoder->iNumSubSets = LCLD_BLOCKS_PER_FRAME / psPredictionDecoder->iNumBlocks; + psPredictionDecoder->iSubSetId = 0; +#endif if ( ( psPredictionDecoder->piPredChanEnable = (int32_t *) malloc( sizeof( int32_t ) * iChannels ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); } +#ifndef SPLIT_REND_LCLD_5MS if ( ( psPredictionDecoder->piNumPredBands = (int32_t *) malloc( sizeof( int32_t ) * iChannels ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); @@ -76,6 +82,7 @@ ivas_error CreatePredictionDecoder( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); } +#endif if ( ( psPredictionDecoder->ppiPredBandEnable = (int32_t **) malloc( sizeof( int32_t * ) * iChannels ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); @@ -96,17 +103,37 @@ ivas_error CreatePredictionDecoder( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); } +#ifdef SPLIT_REND_LCLD_5MS + if ( ( psPredictionDecoder->ppfPredStateReal = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } + if ( ( psPredictionDecoder->ppfPredStateImag = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } +#endif for ( n = 0; n < psPredictionDecoder->iChannels; n++ ) { +#ifdef SPLIT_REND_LCLD_5MS + psPredictionDecoder->piPredChanEnable[n] = 0; +#else if ( ( psPredictionDecoder->ppfEstPredGain[n] = (float *) malloc( sizeof( float ) * LCLD_BANDS ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); } - if ( ( psPredictionDecoder->ppiPredBandEnable[n] = (int32_t *) malloc( sizeof( int32_t ) * LCLD_BANDS ) ) == NULL ) +#endif + if ( ( psPredictionDecoder->ppiPredBandEnable[n] = (int32_t *) malloc( LCLD_BANDS * sizeof( int32_t ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); } +#ifdef SPLIT_REND_LCLD_5MS + for ( m = 0; m < LCLD_BANDS; m++ ) + { + psPredictionDecoder->ppiPredBandEnable[n][m] = 0; + } +#endif if ( ( psPredictionDecoder->ppfA1Real[n] = (float *) malloc( sizeof( float ) * LCLD_BANDS ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); @@ -123,6 +150,23 @@ ivas_error CreatePredictionDecoder( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); } +#ifdef SPLIT_REND_LCLD_5MS + if ( ( psPredictionDecoder->ppfPredStateReal[n] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionDecoder Module \n" ) ); + } + if ( ( psPredictionDecoder->ppfPredStateImag[n] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionDecoder Module \n" ) ); + } +#ifdef SPLIT_REND_LCLD_5MS + for ( m = 0; m < LCLD_BANDS; m++ ) + { + psPredictionDecoder->ppfPredStateReal[n][m] = 0; + psPredictionDecoder->ppfPredStateImag[n][m] = 0; + } +#endif +#endif } /* pre-define these tables? */ @@ -161,21 +205,33 @@ void DeletePredictionDecoder( for ( n = 0; n < psPredictionDecoder->iChannels; n++ ) { +#ifndef SPLIT_REND_LCLD_5MS free( psPredictionDecoder->ppfEstPredGain[n] ); +#endif free( psPredictionDecoder->ppiPredBandEnable[n] ); free( psPredictionDecoder->ppfA1Real[n] ); free( psPredictionDecoder->ppfA1Imag[n] ); free( psPredictionDecoder->ppiA1Mag[n] ); free( psPredictionDecoder->ppiA1Phase[n] ); +#ifdef SPLIT_REND_LCLD_5MS + free( psPredictionDecoder->ppfPredStateReal[n] ); + free( psPredictionDecoder->ppfPredStateImag[n] ); +#endif } free( psPredictionDecoder->piPredChanEnable ); +#ifndef SPLIT_REND_LCLD_5MS free( psPredictionDecoder->piNumPredBands ); free( psPredictionDecoder->ppfEstPredGain ); +#endif free( psPredictionDecoder->ppiPredBandEnable ); free( psPredictionDecoder->ppfA1Real ); free( psPredictionDecoder->ppfA1Imag ); free( psPredictionDecoder->ppiA1Mag ); free( psPredictionDecoder->ppiA1Phase ); +#ifdef SPLIT_REND_LCLD_5MS + free( psPredictionDecoder->ppfPredStateReal ); + free( psPredictionDecoder->ppfPredStateImag ); +#endif free( psPredictionDecoder ); psPredictionDecoder = NULL; @@ -183,7 +239,7 @@ void DeletePredictionDecoder( return; } - +#ifndef SPLIT_REND_LCLD_5MS #define USE_TABLE_LOOKUP /*-------------------------------------------------------------------* * Function ReadPredictors() @@ -286,7 +342,105 @@ int32_t ReadPredictors( return iBitsRead; } +#else +/*-------------------------------------------------------------------* + * Function ReadPredictors() + * + * + *-------------------------------------------------------------------*/ + +int32_t ReadPredictors( + PredictionDecoder *psPredictionDecoder, + IVAS_SPLIT_REND_BITS_HANDLE pBits ) +{ + int16_t iBitsRead = 0; + int32_t c; + int32_t b; + int16_t iNumPredBandBits = 6; + const int16_t iSubSetBits = ( LCLD_MAX_NUM_PRED_SUBSETS > 4 ? 3 : 2 ); + + psPredictionDecoder->iNumSubSets = ivas_split_rend_bitstream_read_int32( pBits, iSubSetBits ) + 1; + iBitsRead += iSubSetBits; + + if ( psPredictionDecoder->iNumSubSets > 1 ) + { + psPredictionDecoder->iSubSetId = ivas_split_rend_bitstream_read_int32( pBits, iSubSetBits ); + iBitsRead += iSubSetBits; + iNumPredBandBits = ( psPredictionDecoder->iNumSubSets >= 4 ? 4 : 5 ); + } + else + { + psPredictionDecoder->iSubSetId = 0; + } + for ( c = 0; c < psPredictionDecoder->iChannels; c++ ) + { + psPredictionDecoder->piPredChanEnable[c] = ivas_split_rend_bitstream_read_int32( pBits, psPredictionDecoder->iNumSubSets ); + iBitsRead += (int16_t) psPredictionDecoder->iNumSubSets; + + if ( get_bit( psPredictionDecoder->piPredChanEnable[c], psPredictionDecoder->iSubSetId ) ) + { + int32_t b0 = psPredictionDecoder->iSubSetId; + int32_t bstep = psPredictionDecoder->iNumSubSets; + int32_t iNumPredBands; + + for ( b = b0; b < LCLD_BANDS; b += bstep ) + { + psPredictionDecoder->ppiPredBandEnable[c][b] = 0; + } + iNumPredBands = ivas_split_rend_bitstream_read_int32( pBits, iNumPredBandBits ); + iBitsRead += iNumPredBandBits; + iNumPredBands = iNumPredBands * psPredictionDecoder->iNumSubSets + b0; + + for ( b = b0; b < iNumPredBands; b += bstep ) + { + psPredictionDecoder->ppiPredBandEnable[c][b] = ivas_split_rend_bitstream_read_int32( pBits, 1 ); + iBitsRead += 1; + + if ( psPredictionDecoder->ppiPredBandEnable[c][b] == 1 ) + { + int32_t iA1Mag; + int32_t iA1Phase; + float fA1Real; + float fA1Imag; + iA1Mag = ivas_split_rend_bitstream_read_int32( pBits, PRED_QUNAT_FILTER_MAG_BITS ); + iBitsRead += PRED_QUNAT_FILTER_MAG_BITS; + iA1Phase = ivas_split_rend_bitstream_read_int32( pBits, PRED_QUANT_FILTER_PHASE_BITS ); + iBitsRead += PRED_QUANT_FILTER_PHASE_BITS; + + psPredictionDecoder->ppiA1Mag[c][b] = iA1Mag; + psPredictionDecoder->ppiA1Phase[c][b] = iA1Phase + PRED_QUANT_FILTER_PHASE_MIN; + + fA1Real = psPredictionDecoder->pfMagLUT[iA1Mag] * psPredictionDecoder->pfP2RRealLUT[iA1Phase]; + fA1Imag = psPredictionDecoder->pfMagLUT[iA1Mag] * psPredictionDecoder->pfP2RImagLUT[iA1Phase]; + + psPredictionDecoder->ppfA1Real[c][b] = fA1Real; + psPredictionDecoder->ppfA1Imag[c][b] = fA1Imag; + } + } + } + } + + /* disable any inactive prediction bands */ + for ( c = 0; c < psPredictionDecoder->iChannels; c++ ) + { + int32_t set; + for ( set = 0; set < psPredictionDecoder->iNumSubSets; set++ ) + { + if ( !get_bit( psPredictionDecoder->piPredChanEnable[c], set ) ) + { + for ( b = set; b < LCLD_BANDS; b += psPredictionDecoder->iNumSubSets ) + { + psPredictionDecoder->ppiPredBandEnable[c][b] = 0; + } + } + } + } + return iBitsRead; +} +#endif + +#ifndef SPLIT_REND_LCLD_5MS /*-------------------------------------------------------------------* * Function ApplyInversePredictros() * @@ -332,4 +486,65 @@ void ApplyInversePredictros( return; } +#else +/*-------------------------------------------------------------------* + * Function ApplyInversePredictors() + * + * + *-------------------------------------------------------------------*/ + +void ApplyInversePredictors( + PredictionDecoder *psPredictionDecoder, + float ***pppfReal, + float ***pppfImag ) +{ + int32_t c; + for ( c = 0; c < psPredictionDecoder->iChannels; c++ ) + { + if ( psPredictionDecoder->piPredChanEnable[c] > 0 ) + { + int32_t b; + for ( b = 0; b < LCLD_BANDS; b++ ) + { + if ( psPredictionDecoder->ppiPredBandEnable[c][b] == 1 ) + { + int32_t n; + float fA1Real; + float fA1Imag; + float fPrevReal = 0.0f; + float fPrevImag = 0.0f; + int32_t iSubset = b % psPredictionDecoder->iNumSubSets; + + if ( iSubset != psPredictionDecoder->iSubSetId ) + { + fPrevReal = psPredictionDecoder->ppfPredStateReal[c][b]; + fPrevImag = psPredictionDecoder->ppfPredStateImag[c][b]; + } + + fA1Real = psPredictionDecoder->ppfA1Real[c][b]; + fA1Imag = psPredictionDecoder->ppfA1Imag[c][b]; + for ( n = 0; n < psPredictionDecoder->iNumBlocks; n++ ) + { + float fReal; + float fImag; + + fReal = pppfReal[c][n][b] - fA1Real * fPrevReal + fA1Imag * fPrevImag; + fImag = pppfImag[c][n][b] - fA1Real * fPrevImag - fA1Imag * fPrevReal; + + pppfReal[c][n][b] = fReal; + pppfImag[c][n][b] = fImag; + + fPrevReal = fReal; + fPrevImag = fImag; + } + psPredictionDecoder->ppfPredStateReal[c][b] = fPrevReal; + psPredictionDecoder->ppfPredStateImag[c][b] = fPrevImag; + } + } + } + } + + return; +} +#endif #endif diff --git a/lib_rend/ivas_PredEncoder.c b/lib_rend/ivas_PredEncoder.c index 0a61685105fc869498337e502e3834225b29f1a6..2f7cfd3900cb03948ddb3175858f0f3962efabfc 100644 --- a/lib_rend/ivas_PredEncoder.c +++ b/lib_rend/ivas_PredEncoder.c @@ -40,6 +40,33 @@ #include "ivas_prot_rend.h" #include "wmc_auto.h" +#ifdef SPLIT_REND_LCLD_5MS + +/*-------------------------------------------------------------------* + * Function activate_bit() + * + * + *-------------------------------------------------------------------*/ +static void activate_bit( + int32_t *state, + const int32_t bit_id ) +{ + ( *state ) |= ( 1 << bit_id ); +} + +/*-------------------------------------------------------------------* + * Function deactivate_bit() + * + * + *-------------------------------------------------------------------*/ + +static void deactivate_bit( + int32_t *state, + const int32_t bit_id ) +{ + ( *state ) &= ( ~( 1 << bit_id ) ); +} +#endif /*-------------------------------------------------------------------* * Function CreatePredictionEncoder() @@ -47,10 +74,19 @@ * *-------------------------------------------------------------------*/ +#ifdef SPLIT_REND_LCLD_5MS +ivas_error CreatePredictionEncoder( + PredictionEncoder **psPredictionEncoder_out, + const int32_t iChannels, + const int32_t iNumBlocks, + const int32_t iNumSubSets, + const int32_t iMaxNumPredBands ) +#else ivas_error CreatePredictionEncoder( PredictionEncoder **psPredictionEncoder_out, const int32_t iChannels, const int32_t iNumBlocks ) +#endif { int32_t k, n; PredictionEncoder *psPredictionEncoder = NULL; @@ -62,15 +98,33 @@ ivas_error CreatePredictionEncoder( psPredictionEncoder->iChannels = iChannels; psPredictionEncoder->iNumBlocks = iNumBlocks; - +#ifdef SPLIT_REND_LCLD_5MS + psPredictionEncoder->iSubSetId = 0; + psPredictionEncoder->iMaxNumPredBands = iMaxNumPredBands; + psPredictionEncoder->iNumSubSets = iNumSubSets; + if ( ( psPredictionEncoder->pfWindow = (float *) malloc( sizeof( float ) * LCLD_PRED_WIN_LEN ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } +#else if ( ( psPredictionEncoder->pfWindow = (float *) malloc( sizeof( float ) * iNumBlocks ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); } +#endif + +#ifdef SPLIT_REND_LCLD_5MS + for ( n = 0; n < LCLD_PRED_WIN_LEN; n++ ) + { + psPredictionEncoder->pfWindow[n] = 0.54f - 0.46f * cosf( 2.0f * M_PI * ( (float) n + 0.5f ) / (float) LCLD_PRED_WIN_LEN ); + } +#else for ( n = 0; n < iNumBlocks; n++ ) { psPredictionEncoder->pfWindow[n] = 0.54f - 0.46f * cosf( 2.0f * M_PI * ( (float) n + 0.5f ) / (float) iNumBlocks ); } +#endif + if ( ( psPredictionEncoder->piPredChanEnable = (int32_t *) malloc( sizeof( int32_t ) * iChannels ) ) == NULL ) { @@ -87,6 +141,60 @@ ivas_error CreatePredictionEncoder( psPredictionEncoder->piNumPredBands[n] = 40; // Will need to be set correctly } +#ifdef SPLIT_REND_LCLD_5MS + if ( ( psPredictionEncoder->ppiPredBandEnable = (int32_t **) malloc( sizeof( int32_t * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfA1Real = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfA1Imag = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppiA1Mag = (int32_t **) malloc( sizeof( int32_t * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppiA1Phase = (int32_t **) malloc( sizeof( int32_t * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->pppfInpBufReal = (float ***) malloc( sizeof( float ** ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->pppfInpBufImag = (float ***) malloc( sizeof( float ** ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfInpPrevReal = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfInpPrevImag = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfPredStateReal = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfPredStateImag = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfPredStateRealTmp = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfPredStateImagTmp = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } +#else if ( ( psPredictionEncoder->ppfEstPredGain = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); @@ -116,8 +224,11 @@ ivas_error CreatePredictionEncoder( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); } +#endif + for ( n = 0; n < psPredictionEncoder->iChannels; n++ ) { +#ifndef SPLIT_REND_LCLD_5MS if ( ( psPredictionEncoder->ppfEstPredGain[n] = (float *) malloc( sizeof( float ) * LCLD_BANDS ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); @@ -126,6 +237,7 @@ ivas_error CreatePredictionEncoder( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); } +#endif if ( ( psPredictionEncoder->ppiPredBandEnable[n] = (int32_t *) malloc( sizeof( int32_t ) * LCLD_BANDS ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); @@ -146,11 +258,72 @@ ivas_error CreatePredictionEncoder( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); } +#ifdef SPLIT_REND_LCLD_5MS + if ( ( psPredictionEncoder->pppfInpBufReal[n] = (float **) malloc( sizeof( float * ) * LCLD_PRED_WIN_LEN ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->pppfInpBufImag[n] = (float **) malloc( sizeof( float * ) * LCLD_PRED_WIN_LEN ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + for ( k = 0; k < LCLD_PRED_WIN_LEN; k++ ) + { + if ( ( psPredictionEncoder->pppfInpBufReal[n][k] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->pppfInpBufImag[n][k] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + set_zero( psPredictionEncoder->pppfInpBufReal[n][k], LCLD_BANDS ); + set_zero( psPredictionEncoder->pppfInpBufImag[n][k], LCLD_BANDS ); + } + if ( ( psPredictionEncoder->ppfPredStateReal[n] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfPredStateImag[n] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + set_zero( psPredictionEncoder->ppfPredStateReal[n], LCLD_BANDS ); + set_zero( psPredictionEncoder->ppfPredStateImag[n], LCLD_BANDS ); + + if ( ( psPredictionEncoder->ppfInpPrevReal[n] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfInpPrevImag[n] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + + set_zero( psPredictionEncoder->ppfInpPrevReal[n], LCLD_BANDS ); + set_zero( psPredictionEncoder->ppfInpPrevImag[n], LCLD_BANDS ); + + if ( ( psPredictionEncoder->ppfPredStateRealTmp[n] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfPredStateImagTmp[n] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + set_zero( psPredictionEncoder->ppfPredStateRealTmp[n], LCLD_BANDS ); + set_zero( psPredictionEncoder->ppfPredStateImagTmp[n], LCLD_BANDS ); +#endif for ( k = 0; k < LCLD_BANDS; k++ ) { psPredictionEncoder->ppiPredBandEnable[n][k] = 0; +#ifndef SPLIT_REND_LCLD_5MS psPredictionEncoder->ppfA1Real[n][k] = 0.0; psPredictionEncoder->ppfA1Imag[n][k] = 0.0; +#else + psPredictionEncoder->ppfA1Real[n][k] = 0.0f; + psPredictionEncoder->ppfA1Imag[n][k] = 0.0f; +#endif } } @@ -175,23 +348,55 @@ void DeletePredictionEncoder( for ( n = 0; n < psPredictionEncoder->iChannels; n++ ) { +#ifdef SPLIT_REND_LCLD_5MS + int32_t k; +#else free( psPredictionEncoder->ppfEstPredGain[n] ); free( psPredictionEncoder->ppfEstPredBitGain[n] ); +#endif free( psPredictionEncoder->ppiPredBandEnable[n] ); free( psPredictionEncoder->ppfA1Real[n] ); free( psPredictionEncoder->ppfA1Imag[n] ); free( psPredictionEncoder->ppiA1Mag[n] ); free( psPredictionEncoder->ppiA1Phase[n] ); +#ifdef SPLIT_REND_LCLD_5MS + for ( k = 0; k < LCLD_PRED_WIN_LEN; k++ ) + { + free( psPredictionEncoder->pppfInpBufReal[n][k] ); + free( psPredictionEncoder->pppfInpBufImag[n][k] ); + } + free( psPredictionEncoder->pppfInpBufReal[n] ); + free( psPredictionEncoder->pppfInpBufImag[n] ); + free( psPredictionEncoder->ppfInpPrevReal[n] ); + free( psPredictionEncoder->ppfInpPrevImag[n] ); + free( psPredictionEncoder->ppfPredStateReal[n] ); + free( psPredictionEncoder->ppfPredStateImag[n] ); + free( psPredictionEncoder->ppfPredStateRealTmp[n] ); + free( psPredictionEncoder->ppfPredStateImagTmp[n] ); +#endif } free( psPredictionEncoder->piPredChanEnable ); free( psPredictionEncoder->piNumPredBands ); +#ifndef SPLIT_REND_LCLD_5MS free( psPredictionEncoder->ppfEstPredGain ); free( psPredictionEncoder->ppfEstPredBitGain ); +#endif free( psPredictionEncoder->ppiPredBandEnable ); free( psPredictionEncoder->ppfA1Real ); free( psPredictionEncoder->ppfA1Imag ); free( psPredictionEncoder->ppiA1Mag ); free( psPredictionEncoder->ppiA1Phase ); +#ifdef SPLIT_REND_LCLD_5MS + free( psPredictionEncoder->pppfInpBufReal ); + free( psPredictionEncoder->pppfInpBufImag ); + free( psPredictionEncoder->ppfInpPrevReal ); + free( psPredictionEncoder->ppfInpPrevImag ); + free( psPredictionEncoder->ppfPredStateReal ); + free( psPredictionEncoder->ppfPredStateImag ); + free( psPredictionEncoder->ppfPredStateRealTmp ); + free( psPredictionEncoder->ppfPredStateImagTmp ); +#endif + free( psPredictionEncoder ); @@ -199,14 +404,201 @@ void DeletePredictionEncoder( } -//#define USE_RXX_WINDOW - /*-------------------------------------------------------------------* * Function ComputePredictors() * * *-------------------------------------------------------------------*/ +#ifdef SPLIT_REND_LCLD_5MS +void ComputePredictors( + PredictionEncoder *psPredictionEncoder, + float ***pppfReal, + float ***pppfImag ) +{ + int32_t c; + + int32_t b0 = psPredictionEncoder->iSubSetId; + int32_t bstep = psPredictionEncoder->iNumSubSets; + int32_t iNumBlocks = psPredictionEncoder->iNumBlocks; + float ***pppfRealBuf; + float ***pppfImagBuf; + float pfEstPredBitGain[LCLD_BANDS] = { 0 }; + + if ( iNumBlocks < LCLD_PRED_WIN_LEN ) + { + pppfRealBuf = psPredictionEncoder->pppfInpBufReal; + pppfImagBuf = psPredictionEncoder->pppfInpBufImag; + for ( c = 0; c < psPredictionEncoder->iChannels; c++ ) + { + int32_t n; + for ( n = 0; n < LCLD_PRED_WIN_LEN - iNumBlocks; n++ ) + { + mvr2r( pppfRealBuf[c][n + iNumBlocks], pppfRealBuf[c][n], LCLD_BANDS ); + mvr2r( pppfImagBuf[c][n + iNumBlocks], pppfImagBuf[c][n], LCLD_BANDS ); + } + for ( n = 0; n < iNumBlocks; n++ ) + { + mvr2r( pppfReal[c][n], pppfRealBuf[c][n + LCLD_PRED_WIN_LEN - iNumBlocks], LCLD_BANDS ); + mvr2r( pppfImag[c][n], pppfImagBuf[c][n + LCLD_PRED_WIN_LEN - iNumBlocks], LCLD_BANDS ); + } + } + } + else + { + pppfRealBuf = pppfReal; + pppfImagBuf = pppfImag; + } + + for ( c = 0; c < psPredictionEncoder->iChannels; c++ ) + { + int32_t b; + psPredictionEncoder->piNumPredBands[c] = min( 50, psPredictionEncoder->iMaxNumPredBands ); + for ( b = b0; b < psPredictionEncoder->piNumPredBands[c]; b += bstep ) + { + int32_t n; + float fGain = 0.0; + float fBitGain = 0.0; + float *pfRxxReal; + float *pfRxxImag; + float fA1Real; + float fA1Imag; + int32_t iA1Mag; + int32_t iA1Phase; + + pfRxxReal = psPredictionEncoder->pfRxxReal; + pfRxxImag = psPredictionEncoder->pfRxxImag; + + pfRxxReal[0] = 0.0; + pfRxxImag[0] = 0.0; + for ( n = 0; n < LCLD_PRED_WIN_LEN; n++ ) + { + pfRxxReal[0] += ( pppfRealBuf[c][n][b] * pppfRealBuf[c][n][b] + pppfImagBuf[c][n][b] * pppfImagBuf[c][n][b] ); + } + + pfRxxReal[1] = 0.0; + pfRxxImag[1] = 0.0; + for ( n = 1; n < LCLD_PRED_WIN_LEN; n++ ) + { + pfRxxReal[1] += ( pppfRealBuf[c][n][b] * pppfRealBuf[c][n - 1][b] + pppfImagBuf[c][n][b] * pppfImagBuf[c][n - 1][b] ); + pfRxxImag[1] += ( pppfImagBuf[c][n][b] * pppfRealBuf[c][n - 1][b] - pppfRealBuf[c][n][b] * pppfImagBuf[c][n - 1][b] ); + } + + if ( pfRxxReal[0] > 1e-12f ) + { + float fA1Mag; + float fA1Phase; + float fGain2; + float fBitGain2; + int32_t iNumBlocksPerPredCoef = min( iNumBlocks * psPredictionEncoder->iNumSubSets, LCLD_PRED_WIN_LEN ); + + const float fMagScale = ( 2.0f * (float) ( 1 << ( PRED_QUNAT_FILTER_MAG_BITS ) ) + 1.0f ) / M_PI; + const float fInvMagScale = M_PI / ( 2.0f * (float) ( 1 << ( PRED_QUNAT_FILTER_MAG_BITS ) ) + 1.0f ); + const float fPhaseScale = (float) ( 1 << ( PRED_QUANT_FILTER_PHASE_BITS - 1 ) ) / M_PI; + const float fInvPhaseScale = M_PI / (float) ( 1 << ( PRED_QUANT_FILTER_PHASE_BITS - 1 ) ); + + /* Compute filter coefficeints */ + fA1Real = -pfRxxReal[1] / pfRxxReal[0]; + fA1Imag = -pfRxxImag[1] / pfRxxReal[0]; + + /* compute these before quant */ + /* Compute est coding gain based on quantized filter coefficients */ + fGain = 1.0f / ( 1.0f - fA1Real * fA1Real - fA1Imag * fA1Imag ); + fBitGain = 0.65f * log2f( fGain ) * (float) ( iNumBlocksPerPredCoef ) - (float) ( PRED_QUNAT_FILTER_MAG_BITS + PRED_QUANT_FILTER_PHASE_BITS ); // Wrong fix (iNumBlocks-1) + fA1Mag = sqrtf( fA1Real * fA1Real + fA1Imag * fA1Imag ); + fA1Mag = fMagScale * asinf( fA1Mag ); + iA1Mag = (int32_t) ( fA1Mag + 0.5f ); + iA1Mag = ( iA1Mag > PRED_QUANT_FILTER_MAG_MIN ) ? iA1Mag : PRED_QUANT_FILTER_MAG_MIN; + iA1Mag = ( iA1Mag < PRED_QUANT_FILTER_MAG_MAX ) ? iA1Mag : PRED_QUANT_FILTER_MAG_MAX; + fA1Mag = sinf( fInvMagScale * (float) iA1Mag ); + + fA1Phase = atan2f( fA1Imag, fA1Real ); + fA1Phase = fPhaseScale * fA1Phase; + iA1Phase = ( fA1Phase > 0.0f ) ? (int32_t) ( fA1Phase + 0.5f ) : (int32_t) ( fA1Phase - 0.5f ); + iA1Phase = ( iA1Phase > PRED_QUANT_FILTER_PHASE_MIN ) ? iA1Phase : PRED_QUANT_FILTER_PHASE_MIN; + iA1Phase = ( iA1Phase < PRED_QUANT_FILTER_PHASE_MAX ) ? iA1Phase : PRED_QUANT_FILTER_PHASE_MAX; // Is this the correct way to deal with this? should wrap? + fA1Phase = fInvPhaseScale * (float) iA1Phase; + + fA1Real = fA1Mag * cosf( fA1Phase ); + fA1Imag = fA1Mag * sinf( fA1Phase ); + + fGain2 = 1.0f / ( 1.0f - fA1Real * fA1Real - fA1Imag * fA1Imag ); + fBitGain2 = 0.65f * log2f( fGain ) * (float) ( iNumBlocksPerPredCoef ) - (float) ( PRED_QUNAT_FILTER_MAG_BITS + PRED_QUANT_FILTER_PHASE_BITS ); // Wrong fix (iNumBlocks-1) + fGain = ( fGain < fGain2 ) ? fGain : fGain2; + fBitGain = ( fBitGain < fBitGain2 ) ? fBitGain : fBitGain2; + } + else + { + fA1Real = 0.0f; + fA1Imag = 0.0f; + iA1Mag = 0; + iA1Phase = 0; + fGain = -10.0f; // Fix this + } + + pfEstPredBitGain[b] = fBitGain; + psPredictionEncoder->ppiPredBandEnable[c][b] = ( fBitGain > 0.0f ); // Initial prediction enable + psPredictionEncoder->ppfA1Real[c][b] = fA1Real; + psPredictionEncoder->ppfA1Imag[c][b] = fA1Imag; + psPredictionEncoder->ppiA1Mag[c][b] = iA1Mag; + psPredictionEncoder->ppiA1Phase[c][b] = iA1Phase; + } + + { + float fBestCost; + int32_t iPredBands; + float fBitGain; + int32_t iPredChanEnable = 0; + + fBestCost = 0.0; + iPredBands = 0; + fBitGain = -7.0; + for ( b = b0; b < 50; b += bstep ) + { // still getting this decision wrong! + fBitGain -= 1.0; + if ( psPredictionEncoder->ppiPredBandEnable[c][b] == 1 ) + { + fBitGain += pfEstPredBitGain[b]; + } + if ( fBitGain > fBestCost ) + { + fBestCost = fBitGain; + iPredBands = b; + iPredChanEnable = 1; + } + } + + if ( iPredChanEnable == 1 ) + { + for ( b = iPredBands + bstep; b < LCLD_BANDS; b += bstep ) + { + psPredictionEncoder->ppiPredBandEnable[c][b] = 0; + } + activate_bit( &psPredictionEncoder->piPredChanEnable[c], psPredictionEncoder->iSubSetId ); + psPredictionEncoder->piNumPredBands[c] = iPredBands + bstep; + } + else if ( iPredBands > 0 ) + { + for ( b = iPredBands; b < LCLD_BANDS; b += bstep ) + { + psPredictionEncoder->ppiPredBandEnable[c][b] = 0; + } + activate_bit( &psPredictionEncoder->piPredChanEnable[c], psPredictionEncoder->iSubSetId ); + psPredictionEncoder->piNumPredBands[c] = iPredBands; + } + else + { + for ( b = b0; b < LCLD_BANDS; b += bstep ) + { + psPredictionEncoder->ppiPredBandEnable[c][b] = 0; + } + deactivate_bit( &psPredictionEncoder->piPredChanEnable[c], psPredictionEncoder->iSubSetId ); + psPredictionEncoder->piNumPredBands[c] = 0; + } + } + } +} +#else int32_t ComputePredictors( PredictionEncoder *psPredictionEncoder, float ***pppfReal, @@ -241,36 +633,15 @@ int32_t ComputePredictors( pfRxxImag[0] = 0.0; for ( n = 0; n < iNumBlocks; n++ ) { -#ifdef USE_RXX_WINDOW - float fReal; - float fImag; - fReal = psPredictionEncoder->pfWindow[n] * pppfReal[c][n][b]; - fImag = psPredictionEncoder->pfWindow[n] * pppfImag[c][n][b]; - pfRxxReal[0] += ( fReal * fReal + fImag * fImag ); -#else pfRxxReal[0] += ( pppfReal[c][n][b] * pppfReal[c][n][b] + pppfImag[c][n][b] * pppfImag[c][n][b] ); -#endif } pfRxxReal[1] = 0.0; pfRxxImag[1] = 0.0; for ( n = 1; n < iNumBlocks; n++ ) { -#ifdef USE_RXX_WINDOW - float fReal1; - float fImag1; - float fReal2; - float fImag2; - fReal1 = psPredictionEncoder->pfWindow[n] * pppfReal[c][n][b]; - fImag1 = psPredictionEncoder->pfWindow[n] * pppfImag[c][n][b]; - fReal2 = psPredictionEncoder->pfWindow[n - 1] * pppfReal[c][n - 1][b]; - fImag2 = psPredictionEncoder->pfWindow[n - 1] * pppfImag[c][n - 1][b]; - pfRxxReal[1] += ( fReal1 * fReal2 + fImag1 * fImag2 ); - pfRxxImag[1] += ( fImag1 * fReal2 - fReal1 * fImag2 ); -#else pfRxxReal[1] += ( pppfReal[c][n][b] * pppfReal[c][n - 1][b] + pppfImag[c][n][b] * pppfImag[c][n - 1][b] ); pfRxxImag[1] += ( pppfImag[c][n][b] * pppfReal[c][n - 1][b] - pppfReal[c][n][b] * pppfImag[c][n - 1][b] ); -#endif } if ( pfRxxReal[0] > 1e-12f ) @@ -425,6 +796,7 @@ int32_t ComputePredictors( return iPredictionBits; } +#endif /*-------------------------------------------------------------------* @@ -433,6 +805,61 @@ int32_t ComputePredictors( * *-------------------------------------------------------------------*/ +#ifdef SPLIT_REND_LCLD_5MS +void ApplyForwardPredictors( + PredictionEncoder *psPredictionEncoder, + float ***pppfReal, + float ***pppfImag ) +{ + int32_t c; + for ( c = 0; c < psPredictionEncoder->iChannels; c++ ) + { + int32_t b; + if ( psPredictionEncoder->piPredChanEnable[c] > 0 ) + { + for ( b = 0; b < LCLD_BANDS; b++ ) + { + if ( psPredictionEncoder->ppiPredBandEnable[c][b] == 1 ) + { + int32_t n; + float fOldReal = 0.0f; + float fOldImag = 0.0f; + float fA1Real; + float fA1Imag; + + int32_t iSubset = b % psPredictionEncoder->iNumSubSets; + if ( iSubset != psPredictionEncoder->iSubSetId ) + { + fOldReal = psPredictionEncoder->ppfInpPrevReal[c][b]; + fOldImag = psPredictionEncoder->ppfInpPrevImag[c][b]; + } + psPredictionEncoder->ppfInpPrevReal[c][b] = pppfReal[c][psPredictionEncoder->iNumBlocks - 1][b]; + psPredictionEncoder->ppfInpPrevImag[c][b] = pppfImag[c][psPredictionEncoder->iNumBlocks - 1][b]; + + fA1Real = psPredictionEncoder->ppfA1Real[c][b]; + fA1Imag = psPredictionEncoder->ppfA1Imag[c][b]; + for ( n = 0; n < psPredictionEncoder->iNumBlocks; n++ ) + { + float fReal; + float fImag; + + fReal = pppfReal[c][n][b] + fA1Real * fOldReal - fA1Imag * fOldImag; + fImag = pppfImag[c][n][b] + fA1Real * fOldImag + fA1Imag * fOldReal; + + fOldReal = pppfReal[c][n][b]; + fOldImag = pppfImag[c][n][b]; + + pppfReal[c][n][b] = fReal; + pppfImag[c][n][b] = fImag; + } + } + } + } + } + + return; +} +#else void ApplyForwardPredictors( PredictionEncoder *psPredictionEncoder, float ***pppfReal, @@ -479,6 +906,7 @@ void ApplyForwardPredictors( return; } +#endif /*-------------------------------------------------------------------* @@ -487,6 +915,71 @@ void ApplyForwardPredictors( * *-------------------------------------------------------------------*/ +#ifdef SPLIT_REND_LCLD_5MS +int32_t WritePredictors( + PredictionEncoder *psPredictionEncoder, + IVAS_SPLIT_REND_BITS_HANDLE pBits ) +{ + int32_t iBitsWritten = 0; + int32_t c; + int32_t iNumSubSets = psPredictionEncoder->iNumSubSets; + int32_t iSubSetId = psPredictionEncoder->iSubSetId; + int32_t iNumPredBandBits = 6; + const int16_t iSubSetBits = ( LCLD_MAX_NUM_PRED_SUBSETS > 4 ? 3 : 2 ); + + /* number of subsets */ + ivas_split_rend_bitstream_write_int32( pBits, iNumSubSets - 1, iSubSetBits ); /* otherwise use default */ + iBitsWritten += iSubSetBits; + + if ( iNumSubSets > 1 ) + { + /* write current subset */ + ivas_split_rend_bitstream_write_int32( pBits, iSubSetId, iSubSetBits ); + iBitsWritten += iSubSetBits; + iNumPredBandBits = ( iNumSubSets >= 4 ? 4 : 5 ); + } + + for ( c = 0; c < psPredictionEncoder->iChannels; c++ ) + { + int32_t b; + int32_t b0 = iSubSetId; + + ivas_split_rend_bitstream_write_int32( pBits, psPredictionEncoder->piPredChanEnable[c], iNumSubSets ); + iBitsWritten += iNumSubSets; + + if ( get_bit( psPredictionEncoder->piPredChanEnable[c], iSubSetId ) ) + { + int32_t iNumPredBands = ( psPredictionEncoder->piNumPredBands[c] - b0 ) / iNumSubSets; + + ivas_split_rend_bitstream_write_int32( pBits, iNumPredBands, iNumPredBandBits ); + iBitsWritten += iNumPredBandBits; + + for ( b = b0; b < psPredictionEncoder->piNumPredBands[c]; b += iNumSubSets ) + { + ivas_split_rend_bitstream_write_int32( pBits, psPredictionEncoder->ppiPredBandEnable[c][b], 1 ); + iBitsWritten += 1; + + if ( psPredictionEncoder->ppiPredBandEnable[c][b] == 1 ) + { + int32_t iA1Mag; + int32_t iA1Phase; + + iA1Mag = psPredictionEncoder->ppiA1Mag[c][b]; + iA1Phase = psPredictionEncoder->ppiA1Phase[c][b] - PRED_QUANT_FILTER_PHASE_MIN; + + ivas_split_rend_bitstream_write_int32( pBits, iA1Mag, PRED_QUNAT_FILTER_MAG_BITS ); + iBitsWritten += PRED_QUNAT_FILTER_MAG_BITS; + + ivas_split_rend_bitstream_write_int32( pBits, iA1Phase, PRED_QUANT_FILTER_PHASE_BITS ); + iBitsWritten += PRED_QUANT_FILTER_PHASE_BITS; + } + } + } + } + + return iBitsWritten; +} +#else int32_t WritePredictors( PredictionEncoder *psPredictionEncoder, IVAS_SPLIT_REND_BITS_HANDLE pBits ) @@ -529,3 +1022,4 @@ int32_t WritePredictors( return iBitsWritten; } #endif +#endif diff --git a/lib_rend/ivas_RMSEnvGrouping.c b/lib_rend/ivas_RMSEnvGrouping.c index beb309ee64181e49f4d5451c2f1739f729175ab4..81deff1759403f313fcdc213089e2ab1f5dfa6e3 100644 --- a/lib_rend/ivas_RMSEnvGrouping.c +++ b/lib_rend/ivas_RMSEnvGrouping.c @@ -275,7 +275,6 @@ static void ComputeBandEnergy( return; } - /*-------------------------------------------------------------------* * Function ComputeMergeRMS() * @@ -487,7 +486,6 @@ static float TryMerge2( return fMergedCost; } - /*-------------------------------------------------------------------* * Function ComputeGreedyGroups3() * @@ -700,9 +698,13 @@ void ComputeEnvelopeGrouping( psRMSEnvelopeGrouping->psGMNodes[n].psNext = NULL; } - /* Perform grouping via Greedy Merge */ - /* Allows control over max groups can call using 16 if want same as previous call */ +/* Perform grouping via Greedy Merge */ +/* Allows control over max groups can call using 16 if want same as previous call */ +#ifdef SPLIT_REND_LCLD_5MS + ComputeGreedyGroups3( psRMSEnvelopeGrouping, iChannels, iNumBands, piBandwidths, psRMSEnvelopeGrouping->iNumBlocks ); +#else ComputeGreedyGroups3( psRMSEnvelopeGrouping, iChannels, iNumBands, piBandwidths, LCLD_BLOCKS_PER_FRAME ); +#endif /* Calc Groups from Merge Results */ *piNumGroups = 0; diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c index 33372952e3241630099feea30fd199809263f8f1..04af3f9a3d443565e10836d7b92fda491c8b5803 100644 --- a/lib_rend/ivas_crend.c +++ b/lib_rend/ivas_crend.c @@ -1615,7 +1615,9 @@ void ivas_rend_closeCldfbRend( } ivas_binRenderer_close( &pCldfbRend->hCldfbRend ); - +#ifdef SPLIT_REND_LCLD_5MS + ivas_binaural_hrtf_close( &pCldfbRend->hHrtfFastConv ); +#endif ivas_HRTF_fastconv_binary_close( &pCldfbRend->hHrtfFastConv ); return; diff --git a/lib_rend/ivas_lcld_decoder.c b/lib_rend/ivas_lcld_decoder.c index a2c2361be54efb8ff63c642be462a4b410fd5b8a..067b1ede71fae592112c18478309d597df237532 100644 --- a/lib_rend/ivas_lcld_decoder.c +++ b/lib_rend/ivas_lcld_decoder.c @@ -83,9 +83,6 @@ struct LCLD_DECODER uint32_t num_decode_table[2 * ALLOC_TABLE_SIZE]; int32_t piMSPredCoefs[MAX_BANDS]; int32_t piLRPhaseDiffs[MAX_BANDS]; -#ifdef ENABLE_PMOD_ADJUST - int32_t **ppiHiSMRFlags; -#endif int32_t iCommonGrouping; int32_t *piNumGroups; int32_t **ppiGroupLengths; @@ -344,29 +341,47 @@ static void CreateDecodeTable( LCLDDecoder *psLCLDDecoder, int32_t num, const ui * *------------------------------------------------------------------------------------------*/ +#ifndef SPLIT_REND_LCLD_5MS ivas_error CreateLCLDDecoder( LCLDDecoder **psLCLDDecoder_out, const int32_t iSampleRate, const int32_t iChannels ) +#else +ivas_error CreateLCLDDecoder( + LCLDDecoder **psLCLDDecoder_out, + const int32_t iSampleRate, + const int32_t iChannels, + const int32_t iNumBlocks ) +#endif { int32_t n; int32_t read_length; ivas_error error; LCLDDecoder *psLCLDDecoder = NULL; - assert( iSampleRate == 48000 ); // Fix - + assert( iSampleRate == 48000 ); +#ifdef SPLIT_REND_LCLD_5MS + assert( iNumBlocks == 16 || iNumBlocks == 8 || iNumBlocks == 4 ); +#endif if ( ( psLCLDDecoder = (LCLDDecoder *) malloc( sizeof( LCLDDecoder ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); } psLCLDDecoder->iSampleRate = iSampleRate; psLCLDDecoder->iChannels = iChannels; +#ifdef SPLIT_REND_LCLD_5MS + psLCLDDecoder->iNumBlocks = iNumBlocks; +#else psLCLDDecoder->iNumBlocks = LCLD_BLOCKS_PER_FRAME; +#endif psLCLDDecoder->iAllocOffset = 0; - psLCLDDecoder->iNumBands = MAX_BANDS_48; // Fix - psLCLDDecoder->piBandwidths = c_aiBandwidths48; // Fix +#ifdef SPLIT_REND_LCLD_5MS + psLCLDDecoder->iNumBands = 0; /* read from bitstream*/ +#else + psLCLDDecoder->iNumBands = MAX_BANDS_48; /* Fix */ +#endif + psLCLDDecoder->piBandwidths = c_aiBandwidths48; psLCLDDecoder->iMSMode = 0; if ( ( psLCLDDecoder->piMSFlags = (int32_t *) malloc( MAX_BANDS * sizeof( int32_t ) ) ) == NULL ) @@ -378,10 +393,6 @@ ivas_error CreateLCLDDecoder( psLCLDDecoder->piLRPhaseDiffs[n] = 0; psLCLDDecoder->piMSPredCoefs[n] = 0; } -#ifdef ENABLE_PMOD_ADJUST - psLCLDDecoder->ppiHiSMRFlags = - (int32_t **) malloc( psLCLDDecoder->iChannels * sizeof( int32_t * ) ); -#endif psLCLDDecoder->iCommonGrouping = 1; /* Common grouping always on only impacts stereo */ if ( ( psLCLDDecoder->piNumGroups = (int32_t *) malloc( psLCLDDecoder->iChannels * sizeof( int32_t ) ) ) == NULL ) @@ -429,11 +440,6 @@ ivas_error CreateLCLDDecoder( for ( n = 0; n < iChannels; n++ ) { int16_t k; -#ifdef ENABLE_PMOD_ADJUST - psLCLDDecoder->ppiHiSMRFlags[n] = - (int32_t *) malloc( MAX_BANDS * sizeof( int32_t ) ); - ; -#endif if ( ( psLCLDDecoder->ppiGroupLengths[n] = (int32_t *) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( int32_t ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); @@ -529,7 +535,7 @@ ivas_error CreateLCLDDecoder( { return error; } - psLCLDDecoder->psNoiseGen = NULL; // CreateNoiseGen(); // No noise fill for now + psLCLDDecoder->psNoiseGen = NULL; /* CreateNoiseGen(); No noise fill for now*/ *psLCLDDecoder_out = psLCLDDecoder; return IVAS_ERR_OK; @@ -606,16 +612,6 @@ void DeleteLCLDDecoder( LCLDDecoder *psLCLDDecoder ) free( psLCLDDecoder->pppiExcitation ); } -#ifdef ENABLE_PMOD_ADJUST - if ( psLCLDDecoder->ppiHiSMRFlags != NULL ) - { - for ( n = 0; n < psLCLDDecoder->iChannels; n++ ) - { - free( psLCLDDecoder->ppiHiSMRFlags[n] ); - } - free( psLCLDDecoder->ppiHiSMRFlags ); - } -#endif if ( psLCLDDecoder->pppiAlloc != NULL ) { @@ -717,7 +713,11 @@ void DeleteLCLDDecoder( LCLDDecoder *psLCLDDecoder ) static void ApplyRMSEnvelope( const int32_t iNumBands, const int32_t *piBandwidths, const int32_t iNumGroups, const int32_t *piGroupLengths, int32_t **ppiRMSEnvelope, float **ppfReal, float **ppfImag ); +#ifdef SPLIT_REND_LCLD_5MS +static void ReplaceSign( const int32_t iNumBlocks, const int32_t iNumLCLDBands, int32_t **ppiSignReal, int32_t **ppiSignImag, float **ppfReal, float **ppfImag, const int32_t *piBandwidths ); +#else static void ReplaceSign( const int32_t iNumBlocks, const int32_t iNumLCLDBands, int32_t **ppiSignReal, int32_t **ppiSignImag, float **ppfReal, float **ppfImag ); +#endif static void InvQuantizeSpectrum( const int32_t iNumGroups, const int32_t *piGroupLengths, const int32_t iNumBands, const int32_t *piBandwidths, int32_t **ppiAlloc, int32_t **ppiQReal, int32_t **ppiQImag, float **ppfReal, float **ppfImag, NoiseGen *psNoiseGen ); @@ -768,9 +768,6 @@ int32_t DecodeLCLDFrame( ReadRMSEnvelope( psLCLDDecoder->iChannels, (const int32_t *) psLCLDDecoder->piNumGroups, psLCLDDecoder->iNumBands, psLCLDDecoder->pppiRMSEnvelope, pBits ); -#ifdef ENABLE_PMOD_ADJUST - ReadPmodInformation( psLCLDDecoder->ppiHiSMRFlags, pBits, psLCLDDecoder->iChannels, psLCLDDecoder->iNumBands ); -#endif ReadAllocInformation( &psLCLDDecoder->iAllocOffset, pBits ); @@ -790,7 +787,7 @@ int32_t DecodeLCLDFrame( else { for ( n = 0; n < psLCLDDecoder->iChannels; n++ ) - { // This will be updated to support multiple sample rates + { /* This will be updated to support multiple sample rates*/ for ( k = 0; k < psLCLDDecoder->piNumGroups[n]; k++ ) { PerceptualModel( psLCLDDecoder->iNumBands, psLCLDDecoder->pppiRMSEnvelope[n][k], psLCLDDecoder->pppiExcitation[n][k], psLCLDDecoder->pppiSMR[n][k] ); @@ -826,13 +823,38 @@ int32_t DecodeLCLDFrame( pppfLCLDReal[n], pppfLCLDImag[n], psLCLDDecoder->psNoiseGen ); +#ifdef SPLIT_REND_LCLD_5MS + ReplaceSign( psLCLDDecoder->iNumBlocks, psLCLDDecoder->iNumBands, + psLCLDDecoder->pppiLCLDSignReal[n], + psLCLDDecoder->pppiLCLDSignImag[n], + pppfLCLDReal[n], pppfLCLDImag[n], psLCLDDecoder->piBandwidths ); +#else ReplaceSign( psLCLDDecoder->iNumBlocks, LCLD_BANDS, psLCLDDecoder->pppiLCLDSignReal[n], psLCLDDecoder->pppiLCLDSignImag[n], pppfLCLDReal[n], pppfLCLDImag[n] ); +#endif } +#ifdef DEBUG_WRITE_PREDICTORS + { + static FILE *fid; + if ( !fid ) + fid = fopen( "pred_dec.txt", "wt" ); + for ( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + int16_t b; + for ( b = 0; b < 60; b++ ) + fprintf( fid, "%.5f ", (float) psLCLDDecoder->psPredictionDecoder->ppiPredBandEnable[n][b] * psLCLDDecoder->psPredictionDecoder->ppfA1Imag[n][b] ); + } + fprintf( fid, "%d %d\n", psLCLDDecoder->psPredictionDecoder->iSubSetId, psLCLDDecoder->psPredictionDecoder->piPredChanEnable[n] ); + } +#endif +#ifdef SPLIT_REND_LCLD_5MS + ApplyInversePredictors( psLCLDDecoder->psPredictionDecoder, pppfLCLDReal, pppfLCLDImag ); +#else ApplyInversePredictros( psLCLDDecoder->psPredictionDecoder, pppfLCLDReal, pppfLCLDImag ); +#endif for ( n = 0; n < psLCLDDecoder->iChannels; n++ ) { @@ -904,7 +926,16 @@ static void ApplyRMSEnvelope( return; } - +#ifdef SPLIT_REND_LCLD_5MS +static void ReplaceSign( + const int32_t iNumBlocks, + const int32_t iNumLCLDBands, + int32_t **ppiSignReal, + int32_t **ppiSignImag, + float **ppfReal, + float **ppfImag, + const int32_t *piBandwidths ) +#else static void ReplaceSign( const int32_t iNumBlocks, const int32_t iNumLCLDBands, @@ -912,11 +943,34 @@ static void ReplaceSign( int32_t **ppiSignImag, float **ppfReal, float **ppfImag ) +#endif { int32_t b, n; +#ifdef SPLIT_REND_LCLD_5MS + int32_t m, idx; +#endif for ( n = 0; n < iNumBlocks; n++ ) { +#ifdef SPLIT_REND_LCLD_5MS + idx = 0; + for ( b = 0; b < iNumLCLDBands; b++ ) + { + for ( m = 0; m < piBandwidths[b]; m++ ) + { + if ( ppiSignReal[n][idx] == 1 ) + { + ppfReal[n][idx] = -ppfReal[n][idx]; + } + + if ( ppiSignImag[n][idx] == 1 ) + { + ppfImag[n][idx] = -ppfImag[n][idx]; + } + idx++; + } + } +#else for ( b = 0; b < iNumLCLDBands; b++ ) { if ( ppiSignReal[n][b] == 1 ) @@ -929,6 +983,7 @@ static void ReplaceSign( ppfImag[n][b] = -ppfImag[n][b]; } } +#endif } return; @@ -1020,9 +1075,10 @@ static void InvMSCoding( { int32_t b; int32_t iFBOffset; +#ifdef SPLIT_REND_LCLD_5MS + int32_t bMSPred = 0; +#else int32_t bms = 0; -#if defined SIMPLE_PHASE - void( *pFuncPhaseRotateOptions[4] ) = { &rot_zero, &rot_m_pi_2, &rot_pm_pi, &rot_p_pi_2 }; #endif iFBOffset = 0; @@ -1031,9 +1087,11 @@ static void InvMSCoding( if ( piMSFlags[b] == 1 ) { int32_t n; -#if defined SIMPLE_PHASE - void ( *pFuncPhaseRotate )( float *, float * ) = - pFuncPhaseRotateOptions[piLRPhaseDiffs[bms]]; +#ifdef SPLIT_REND_LCLD_5MS + int32_t phaseIdx; + float fPred; + phaseIdx = piLRPhaseDiffs[bMSPred] - PHASE_MIN_VAL; + fPred = dequantPred( piMSPredCoefs[bMSPred] ); #endif for ( n = 0; n < piBandwidths[b]; n++ ) { @@ -1047,8 +1105,10 @@ static void InvMSCoding( if ( iMSMode == 3 ) { +#ifndef SPLIT_REND_LCLD_5MS float fPred; fPred = dequantPred( piMSPredCoefs[bms] ); +#endif pppfReal[1][k][iFBOffset] += fPred * pppfReal[0][k][iFBOffset]; pppfImag[1][k][iFBOffset] += fPred * pppfImag[0][k][iFBOffset]; } @@ -1060,13 +1120,11 @@ static void InvMSCoding( if ( iMSMode == 3 ) { -#ifdef SIMPLE_PHASE - ( *pFuncPhaseRotate )( &fRightReal, &fRightImag ); -#else +#ifndef SPLIT_REND_LCLD_5MS int32_t phaseIdx; phaseIdx = piLRPhaseDiffs[bms] - PHASE_MIN_VAL; - cplxmult( &fRightReal, &fRightImag, c_afRotRealImag[phaseIdx][0], -c_afRotRealImag[phaseIdx][1] ); #endif + cplxmult( &fRightReal, &fRightImag, c_afRotRealImag[phaseIdx][0], -c_afRotRealImag[phaseIdx][1] ); } pppfReal[0][k][iFBOffset] = fLeftReal; @@ -1076,8 +1134,11 @@ static void InvMSCoding( } iFBOffset++; } - +#ifdef SPLIT_REND_LCLD_5MS + bMSPred++; +#else bms++; +#endif } else { @@ -1175,13 +1236,6 @@ static int32_t ReadMSInformation( anyNonZero = ivas_split_rend_bitstream_read_int32( pBits, 1 ); if ( anyNonZero ) { -#ifdef SIMPLE_PHASE - for ( n = 0; n < iNumMSPredBands; n++ ) - { - piLRPhaseDiffs[n] = ivas_split_rend_bitstream_read_int32( pBits, SIMPLE_PHASE_BITS ); - iBitsRead += SIMPLE_PHASE_BITS; - } -#else piLRPhaseDiffs[0] = ivas_split_rend_bitstream_read_int32( pBits, PHASE_BAND0_BITS ); piLRPhaseDiffs[0] += PHASE_MIN_VAL; iBitsRead += PHASE_BAND0_BITS; @@ -1192,7 +1246,6 @@ static int32_t ReadMSInformation( piLRPhaseDiffs[n] = tabIdx + ENV_DELTA_MIN; } DecodePhase( piLRPhaseDiffs, iNumMSPredBands, PHASE_DIFF_DIM ); -#endif } else { @@ -1224,11 +1277,9 @@ static int32_t ReadMSInformation( } #ifdef DEBUG_WRITE_MS_PRED { - static FILE *fid = 0; + static FILE *fid; if ( !fid ) - { - fid = fopen( "ms_mode_dec.txt", "wt" ); - } + fid = fopen( "ms_pred_dec.txt", "wt" ); writeMSPred( piLRPhaseDiffs, piMSPredCoefs, *piMSMode, iNumMSPredBands, iNumBands, fid, piMSFlags ); } #endif @@ -1241,7 +1292,6 @@ static int32_t ReadMSInformation( return iBitsRead; } - static int32_t ReadGroupInformation( const int32_t iChannels, const int32_t iNumBlocks, @@ -1430,66 +1480,6 @@ static int32_t ReadRMSEnvelope( } -#ifdef ENABLE_PMOD_ADJUST -static int32_t ReadPmodInformation( - int32_t **ppiHiSMRFlags, - IVAS_SPLIT_REND_BITS_HANDLE pBits, - int32_t iChannels, - int32_t iNumBands ) -{ - int32_t iBitsRead; - int32_t c; - iBitsRead = 0; - for ( c = 0; c < iChannels; c++ ) - { - int32_t b; - int32_t iFlags = ivas_split_rend_bitstream_read_int32( pBits, 1 ); - iBitsRead += 1; - if ( iFlags ) - { - for ( b = 0; b < iNumBands; b++ ) - { - ppiHiSMRFlags[c][b] = ivas_split_rend_bitstream_read_int32( pBits, 1 ); - iBitsRead += 1; - } - } - else - { - for ( b = 0; b < iNumBands; b++ ) - { - ppiHiSMRFlags[c][b] = 0; - } - } - } -#ifdef WRITE_HISMR_FLAGS - { - static FILE *fid = 0; - if ( !fid ) - { - fid = fopen( "hismr_dec.txt", "wt" ); - } - for ( c = 0; c < iChannels; c++ ) - { - int32_t b; - for ( b = 0; b < iNumBands; b++ ) - { - if ( c == iChannels - 1 && b == iNumBands - 1 ) - { - fprintf( fid, "%d\n", ppiHiSMRFlags[c][b] ); - } - else - { - fprintf( fid, "%d ", ppiHiSMRFlags[c][b] ); - } - } - } - } -#endif - return iBitsRead; -} -#endif - - static int32_t ReadAllocInformation( int32_t *piAllocOffset, IVAS_SPLIT_REND_BITS_HANDLE pBits ) diff --git a/lib_rend/ivas_lcld_encoder.c b/lib_rend/ivas_lcld_encoder.c index bd07175d95ca266814bbb87f61d5273d1ed13d02..bab9409157d84ae6720656951a89699b60b50a01 100644 --- a/lib_rend/ivas_lcld_encoder.c +++ b/lib_rend/ivas_lcld_encoder.c @@ -39,9 +39,6 @@ #include "ivas_lcld_rom_tables.h" #include "prot.h" #include "ivas_prot_rend.h" -#ifdef ENABLE_PMOD_ADJUST -#include "ton_corr.h" -#endif #include "wmc_auto.h" /*------------------------------------------------------------------------------------------* @@ -55,7 +52,9 @@ struct LCLD_ENCODER int32_t iNumBlocks; int32_t iTargetBitRate; +#ifndef SPLIT_REND_LCLD_5MS int32_t iTargetBitsPerFrame; +#endif int32_t iNumBands; const int32_t *piBandwidths; @@ -66,9 +65,6 @@ struct LCLD_ENCODER int32_t piLRPhaseDiffs[MAX_BANDS]; int32_t iAllowSidePred; -#ifdef ENABLE_PMOD_ADJUST - int32_t **ppiHiSMRFlags; -#endif RMSEnvelopeGrouping *psRMSEnvelopeGrouping; @@ -92,6 +88,58 @@ struct LCLD_ENCODER PredictionEncoder *psPredictionEncoder; }; +#ifdef SPLIT_REND_LCLD_5MS +/*------------------------------------------------------------------------------------------* + * Function Quantize() + * + * + *------------------------------------------------------------------------------------------*/ + +static int32_t Quantize( + const float fVal, + const float fScale, + int32_t *iSign, + const int32_t iMaxVal ) +{ + int32_t iVal; + if ( fVal > 0.0f ) + { + iVal = (int32_t) ( fScale * fVal + 0.5f ); + *iSign = 0; + } + else + { + iVal = (int32_t) ( -fScale * fVal + 0.5f ); + *iSign = 1; + } + iVal = ( iVal < iMaxVal ) ? iVal : iMaxVal; + + return iVal; +} + +/*------------------------------------------------------------------------------------------* + * Function UnQuantize() + * + * + *------------------------------------------------------------------------------------------*/ + +static float UnQuantize( + const int32_t iVal, + const float fScale, + const int32_t iSign ) +{ + float fVal; + if ( iSign == 0 ) + { + fVal = fScale * (float) iVal; + } + else + { + fVal = -fScale * (float) iVal; + } + return fVal; +} +#endif /*------------------------------------------------------------------------------------------* * Function CreateLCLDEncoder() @@ -99,18 +147,36 @@ struct LCLD_ENCODER * *------------------------------------------------------------------------------------------*/ +#ifdef SPLIT_REND_LCLD_5MS +ivas_error CreateLCLDEncoder( + LCLDEncoder **psLCLDEncoder_out, + const int32_t iSampleRate, + const int32_t iChannels, + const int32_t iTargetBitRate, + const int32_t iAllowSidePred, + const int16_t iNumBlocks, + const int16_t iNumSubSets ) +#else ivas_error CreateLCLDEncoder( LCLDEncoder **psLCLDEncoder_out, const int32_t iSampleRate, const int32_t iChannels, const int32_t iTargetBitRate, const int32_t iAllowSidePred ) +#endif { int32_t n; LCLDEncoder *psLCLDEncoder; ivas_error error; +#ifdef SPLIT_REND_LCLD_5MS + int32_t iMaxNumPredBands = 0; +#endif assert( iSampleRate == 48000 ); // Fix +#ifdef SPLIT_REND_LCLD_5MS + assert( iNumBlocks == 16 || iNumBlocks == 8 || iNumBlocks == 4 ); + assert( iNumSubSets > 0 && iNumSubSets <= LCLD_MAX_NUM_PRED_SUBSETS ); +#endif if ( ( psLCLDEncoder = (LCLDEncoder *) malloc( sizeof( LCLDEncoder ) ) ) == NULL ) { @@ -119,14 +185,29 @@ ivas_error CreateLCLDEncoder( psLCLDEncoder->iSampleRate = iSampleRate; psLCLDEncoder->iChannels = iChannels; +#ifdef SPLIT_REND_LCLD_5MS + psLCLDEncoder->iNumBlocks = (int32_t) iNumBlocks; +#else psLCLDEncoder->iNumBlocks = LCLD_BLOCKS_PER_FRAME; +#endif psLCLDEncoder->iAllocOffset = 0; psLCLDEncoder->iTargetBitRate = iTargetBitRate; +#ifndef SPLIT_REND_LCLD_5MS psLCLDEncoder->iTargetBitsPerFrame = iTargetBitRate * LCLD_BLOCKS_PER_FRAME * LCLD_BANDS / iSampleRate; +#endif + + psLCLDEncoder->piBandwidths = c_aiBandwidths48; +#ifdef SPLIT_REND_LCLD_5MS + psLCLDEncoder->iNumBands = DEF_BANDS_48; /* 22 bands = 50 CLDFB bands (rather than 23 bands) */ + for ( n = 0; n < psLCLDEncoder->iNumBands; n++ ) + { + iMaxNumPredBands += psLCLDEncoder->piBandwidths[n]; + } +#else + psLCLDEncoder->iNumBands = MAX_BANDS_48; +#endif - psLCLDEncoder->iNumBands = MAX_BANDS_48; // Fix - psLCLDEncoder->piBandwidths = c_aiBandwidths48; // Fix psLCLDEncoder->iMSMode = 0; if ( ( psLCLDEncoder->piMSFlags = (int32_t *) malloc( MAX_BANDS * sizeof( int32_t ) ) ) == NULL ) @@ -194,23 +275,11 @@ ivas_error CreateLCLDEncoder( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); } -#ifdef ENABLE_PMOD_ADJUST - if ( ( psLCLDEncoder->ppiHiSMRFlags = (int32_t **) malloc( psLCLDEncoder->iChannels * sizeof( int32_t * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); - } -#endif for ( n = 0; n < iChannels; n++ ) { int32_t k; -#ifdef ENABLE_PMOD_ADJUST - if ( ( psLCLDEncoder->ppiHiSMRFlags[n] = (int32_t *) malloc( MAX_BANDS * sizeof( int32_t ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); - } -#endif if ( ( psLCLDEncoder->ppiGroupLengths[n] = (int32_t *) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( int32_t ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); @@ -302,10 +371,17 @@ ivas_error CreateLCLDEncoder( } } +#ifdef SPLIT_REND_LCLD_5MS + if ( ( error = CreatePredictionEncoder( &( psLCLDEncoder->psPredictionEncoder ), iChannels, psLCLDEncoder->iNumBlocks, (int32_t) iNumSubSets, iMaxNumPredBands ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = CreatePredictionEncoder( &( psLCLDEncoder->psPredictionEncoder ), iChannels, psLCLDEncoder->iNumBlocks ) ) != IVAS_ERR_OK ) { return error; } +#endif *psLCLDEncoder_out = psLCLDEncoder; @@ -350,16 +426,6 @@ void DeleteLCLDEncoder( } free( psLCLDEncoder->ppiGroupLengths ); } -#ifdef ENABLE_PMOD_ADJUST - if ( psLCLDEncoder->ppiHiSMRFlags != NULL ) - { - for ( n = 0; n < psLCLDEncoder->iChannels; n++ ) - { - free( psLCLDEncoder->ppiHiSMRFlags[n] ); - } - free( psLCLDEncoder->ppiHiSMRFlags ); - } -#endif if ( psLCLDEncoder->pppiRMSEnvelope != NULL ) { for ( n = 0; n < psLCLDEncoder->iChannels; n++ ) @@ -483,10 +549,6 @@ static int32_t CountLCLDBits( const int32_t iNumGroups, const int32_t *piGroupLe static int32_t WriteHeaderInformation( const int32_t iNumBands, IVAS_SPLIT_REND_BITS_HANDLE pBits ); -#ifdef ENABLE_PMOD_ADJUST -static int32_t WritePmodInformation( const int32_t **ppiHiSMRFlags, IVAS_SPLIT_REND_BITS_HANDLE pBits, int32_t iChannels, int32_t iNumBands ); -#endif - static int32_t WriteMSInformation( const int32_t iNumBands, const int32_t iMSMode, const int32_t *piMSFlags, const int32_t *piLRPhaseDiffs, const int32_t *piMSPredCoefs, int32_t iNumMSPredBands, IVAS_SPLIT_REND_BITS_HANDLE pBits ); static int32_t WriteGroupInformation( const int32_t iChannels, const int32_t iCommonGrouping, const int32_t *piNumGroups, int32_t **ppiGroupLengths, IVAS_SPLIT_REND_BITS_HANDLE pBits ); @@ -497,8 +559,11 @@ static int32_t WriteAllocInformation( const int32_t iAllocOffset, IVAS_SPLIT_REN static int32_t WriteLCLDData( const int32_t iNumGroups, const int32_t *piGroupLengths, const int32_t iNumBands, const int32_t *piBandwidths, const int32_t *piPredEnable, int32_t **ppiAlloc, int32_t **ppiSignReal, int32_t **ppiSignImag, int32_t **ppiQReal, int32_t **ppiQImag, IVAS_SPLIT_REND_BITS_HANDLE pBits ); +#ifdef SPLIT_REND_LCLD_5MS +static int32_t ComputeAllocation( const int32_t iChannels, const int32_t *piNumGroups, int32_t **ppiGroupLengths, const int32_t iNumBands, const int32_t *piBandwidths, float ***pppfReal, float ***pppfImag, int32_t ***pppiSMR, const int32_t iAvailableBits, int32_t *piAllocOffset, int32_t ***pppiAlloc, int32_t ***pppiQReal, int32_t ***pppiQImag, int32_t ***pppiSignReal, int32_t ***pppiSignImag, PredictionEncoder *psPredictionEncoder ); +#else static int32_t ComputeAllocation( const int32_t iChannels, const int32_t *piNumGroups, int32_t **ppiGroupLengths, const int32_t iNumBands, const int32_t *piBandwidths, float ***pppfReal, float ***pppfImag, int32_t ***pppiSMR, const int32_t iAvailableBits, int32_t *piAllocOffset, int32_t ***pppiAlloc, int32_t ***pppiQReal, int32_t ***pppiQImag, int32_t ***pppiSignReal, int32_t ***pppiSignImag, int32_t **ppiPredEnable, float **ppfA1Real, float **ppfA1Imag ); - +#endif /*------------------------------------------------------------------------------------------* * Function EncodeLCLDFrame() @@ -519,6 +584,9 @@ int32_t EncodeLCLDFrame( int32_t iNumMSBands = 0; iAvailableBits = available_bits; // HCBR for now iBitsWritten = 0; +#ifdef SPLIT_REND_LCLD_5MS + assert( available_bits <= pBits->buf_len * 8 ); +#endif /* Do MS calc here */ if ( psLCLDEncoder->iChannels == 2 ) @@ -540,9 +608,6 @@ int32_t EncodeLCLDFrame( } } -#ifdef ENABLE_PMOD_ADJUST - CalcTonQuotas( psLCLDEncoder->iChannels, psLCLDEncoder->iNumBands, psLCLDEncoder->piBandwidths, pppfLCLDReal, pppfLCLDImag, psLCLDEncoder->ppiHiSMRFlags ); -#endif /* Compute Grouping and RMS Envelopes */ if ( psLCLDEncoder->iChannels == 2 && psLCLDEncoder->iCommonGrouping == 1 ) @@ -612,12 +677,6 @@ int32_t EncodeLCLDFrame( iBitsWritten += WriteRMSEnvelope( psLCLDEncoder->iChannels, (const int32_t *) psLCLDEncoder->piNumGroups, psLCLDEncoder->iNumBands, psLCLDEncoder->pppiRMSEnvelope, pBits ); -#ifdef ENABLE_PMOD_ADJUST - iBitsWritten += WritePmodInformation( psLCLDEncoder->ppiHiSMRFlags, - pBits, - psLCLDEncoder->iChannels, - psLCLDEncoder->iNumBands ); -#endif if ( psLCLDEncoder->iChannels == 2 && psLCLDEncoder->iCommonGrouping == 1 ) { @@ -648,7 +707,20 @@ int32_t EncodeLCLDFrame( } } } - +#ifdef DEBUG_WRITE_PREDICTORS + { + static FILE *fid; + if ( !fid ) + fid = fopen( "pred_enc.txt", "wt" ); + for ( n = 0; n < psLCLDEncoder->iChannels; n++ ) + { + int16_t b; + for ( b = 0; b < 60; b++ ) + fprintf( fid, "%.5f ", (float) psLCLDEncoder->psPredictionEncoder->ppiPredBandEnable[n][b] * psLCLDEncoder->psPredictionEncoder->ppfA1Imag[n][b] ); + } + fprintf( fid, "%d %d\n", psLCLDEncoder->psPredictionEncoder->iSubSetId, psLCLDEncoder->psPredictionEncoder->piPredChanEnable[n] ); + } +#endif iAvailableBits -= iBitsWritten; ComputeAllocation( psLCLDEncoder->iChannels, (const int32_t *) psLCLDEncoder->piNumGroups, @@ -665,10 +737,15 @@ int32_t EncodeLCLDFrame( psLCLDEncoder->pppiQLCLDImag, psLCLDEncoder->pppiLCLDSignReal, psLCLDEncoder->pppiLCLDSignImag, +#ifdef SPLIT_REND_LCLD_5MS + psLCLDEncoder->psPredictionEncoder ); +#else psLCLDEncoder->psPredictionEncoder->ppiPredBandEnable, psLCLDEncoder->psPredictionEncoder->ppfA1Real, psLCLDEncoder->psPredictionEncoder->ppfA1Imag ); +#endif + iBitsWritten += WriteAllocInformation( psLCLDEncoder->iAllocOffset, pBits ); @@ -710,6 +787,344 @@ int32_t GetNumGroups( LCLDEncoder *psLCLDEncoder ) * *------------------------------------------------------------------------------------------*/ +#ifdef SPLIT_REND_LCLD_5MS +enum MSPred_Types +{ + MS_PHASE_AND_PRED = 0, /* LR phase alignment + real-valued M/S prediction */ + MS_PRED_ONLY = 1, /* real-valued M/S prediction */ + MS_PHASE_ONLY = 2 /* LR phase alignment + M/S */ +}; + +enum MS_BS_TYPES +{ + MS_OFF = 0, + MS_ALL = 1, + MS_SOME = 2, + MS_PRED = 3 +}; + +static int32_t MSModeCalculation( + const int32_t iNumBlocks, + const int32_t iNumBands, + const int32_t *piBandwidths, + float ***pppfReal, + float ***pppfImag, + int32_t *piMSMode, + int32_t *piLRPhaseDiffs, + int32_t *piMSPredCoefs, + const int32_t iAllowSidePred, + int32_t *piMSFlags ) +{ + int32_t b; + int32_t iFBOffset; + int32_t iNumMSBands; + int32_t iMSPredType; + float fMSBitGain = 0.0f; + float pfMSPredBitGain[3] = { 0.0f }; + float fPred; + int32_t piMSPredFlags0[MAX_BANDS] = { 0 }; + int32_t piMSPredFlags1[MAX_BANDS] = { 0 }; + int32_t piMSPredFlags2[MAX_BANDS] = { 0 }; + int32_t *ppiMSPredFlags[3]; + int32_t piMSPredCoefs0[MAX_BANDS] = { 0 }; + int32_t piMSPredCoefs1[MAX_BANDS] = { 0 }; + int32_t piMSPredCoefs2[MAX_BANDS] = { 0 }; + int32_t *ppiMSPredCoefs[3]; + int32_t piMSPredPhase0[MAX_BANDS] = { 0 }; + int32_t piMSPredPhase1[MAX_BANDS] = { 0 }; + int32_t piMSPredPhase2[MAX_BANDS] = { 0 }; + int32_t *ppiMSPredPhase[3]; + int32_t iMsInfoBits; + int32_t piMsPredInfoBits[3] = { 0 }; + + const float feps = 1e-12f; + float fBitsFactor = 3.32192809488736f; /* = 1/log10(2), from dB/10 to bits assuming 1 bit per log2(SNR) or 1 bit per 3dB SNR */ + if ( iNumBlocks < LCLD_BLOCKS_PER_FRAME ) + { + fBitsFactor *= ( 0.7f + (float) ( iNumBlocks - 4 ) / (float) ( LCLD_BLOCKS_PER_FRAME - 4 ) * ( 1.0f - 0.7f ) ); /* Tuning for relatively higher side rate due to shorter frame length */ + } + + ppiMSPredFlags[0] = piMSPredFlags0; + ppiMSPredFlags[1] = piMSPredFlags1; + ppiMSPredFlags[2] = piMSPredFlags2; + + ppiMSPredCoefs[0] = piMSPredCoefs0; + ppiMSPredCoefs[1] = piMSPredCoefs1; + ppiMSPredCoefs[2] = piMSPredCoefs2; + + ppiMSPredPhase[0] = piMSPredPhase0; + ppiMSPredPhase[1] = piMSPredPhase1; + ppiMSPredPhase[2] = piMSPredPhase2; + + *piMSMode = MS_OFF; + iFBOffset = 0; + iNumMSBands = 0; + for ( b = 0; b < iNumBands; b++ ) + { + int32_t n; + float fLeftEnergy; + float fRightEnergy; + float fMidEnergy; + float fSideEnergy; + float fLRRatio; + float fMSRatio; + float pfMSPredRatio[3] = { 0.0f }; + float fMidEnergyPred; + float fSideEnergyPred; + float fLRCovReal = 0.0f; + float fLRCovImag = 0.0f; + int32_t iPhase; + int32_t iPred; + int32_t tabIdx = 0; + float fNumLines = (float) ( iNumBlocks * piBandwidths[b] * 2 ); /* per band per channel */ + float fLevelToSMRdBFactor = (float) c_aiDefaultTheta48[b] / (float) ( 1 << PERCEPTUAL_MODEL_SLGAIN_SHIFT ); /* frequency dependent SMR slope in psy model */ +#ifndef SPLIT_REND_LCLD_5MS + fLevelToSMRdBFactor = (float) c_aiDefaultTheta48[b] / 16.0f; /* this is a bug due to a change of PERCEPTUAL_MODEL_SLGAIN_SHIFT */ +#endif + fLeftEnergy = 0.0f; + fRightEnergy = 0.0f; + fMidEnergy = 0.0f; + fSideEnergy = 0.0f; + + for ( n = 0; n < piBandwidths[b]; n++ ) + { + int32_t k; + for ( k = 0; k < iNumBlocks; k++ ) + { + float fMidReal; + float fMidImag; + float fSideReal; + float fSideImag; + + fMidReal = 0.5f * ( pppfReal[0][k][iFBOffset] + pppfReal[1][k][iFBOffset] ); + fMidImag = 0.5f * ( pppfImag[0][k][iFBOffset] + pppfImag[1][k][iFBOffset] ); + fSideReal = 0.5f * ( pppfReal[0][k][iFBOffset] - pppfReal[1][k][iFBOffset] ); + fSideImag = 0.5f * ( pppfImag[0][k][iFBOffset] - pppfImag[1][k][iFBOffset] ); + + fLeftEnergy += ( pppfReal[0][k][iFBOffset] * pppfReal[0][k][iFBOffset] + pppfImag[0][k][iFBOffset] * pppfImag[0][k][iFBOffset] ); + fRightEnergy += ( pppfReal[1][k][iFBOffset] * pppfReal[1][k][iFBOffset] + pppfImag[1][k][iFBOffset] * pppfImag[1][k][iFBOffset] ); + fMidEnergy += ( fMidReal * fMidReal + fMidImag * fMidImag ); + fSideEnergy += ( fSideReal * fSideReal + fSideImag * fSideImag ); + + fLRCovReal += ( pppfReal[0][k][iFBOffset] * pppfReal[1][k][iFBOffset] + pppfImag[0][k][iFBOffset] * pppfImag[1][k][iFBOffset] ); + fLRCovImag += ( pppfImag[0][k][iFBOffset] * pppfReal[1][k][iFBOffset] - pppfImag[1][k][iFBOffset] * pppfReal[0][k][iFBOffset] ); + } + + iFBOffset++; + } + + /* M/S prediction without phase alignment*/ + fPred = 0.25f * ( fLeftEnergy - fRightEnergy ) / ( fMidEnergy + feps ); + iPred = quantPred( fPred ); + fPred = dequantPred( iPred ); + fSideEnergyPred = fSideEnergy + ( fPred * fPred * fMidEnergy - 2.0f * fPred * 0.25f * ( fLeftEnergy - fRightEnergy ) ); + + ppiMSPredCoefs[MS_PRED_ONLY][b] = iPred; + ppiMSPredPhase[MS_PRED_ONLY][b] = 0; + pfMSPredRatio[MS_PRED_ONLY] = log10f( ( fMidEnergy + feps ) / ( fSideEnergyPred + feps ) ); + + /* Phase alignment*/ + iPhase = 0; + if ( fLRCovReal * fLRCovReal + fLRCovImag * fLRCovImag > 0.5f * fLeftEnergy * fRightEnergy ) + { + float fPhase = atan2f( fLRCovImag, fLRCovReal ); + iPhase = quantPhase( fPhase ); + } + + /* adjust covariance */ + tabIdx = iPhase - PHASE_MIN_VAL; + cplxmult( &fLRCovReal, &fLRCovImag, c_afRotRealImag[tabIdx][0], -c_afRotRealImag[tabIdx][1] ); + + /* compute MS prediction coefficient based on adjusted covariance */ + fMidEnergyPred = 0.25f * ( fLeftEnergy + fRightEnergy + 2.0f * fLRCovReal ); + fSideEnergyPred = 0.25f * ( fLeftEnergy + fRightEnergy - 2.0f * fLRCovReal ); + + /* M/S with LR phase alignment but without prediction */ + ppiMSPredCoefs[MS_PHASE_ONLY][b] = 0; + ppiMSPredPhase[MS_PHASE_ONLY][b] = iPhase; + pfMSPredRatio[MS_PHASE_ONLY] = log10f( ( fMidEnergyPred + feps ) / ( fSideEnergyPred + feps ) ); + + /* M/S with LR phase alignment and prediction */ + fPred = fMidEnergyPred == 0.0f ? 0.0f : 0.25f * ( fLeftEnergy - fRightEnergy ) / fMidEnergyPred; + iPred = quantPred( fPred ); + fPred = dequantPred( iPred ); + fSideEnergyPred += ( fPred * fPred * fMidEnergyPred - 2.0f * fPred * 0.25f * ( fLeftEnergy - fRightEnergy ) ); + /* -= fPred * fPred * fMidEnergyPred doesn't work because fPred is quantized and does not match MS/MM exactly */ + ppiMSPredCoefs[MS_PHASE_AND_PRED][b] = iPred; + ppiMSPredPhase[MS_PHASE_AND_PRED][b] = iPhase; + pfMSPredRatio[MS_PHASE_AND_PRED] = log10f( ( fMidEnergyPred + feps ) / ( fSideEnergyPred + feps ) ); + + /* Plain M/S */ + fLeftEnergy = log10f( fLeftEnergy + feps ); + fRightEnergy = log10f( fRightEnergy + feps ); + fMidEnergy = log10f( fMidEnergy + feps ); + fSideEnergy = log10f( fSideEnergy + feps ); + + fLRRatio = ( fLeftEnergy > fRightEnergy ? fLeftEnergy - fRightEnergy : fRightEnergy - fLeftEnergy ); + fMSRatio = ( fMidEnergy > fSideEnergy ? fMidEnergy - fSideEnergy : fSideEnergy - fMidEnergy ); + + if ( fMSRatio > fLRRatio ) + { + iNumMSBands++; + piMSFlags[b] = 1; + fMSBitGain += fNumLines * ( fMSRatio - fLRRatio ) * fLevelToSMRdBFactor * fBitsFactor; + } + else + { + piMSFlags[b] = 0; + } + piLRPhaseDiffs[b] = 0; + piMSPredCoefs[b] = 0; + + /* MSPred bit gains based on increase of level ratio compared to L/R ratio and the level dependent psy-model */ + for ( iMSPredType = 0; iMSPredType < 3; iMSPredType++ ) + { + if ( pfMSPredRatio[iMSPredType] > fLRRatio ) + { + ppiMSPredFlags[iMSPredType][b] = 1; + pfMSPredBitGain[iMSPredType] += fNumLines * ( pfMSPredRatio[iMSPredType] - fLRRatio ) * fLevelToSMRdBFactor * fBitsFactor; + } + } + } + + /* remove signalling cost from bit gains */ + for ( iMSPredType = 0; iMSPredType < 3; iMSPredType++ ) + { + piMsPredInfoBits[iMSPredType] = CountMSBits( iNumBands, MS_PRED, ppiMSPredFlags[iMSPredType], ppiMSPredPhase[iMSPredType], ppiMSPredCoefs[iMSPredType] ); + pfMSPredBitGain[iMSPredType] = max( pfMSPredBitGain[iMSPredType] - piMsPredInfoBits[iMSPredType], 0.0f ); + } + + /* find the best M/S Pred type */ + iMSPredType = MS_PHASE_AND_PRED; +#ifdef SPLIT_REND_LCLD_5MS + iMSPredType = ( pfMSPredBitGain[MS_PRED_ONLY] > pfMSPredBitGain[iMSPredType] ? MS_PRED_ONLY : iMSPredType ); + iMSPredType = ( pfMSPredBitGain[MS_PHASE_ONLY] > pfMSPredBitGain[iMSPredType] ? MS_PHASE_ONLY : iMSPredType ); +#endif + + /* plain M/S */ + iMsInfoBits = CountMSBits( iNumBands, MS_SOME, piMSFlags, NULL, NULL ); + fMSBitGain = max( fMSBitGain - iMsInfoBits, 0.0f ); + if ( iAllowSidePred && pfMSPredBitGain[iMSPredType] > 1.1f * fMSBitGain ) + { + *piMSMode = MS_PRED; + iNumMSBands = 0; + for ( b = 0; b < iNumBands; b++ ) + { + piMSFlags[b] = ppiMSPredFlags[iMSPredType][b]; + if ( piMSFlags[b] == 1 ) + { + piMSPredCoefs[b] = ppiMSPredCoefs[iMSPredType][b]; + piLRPhaseDiffs[b] = ppiMSPredPhase[iMSPredType][b]; + iNumMSBands++; + } + else + { + piMSPredCoefs[b] = 0; + piLRPhaseDiffs[b] = 0; + } + } + } + else if ( iNumMSBands == iNumBands ) + { + *piMSMode = MS_ALL; + } + else if ( iNumMSBands > 0 ) + { + *piMSMode = MS_SOME; + } + else + { + *piMSMode = MS_OFF; + } +#ifdef DEBUG_WRITE_MS_PRED + { + static FILE *fid; + int32_t iActualInfoBits = CountMSBits( iNumBands, *piMSMode, piMSFlags, piLRPhaseDiffs, piMSPredCoefs ); + if ( !fid ) + fid = fopen( "ms_info_bits.txt", "wt" ); + fprintf( fid, "%d %d %d %d %d\n", iMsInfoBits, piMsPredInfoBits[MS_PHASE_AND_PRED], piMsPredInfoBits[MS_PRED_ONLY], piMsPredInfoBits[MS_PHASE_ONLY], iActualInfoBits ); + } +#endif + if ( *piMSMode != MS_OFF ) + { + iFBOffset = 0; + for ( b = 0; b < iNumBands; b++ ) + { + if ( piMSFlags[b] == 1 ) + { + int32_t n; + int32_t phaseIdx; + phaseIdx = piLRPhaseDiffs[b] - PHASE_MIN_VAL; + fPred = dequantPred( piMSPredCoefs[b] ); + for ( n = 0; n < piBandwidths[b]; n++ ) + { + int32_t k; + for ( k = 0; k < iNumBlocks; k++ ) + { + float fMidReal; + float fMidImag; + float fSideReal; + float fSideImag; + + if ( *piMSMode == MS_PRED ) + { + cplxmult( &pppfReal[1][k][iFBOffset], &pppfImag[1][k][iFBOffset], c_afRotRealImag[phaseIdx][0], c_afRotRealImag[phaseIdx][1] ); + } + + fMidReal = 0.5f * ( pppfReal[0][k][iFBOffset] + pppfReal[1][k][iFBOffset] ); + fMidImag = 0.5f * ( pppfImag[0][k][iFBOffset] + pppfImag[1][k][iFBOffset] ); + fSideReal = 0.5f * ( pppfReal[0][k][iFBOffset] - pppfReal[1][k][iFBOffset] ); + fSideImag = 0.5f * ( pppfImag[0][k][iFBOffset] - pppfImag[1][k][iFBOffset] ); + + if ( *piMSMode == MS_PRED ) + { + fSideReal -= fPred * fMidReal; + fSideImag -= fPred * fMidImag; + } + + pppfReal[0][k][iFBOffset] = fMidReal; + pppfReal[1][k][iFBOffset] = fSideReal; + pppfImag[0][k][iFBOffset] = fMidImag; + pppfImag[1][k][iFBOffset] = fSideImag; + } + iFBOffset++; + } + } + else + { + iFBOffset += piBandwidths[b]; + } + } + } +#ifdef DEBUG_WRITE_MS_PRED + { + static FILE *fid; + if ( !fid ) + fid = fopen( "ms_enc.txt", "wt" ); + writeMSPred( piLRPhaseDiffs, piMSPredCoefs, *piMSMode, iNumMSBands, iNumBands, fid, piMSFlags ); + } +#endif + if ( *piMSMode == MS_PRED ) + { + /* Differential Coding of Phase Data*/ + PrepEncode( piLRPhaseDiffs, piMSFlags, iNumBands ); + PrepEncode( piMSPredCoefs, piMSFlags, iNumBands ); +#ifdef DEBUG_WRITE_MS_PRED + { + static FILE *fid; + if ( !fid ) + fid = fopen( "ms_pred_enc.txt", "wt" ); + writeMSPred( piLRPhaseDiffs, piMSPredCoefs, *piMSMode, iNumMSBands, iNumBands, fid, piMSFlags ); + } +#endif + /* Differential Coding*/ + EncodePhase( piLRPhaseDiffs, iNumMSBands, PHASE_DIFF_DIM ); + EncodePredCoef( piMSPredCoefs, iNumMSBands ); + } + + return iNumMSBands; +} +#else static int32_t MSModeCalculation( const int32_t iNumBlocks, const int32_t iNumBands, @@ -1018,6 +1433,7 @@ static int32_t MSModeCalculation( return iNumMSBands; } +#endif static void RemoveRMSEnvelope( @@ -1057,7 +1473,119 @@ static void RemoveRMSEnvelope( return; } +#ifdef SPLIT_REND_LCLD_5MS +static void QuantizeSpectrumDPCM_Opt( + const int32_t iNumGroups, + const int32_t *piGroupLengths, + const int32_t iNumBands, + const int32_t *piBandwidths, + int32_t **ppiAlloc, + float **ppfReal, + float **ppfImag, + int32_t **ppiQReal, + int32_t **ppiQImag, + int32_t **ppiSignReal, + int32_t **ppiSignImag, + int32_t iNumSubSets, + int32_t iSubSetId, + int32_t *piPredEnable, + float *pfA1Real, + float *pfA1Imag, + float *pfPredStateReal, + float *pfPredStateImag ) +{ + int32_t b, n; + int32_t iFBOffset; + int32_t k, iAlloc, iMaxQuantVal; + float fSCFGain, fInvSCFGain; + + iFBOffset = 0; + for ( b = 0; b < iNumBands; b++ ) + { + int32_t m; + for ( m = 0; m < piBandwidths[b]; m++ ) + { + int32_t iBlockOffset = 0; + if ( piPredEnable[iFBOffset] == 1 ) + { + float fReal; + float fImag; + int32_t iSubset = iFBOffset % iNumSubSets; + float fPrevReal = 0.0f; + float fPrevImag = 0.0f; + if ( iSubset != iSubSetId ) + { + /* run predictors across sub-frames */ + fPrevReal = pfPredStateReal[iFBOffset]; + fPrevImag = pfPredStateImag[iFBOffset]; + } + for ( n = 0; n < iNumGroups; n++ ) + { + iAlloc = ppiAlloc[n][b]; + iMaxQuantVal = c_aiQuantMaxValues[iAlloc]; + fSCFGain = c_afScaleFactor[iAlloc]; + fInvSCFGain = c_afInvScaleFactor[iAlloc]; + for ( k = 0; k < piGroupLengths[n]; k++ ) + { + /* prediction */ + fReal = pfA1Real[iFBOffset] * fPrevReal - pfA1Imag[iFBOffset] * fPrevImag; + fImag = pfA1Real[iFBOffset] * fPrevImag + pfA1Imag[iFBOffset] * fPrevReal; + + ppiQReal[iBlockOffset][iFBOffset] = Quantize( ppfReal[iBlockOffset][iFBOffset] + fReal, /* quantize residual */ + fSCFGain, + &ppiSignReal[iBlockOffset][iFBOffset], + iMaxQuantVal ); + + ppiQImag[iBlockOffset][iFBOffset] = Quantize( ppfImag[iBlockOffset][iFBOffset] + fImag, + fSCFGain, + &ppiSignImag[iBlockOffset][iFBOffset], + iMaxQuantVal ); + + fPrevReal = UnQuantize( ppiQReal[iBlockOffset][iFBOffset], + fInvSCFGain, + ppiSignReal[iBlockOffset][iFBOffset] ) - + fReal; /* add prediction to quantized residual = reconstructed sample */ + + fPrevImag = UnQuantize( ppiQImag[iBlockOffset][iFBOffset], + fInvSCFGain, + ppiSignImag[iBlockOffset][iFBOffset] ) - + fImag; + + iBlockOffset++; + } /* group length */ + } /* groups */ + pfPredStateReal[iFBOffset] = fPrevReal; + pfPredStateImag[iFBOffset] = fPrevImag; + } /* predEnable */ + else + { /* no prediction */ + for ( n = 0; n < iNumGroups; n++ ) + { + iAlloc = ppiAlloc[n][b]; + iMaxQuantVal = c_aiQuantMaxValues[iAlloc]; + fSCFGain = c_afScaleFactor[iAlloc]; + fInvSCFGain = c_afInvScaleFactor[iAlloc]; + for ( k = 0; k < piGroupLengths[n]; k++ ) + { + ppiQReal[iBlockOffset][iFBOffset] = Quantize( ppfReal[iBlockOffset][iFBOffset], + fSCFGain, + &ppiSignReal[iBlockOffset][iFBOffset], + iMaxQuantVal ); + + ppiQImag[iBlockOffset][iFBOffset] = Quantize( ppfImag[iBlockOffset][iFBOffset], + fSCFGain, + &ppiSignImag[iBlockOffset][iFBOffset], + iMaxQuantVal ); + iBlockOffset++; + } /* group length */ + } /* groups */ + } /* predEnable */ + iFBOffset++; + } /* bandwidth */ + } /* bands */ +} +#else static void QuantizeSpectrumDPCM_Opt( const int32_t iNumGroups, const int32_t *piGroupLengths, @@ -1199,7 +1727,7 @@ static void QuantizeSpectrumDPCM_Opt( return; } - +#endif static int32_t CountLCLDBits( const int32_t iNumGroups, @@ -1362,13 +1890,6 @@ static int32_t WriteMSInformation( if ( anyNonZero ) { -#ifdef SIMPLE_PHASE - for ( b = 0; b < iNumMSPredBands; b++ ) - { - ivas_split_rend_bitstream_write_int32( pBits, piLRPhaseDiff[b], SIMPLE_PHASE_BITS ); - iBitsWritten += SIMPLE_PHASE_BITS; - } -#else ivas_split_rend_bitstream_write_int32( pBits, piLRPhaseDiff[0] - PHASE_MIN_VAL, PHASE_BAND0_BITS ); iBitsWritten += PHASE_BAND0_BITS; for ( b = 1; b < iNumMSPredBands; b++ ) @@ -1377,7 +1898,6 @@ static int32_t WriteMSInformation( ivas_split_rend_bitstream_write_int32( pBits, c_aaiRMSEnvHuffEnc[tabIdx][1], c_aaiRMSEnvHuffEnc[tabIdx][0] ); iBitsWritten += c_aaiRMSEnvHuffEnc[tabIdx][0]; } -#endif } anyNonZero = 0; @@ -1540,70 +2060,6 @@ static int32_t WriteRMSEnvelope( } -#ifdef ENABLE_PMOD_ADJUST -static int32_t WritePmodInformation( - const int32_t **ppiHiSMRFlags, - IVAS_SPLIT_REND_BITS_HANDLE pBits, - int32_t iChannels, - int32_t iNumBands ) -{ - int32_t iBitsWritten, c, b; - - iBitsWritten = 0; - - for ( c = 0; c < iChannels; c++ ) - { - int32_t anyNonZero = 0; - const int32_t *flags = ppiHiSMRFlags[c]; - for ( b = 0; b < iNumBands; b++ ) - { - if ( flags[b] ) - { - anyNonZero = 1; - break; - } - } - ivas_split_rend_bitstream_write_int32( pBits, anyNonZero, 1 ); - iBitsWritten += 1; - if ( anyNonZero ) - { - for ( b = 0; b < iNumBands; b++ ) - { - ivas_split_rend_bitstream_write_int32( pBits, flags[b], 1 ); - iBitsWritten += 1; - } - } - } -#ifdef WRITE_HISMR_FLAGS - { - static FILE *fid = 0; - if ( !fid ) - { - fid = fopen( "hismr_enc.txt", "wt" ); - } - for ( c = 0; c < iChannels; c++ ) - { - int32_t b; - for ( b = 0; b < iNumBands; b++ ) - { - if ( c == iChannels - 1 && b == iNumBands - 1 ) - { - fprintf( fid, "%d\n", ppiHiSMRFlags[c][b] ); - } - else - { - fprintf( fid, "%d ", ppiHiSMRFlags[c][b] ); - } - } - } - } -#endif - - return iBitsWritten; -} -#endif - - static int32_t WriteAllocInformation( const int32_t iAllocOffset, IVAS_SPLIT_REND_BITS_HANDLE pBits ) @@ -1764,9 +2220,13 @@ static int32_t ComputeAllocation( int32_t ***pppiQImag, int32_t ***pppiSignReal, int32_t ***pppiSignImag, +#ifdef SPLIT_REND_LCLD_5MS + PredictionEncoder *psPredictionEncoder ) +#else int32_t **ppiPredEnable, float **ppfA1Real, float **ppfA1Imag ) +#endif { int32_t iBitsUsed, iDone, iDelta; int32_t b, k, n; @@ -1800,6 +2260,14 @@ static int32_t ComputeAllocation( } } +#ifdef SPLIT_REND_LCLD_5MS + if ( psPredictionEncoder->iNumSubSets > 1 ) + { + mvr2r( psPredictionEncoder->ppfPredStateReal[n], psPredictionEncoder->ppfPredStateRealTmp[n], LCLD_BANDS ); + mvr2r( psPredictionEncoder->ppfPredStateImag[n], psPredictionEncoder->ppfPredStateImagTmp[n], LCLD_BANDS ); + } +#endif + QuantizeSpectrumDPCM_Opt( piNumGroups[n], (const int32_t *) ppiGroupLengths[n], iNumBands, @@ -1811,15 +2279,29 @@ static int32_t ComputeAllocation( pppiQImag[n], pppiSignReal[n], pppiSignImag[n], +#ifdef SPLIT_REND_LCLD_5MS + psPredictionEncoder->iNumSubSets, + psPredictionEncoder->iSubSetId, + psPredictionEncoder->ppiPredBandEnable[n], + psPredictionEncoder->ppfA1Real[n], + psPredictionEncoder->ppfA1Imag[n], + psPredictionEncoder->ppfPredStateRealTmp[n], + psPredictionEncoder->ppfPredStateImagTmp[n] ); +#else ppiPredEnable[n], ppfA1Real[n], ppfA1Imag[n] ); +#endif iBitsUsed += CountLCLDBits( piNumGroups[n], (const int32_t *) ppiGroupLengths[n], iNumBands, piBandwidths, +#ifdef SPLIT_REND_LCLD_5MS + (const int32_t *) psPredictionEncoder->ppiPredBandEnable[n], +#else (const int32_t *) ppiPredEnable[n], +#endif pppiAlloc[n], pppiQReal[n], pppiQImag[n] ); @@ -1866,6 +2348,21 @@ static int32_t ComputeAllocation( } } +#ifdef SPLIT_REND_LCLD_5MS + if ( psPredictionEncoder->iNumSubSets > 1 ) + { + for ( n = 0; n < iChannels; n++ ) + { + mvr2r( psPredictionEncoder->ppfPredStateRealTmp[n], psPredictionEncoder->ppfPredStateReal[n], LCLD_BANDS ); + mvr2r( psPredictionEncoder->ppfPredStateImagTmp[n], psPredictionEncoder->ppfPredStateImag[n], LCLD_BANDS ); + } + if ( ++psPredictionEncoder->iSubSetId == psPredictionEncoder->iNumSubSets ) + { + psPredictionEncoder->iSubSetId = 0; + } + } +#endif + // printf("%d\n",*piAllocOffset); // printf("%d\t%d\t%d\n",pppiAlloc[0][0][0],pppiAlloc[0][0][1],pppiAlloc[0][0][22]); diff --git a/lib_rend/ivas_lcld_prot.h b/lib_rend/ivas_lcld_prot.h index 4f6602b4dd8ce4e8c30febb3b88ec4913df52cd3..f83ef8ae8bd4959b0dfa07b1e610748927d25995 100644 --- a/lib_rend/ivas_lcld_prot.h +++ b/lib_rend/ivas_lcld_prot.h @@ -42,12 +42,23 @@ typedef struct LCLD_ENCODER LCLDEncoder; +#ifdef SPLIT_REND_LCLD_5MS +ivas_error CreateLCLDEncoder( + LCLDEncoder **psLCLDEncoder_out, + const int32_t iSampleRate, + const int32_t iChannels, + const int32_t iTargetBitRate, + const int32_t iAllowSidePred, + const int16_t iNumBlocks, + const int16_t iNumSubSets ); +#else ivas_error CreateLCLDEncoder( LCLDEncoder **psLCLDEncoder, const int32_t iSampleRate, const int32_t iChannels, const int32_t iTargetBitRate, const int32_t iAllowSidePred ); +#endif void DeleteLCLDEncoder( LCLDEncoder *psLCLDEncoder @@ -68,10 +79,18 @@ int32_t GetNumGroups( typedef struct LCLD_DECODER LCLDDecoder; +#ifndef SPLIT_REND_LCLD_5MS ivas_error CreateLCLDDecoder( LCLDDecoder **psLCLDDecoder_out, const int32_t iSampleRate, const int32_t iChannels ); +#else +ivas_error CreateLCLDDecoder( + LCLDDecoder **psLCLDDecoder_out, + const int32_t iSampleRate, + const int32_t iChannels, + const int32_t iNumBlocks ); +#endif void DeleteLCLDDecoder( LCLDDecoder *psLCLDDecoder @@ -100,25 +119,6 @@ void cplxmult( float i2 ); -#ifdef SIMPLE_PHASE -void rot_pm_pi( - float *pr, - float *pi ); - -void rot_p_pi_2( - float *pr, - float *pi -); - -void rot_m_pi_2( - float *pr, - float *pi ); - -void rot_zero( - float *pr, - float *pi -); -#endif int32_t requantPhase( int32_t phaseQ @@ -195,7 +195,6 @@ typedef struct NOISE_GEN float *pfNoiseBuffer; } NoiseGen; - void DeleteNoiseGen( NoiseGen *psNoiseGen ); @@ -244,15 +243,30 @@ typedef struct PREDICTION_ENCODER int32_t iChannels; int32_t iNumBlocks; +#ifdef SPLIT_REND_LCLD_5MS + int32_t iSubSetId; + int32_t iNumSubSets; + int32_t iMaxNumPredBands; + float ***pppfInpBufReal; /* channels, LCLD_PRED_WIN_LEN, bands */ + float ***pppfInpBufImag; + float **ppfPredStateReal; /* channels, bands */ + float **ppfPredStateImag; + float **ppfPredStateRealTmp; + float **ppfPredStateImagTmp; + float **ppfInpPrevReal; /* channels, bands */ + float **ppfInpPrevImag; +#endif + float *pfWindow; float pfRxxReal[2]; float pfRxxImag[2]; int32_t *piPredChanEnable; int32_t *piNumPredBands; - +#ifndef SPLIT_REND_LCLD_5MS float **ppfEstPredGain; float **ppfEstPredBitGain; +#endif int32_t **ppiPredBandEnable; float **ppfA1Real; @@ -262,21 +276,39 @@ typedef struct PREDICTION_ENCODER int32_t **ppiA1Phase; } PredictionEncoder; +#ifdef SPLIT_REND_LCLD_5MS +ivas_error CreatePredictionEncoder( + PredictionEncoder **psPredictionEncoder_out, + const int32_t iChannels, + const int32_t iNumBlocks, + const int32_t iNumSubSets, + const int32_t iMaxNumPredBands +); +#else ivas_error CreatePredictionEncoder( PredictionEncoder **psPredictionEncoder_out, const int32_t iChannels, const int32_t iNumBlocks ); +#endif void DeletePredictionEncoder( PredictionEncoder *psPredictionEncoder ); +#ifdef SPLIT_REND_LCLD_5MS +void ComputePredictors( + PredictionEncoder *psPredictionEncoder, + float ***pppfReal, + float ***pppfImag +); +#else int32_t ComputePredictors( PredictionEncoder *psPredictionEncoder, float ***pppfReal, float ***pppfImag ); +#endif void ApplyForwardPredictors( PredictionEncoder *psPredictionEncoder, @@ -293,11 +325,19 @@ typedef struct PREDICTION_DECODER { int32_t iChannels; int32_t iNumBlocks; + #ifdef SPLIT_REND_LCLD_5MS + int32_t iSubSetId; + int32_t iNumSubSets; + float **ppfPredStateReal; + float **ppfPredStateImag; + #endif int32_t *piPredChanEnable; + #ifndef SPLIT_REND_LCLD_5MS int32_t *piNumPredBands; float **ppfEstPredGain; + #endif int32_t **ppiPredBandEnable; float **ppfA1Real; @@ -327,7 +367,11 @@ int32_t ReadPredictors( IVAS_SPLIT_REND_BITS_HANDLE pBits ); +#ifdef SPLIT_REND_LCLD_5MS +void ApplyInversePredictors( +#else void ApplyInversePredictros( +#endif PredictionDecoder *psPredictionDecoder, float ***pppfReal, float ***pppfImag diff --git a/lib_rend/ivas_lcld_rom_tables.c b/lib_rend/ivas_lcld_rom_tables.c index 2e93c685397da0834e6aba6922fe1e17c2835d09..0499ded47cc2f3ee2c63369ed45bad9fd72921a2 100644 --- a/lib_rend/ivas_lcld_rom_tables.c +++ b/lib_rend/ivas_lcld_rom_tables.c @@ -39,12 +39,14 @@ /* clang-format off */ +#ifndef SPLIT_REND_LCLD_5MS const float c_afRotRealImagSimple[SIMPLE_PHASE_MAX_VAL + 1][2] = { { 1.0f, 0.0f }, /* zero */ { 0.0f, 1.0f }, /* pi/2 */ { -1.0f, 0.0f }, /* pi */ { 0.0f, -1.0f }, /* 3*pi/2 */ }; +#endif /* phi = (-12:12)'/12 *pi; tmp = [cos(phi),sin(phi)]; tmp = tmp';sprintf('{%.8ff, %.8ff},\n',tmp(:)) */ const float c_afRotRealImag[PHASE_MAX_VAL - PHASE_MIN_VAL + 1][2] = diff --git a/lib_rend/ivas_lcld_rom_tables.h b/lib_rend/ivas_lcld_rom_tables.h index 4bdd36c3b79bdd4ca59cf27c4dedbdd076d390da..15a8e2921199329419fa6b3f60745422de1873a8 100644 --- a/lib_rend/ivas_lcld_rom_tables.h +++ b/lib_rend/ivas_lcld_rom_tables.h @@ -45,9 +45,16 @@ #define LCLD_BLOCKS_PER_FRAME ( 16 ) #define LCLD_MAX_BLOCKS_PER_FRAME ( 16 ) #define LCLD_BANDS ( 60 ) +#ifdef SPLIT_REND_LCLD_5MS +#define LCLD_PRED_WIN_LEN ( 16 ) +#define LCLD_MAX_NUM_PRED_SUBSETS ( 8 ) +#endif #define MAX_BANDS ( 23 ) #define MAX_BANDS_48 ( 23 ) +#ifdef SPLIT_REND_LCLD_5MS +#define DEF_BANDS_48 ( 22 ) +#endif #define ENV_MIN ( -64 ) #define ENV_MAX ( 64 ) @@ -88,6 +95,7 @@ #define PHASE_DIFF_DIM ( 2 ) #define PHASE_BAND0_BITS ( 5 ) +#ifndef SPLIT_REND_LCLD_5MS #define SIMPLE_PHASE_MAX_VAL ( 3 ) #define SIMPLE_PHASE_MIN_VAL ( 0 ) #define SIMPLE_PHASE_BITS ( 2 ) @@ -95,7 +103,7 @@ #define TON_QUOTA_ABS_THRESHOLD ( 8.0f ) #define TON_QUOTA_INC_THRESHOLD ( 4.0f ) - +#endif #define PERCEPTUAL_MODEL_SLGAIN_SHIFT ( 8 ) //#define USE_DEMOD_TABLES @@ -103,7 +111,9 @@ #define HUFF_DEC_TABLE_SIZE ( 16 ) extern const float c_afRotRealImag[PRED_MAX_VAL - PRED_MIN_VAL + 1][2]; +#ifndef SPLIT_REND_LCLD_5MS extern const float c_afRotRealImagSimple[SIMPLE_PHASE_MAX_VAL + 1][2]; +#endif extern const int32_t c_aiDefaultTheta48[MAX_BANDS_48]; extern const float c_afScaleFactor[ALLOC_TABLE_SIZE]; diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 60a6d16b7c06b3b5c6f9c1644e499317999b2eae..ad6c02d92be8822eb5f200fa787f32481448c397 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -1524,6 +1524,16 @@ void ivas_init_split_post_rend_handles( SPLIT_POST_REND_WRAPPER *hSplitRendWrapper ); +#ifdef SPLIT_REND_LCLD_5MS +ivas_error ivas_split_renderer_open( + SPLIT_REND_WRAPPER *hSplitBinRend, + const IVAS_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, + const int32_t output_Fs, + const int16_t cldfb_in_flag, + const int16_t pcm_out_flag, + const int16_t num_subframes +); +#else ivas_error ivas_split_renderer_open( SPLIT_REND_WRAPPER *hSplitBinRend, const IVAS_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, @@ -1532,17 +1542,29 @@ ivas_error ivas_split_renderer_open( const int16_t pcm_out_flag, const int16_t is_5ms_frame ); +#endif void ivas_split_renderer_close( SPLIT_REND_WRAPPER *hSplitBinRend ); +#ifdef SPLIT_REND_LCLD_5MS +ivas_error ivas_splitBinLCLDEncOpen( + BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc, + const int32_t iSampleRate, + const int16_t iChannels, + const int32_t iDataRate, + const int16_t iNumBlocks, + const int16_t iNumIterations +); +#else ivas_error ivas_splitBinLCLDEncOpen( BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc, const int32_t iSampleRate, const int16_t iChannels, const int32_t iDataRate ); +#endif void ivas_splitBinLCLDEncClose( BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc @@ -1556,11 +1578,21 @@ void ivas_splitBinLCLDEncProcess( IVAS_SPLIT_REND_BITS_HANDLE pBits ); +#ifdef SPLIT_REND_LCLD_5MS +ivas_error ivas_splitBinLCLDDecOpen( + BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec, + const int32_t iSampleRate, + const int16_t iChannels, + const int16_t iNumBlocks, + const int16_t iNumIterations +); +#else ivas_error ivas_splitBinLCLDDecOpen( BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec, const int32_t iSampleRate, const int16_t iChannels ); +#endif void ivas_splitBinLCLDDecClose( BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec @@ -1670,26 +1702,59 @@ void ivas_splitBinRendPLCClose( SPLIT_REND_PLC_HANDLE* phSplitRendPLC ); +#ifdef SPLIT_REND_LCLD_5MS +void ivas_splitBinRendPLCsaveState( + SPLIT_REND_PLC_HANDLE hSplitRendPLC, + float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const int16_t num_chs, + const int16_t iNumBlocks, + const int16_t iNumIterations +); +#else void ivas_splitBinRendPLCsaveState( SPLIT_REND_PLC_HANDLE hSplitRendPLC, float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const int16_t num_chs ); +#endif +#ifdef SPLIT_REND_LCLD_5MS +void ivas_splitBinRendPLC_xf( + SPLIT_REND_PLC_HANDLE hSplitRendPLC, + float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const int16_t num_chs, + const int16_t iNumBlocks, + const int16_t iNumIterations +); +#else void ivas_splitBinRendPLC_xf( SPLIT_REND_PLC_HANDLE hSplitRendPLC, float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const int16_t num_chs ); +#endif +#ifdef SPLIT_REND_LCLD_5MS +void ivas_splitBinRendPLC( + SPLIT_REND_PLC_HANDLE hSplitRendPLC, + float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const int16_t num_chs, + const int16_t iNumBlocks, + const int16_t iNumIterations +); +#else void ivas_splitBinRendPLC( SPLIT_REND_PLC_HANDLE hSplitRendPLC, float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const int16_t num_chs ); +#endif #ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG void ivas_log_cldfb2wav_data( @@ -1970,6 +2035,12 @@ int32_t ivas_split_rend_bitstream_read_int32( const int32_t bits ); +#ifdef SPLIT_REND_LCLD_5MS +int32_t get_bit( + const int32_t state, + const int32_t bit_id +); +#endif void ivas_rend_closeCldfbRend( CLDFB_REND_WRAPPER *pCldfbRend @@ -2021,12 +2092,22 @@ void ivas_split_rend_get_quant_params( int16_t *num_complex_bands ); +#ifdef SPLIT_REND_LCLD_5MS +ivas_error ivas_split_rend_choose_default_codec( + IVAS_SPLIT_REND_CODEC *pCodec, /* i/o: pointer to codec setting */ + int16_t *pCodec_frame_size_ms, /* i/o: pointer to codec frame size setting */ + const int16_t cldfb_in_flag, /* i : flag indicating rendering in TD */ + const int16_t pcm_out_flag, /* i : flag to indicate PCM output */ + const int16_t num_subframes /* i : number of subframes */ +); +#else ivas_error ivas_split_rend_choose_default_codec( IVAS_SPLIT_REND_CODEC *pCodec, /* i/o: pointer to codec setting */ int16_t *pCodec_frame_size_ms, /* i/o: pointer to codec frame size setting */ const int16_t cldfb_in_flag, /* i : flag indicating rendering in CLDFB */ const int16_t pcm_out_flag /* i : flag to indicate PCM output */ ); +#endif #endif diff --git a/lib_rend/ivas_splitRend_lcld_dec.c b/lib_rend/ivas_splitRend_lcld_dec.c index 67b4c4cd5bcfc109377fa283dfbe1c59bb17f9c2..feb11fe89b7370e6d4b222c59c7c0887f80a3493 100644 --- a/lib_rend/ivas_splitRend_lcld_dec.c +++ b/lib_rend/ivas_splitRend_lcld_dec.c @@ -48,10 +48,19 @@ * *------------------------------------------------------------------------*/ +#ifdef SPLIT_REND_LCLD_5MS +ivas_error ivas_splitBinLCLDDecOpen( + BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec, + const int32_t iSampleRate, + const int16_t iChannels, + const int16_t iNumBlocks, + const int16_t iNumIterations ) +#else ivas_error ivas_splitBinLCLDDecOpen( BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec, const int32_t iSampleRate, const int16_t iChannels ) +#endif { int16_t n; BIN_HR_SPLIT_LCLD_DEC_HANDLE splitBinLCLDDec; @@ -65,10 +74,18 @@ ivas_error ivas_splitBinLCLDDecOpen( splitBinLCLDDec->pLcld_dec = NULL; /* place holder for CLDFB decoder handle */ splitBinLCLDDec->iChannels = iChannels; + +#ifndef SPLIT_REND_LCLD_5MS if ( ( error = CreateLCLDDecoder( &splitBinLCLDDec->psLCLDDecoder, iSampleRate, iChannels ) ) != IVAS_ERR_OK ) { return error; } +#else + if ( ( error = CreateLCLDDecoder( &splitBinLCLDDec->psLCLDDecoder, iSampleRate, iChannels, iNumBlocks ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif if ( ( splitBinLCLDDec->pppfDecLCLDReal = (float ***) malloc( iChannels * sizeof( float ** ) ) ) == NULL ) { @@ -108,6 +125,10 @@ ivas_error ivas_splitBinLCLDDecOpen( { return error; } +#ifdef SPLIT_REND_LCLD_5MS + splitBinLCLDDec->iNumBlocks = iNumBlocks; + splitBinLCLDDec->iNumIterations = iNumIterations; +#endif *hSplitBinLCLDDec = splitBinLCLDDec; @@ -171,7 +192,9 @@ void ivas_splitBinLCLDDecProcess( const int16_t bfi ) { int16_t k, n; - +#ifdef SPLIT_REND_LCLD_5MS + int16_t itr; +#endif push_wmops( "ivas_splitBinLCLDDecProcess" ); assert( hSplitBinLCLDDec != NULL ); @@ -184,9 +207,22 @@ void ivas_splitBinLCLDDecProcess( #endif if ( !bfi ) { - /* Initialized with zeros....... */ - for ( n = 0; n < hSplitBinLCLDDec->iChannels; n++ ) +#ifdef SPLIT_REND_LCLD_5MS + for ( itr = 0; itr < hSplitBinLCLDDec->iNumIterations; itr++ ) { +#endif + /* Initialized with zeros....... */ + for ( n = 0; n < hSplitBinLCLDDec->iChannels; n++ ) + { +#ifdef SPLIT_REND_LCLD_5MS + for ( k = 0; k < hSplitBinLCLDDec->iNumBlocks; k++ ) + { + hSplitBinLCLDDec->pppfDecLCLDReal[n][k] = Cldfb_Out_Real[n][hSplitBinLCLDDec->iNumBlocks * itr + k]; + hSplitBinLCLDDec->pppfDecLCLDImag[n][k] = Cldfb_Out_Imag[n][hSplitBinLCLDDec->iNumBlocks * itr + k]; + set_f( hSplitBinLCLDDec->pppfDecLCLDReal[n][k], 0, CLDFB_NO_CHANNELS_MAX ); + set_f( hSplitBinLCLDDec->pppfDecLCLDImag[n][k], 0, CLDFB_NO_CHANNELS_MAX ); + } +#else for ( k = 0; k < CLDFB_NO_COL_MAX; k++ ) { hSplitBinLCLDDec->pppfDecLCLDReal[n][k] = Cldfb_Out_Real[n][k]; @@ -194,43 +230,59 @@ void ivas_splitBinLCLDDecProcess( set_f( hSplitBinLCLDDec->pppfDecLCLDReal[n][k], 0, CLDFB_NO_CHANNELS_MAX ); set_f( hSplitBinLCLDDec->pppfDecLCLDImag[n][k], 0, CLDFB_NO_CHANNELS_MAX ); } - } +#endif + } - DecodeLCLDFrame( hSplitBinLCLDDec->psLCLDDecoder, pBits, hSplitBinLCLDDec->pppfDecLCLDReal, hSplitBinLCLDDec->pppfDecLCLDImag ); + DecodeLCLDFrame( hSplitBinLCLDDec->psLCLDDecoder, pBits, hSplitBinLCLDDec->pppfDecLCLDReal, hSplitBinLCLDDec->pppfDecLCLDImag ); #ifdef CLDFB_DEBUG - printf( "Frame Decoded = %d\n", ++hSplitBinLCLDDec->numFrame ); - int16_t writeByte = 0; - for ( k = 0; k < CLDFB_NO_COL_MAX; k++ ) - { - for ( int16_t b = 0; b < CLDFB_NO_CHANNELS_MAX; b++ ) + printf( "Frame Decoded = %d\n", ++hSplitBinLCLDDec->numFrame ); + int16_t writeByte = 0; + for ( k = 0; k < CLDFB_NO_COL_MAX; k++ ) { - for ( n = 0; n < hSplitBinLCLDDec->iChannels; n++ ) + for ( int16_t b = 0; b < CLDFB_NO_CHANNELS_MAX; b++ ) { - writeByte = fwrite( &hSplitBinLCLDDec->pppfDecLCLDReal[n][k][b], sizeof( float ), 1, hSplitBinLCLDDec->cldfbOut ); - if ( writeByte != 1 ) - exit( -1 ); - writeByte = fwrite( &hSplitBinLCLDDec->pppfDecLCLDImag[n][k][b], sizeof( float ), 1, hSplitBinLCLDDec->cldfbOut ); - if ( writeByte != 1 ) - exit( -1 ); + for ( n = 0; n < hSplitBinLCLDDec->iChannels; n++ ) + { + writeByte = fwrite( &hSplitBinLCLDDec->pppfDecLCLDReal[n][k][b], sizeof( float ), 1, hSplitBinLCLDDec->cldfbOut ); + if ( writeByte != 1 ) + exit( -1 ); + writeByte = fwrite( &hSplitBinLCLDDec->pppfDecLCLDImag[n][k][b], sizeof( float ), 1, hSplitBinLCLDDec->cldfbOut ); + if ( writeByte != 1 ) + exit( -1 ); + } } } - } #endif - if ( hSplitBinLCLDDec->hSplitRendPLC->prev_bfi != 0 ) - { - /* cross-fade recovered frame into good frame */ + if ( hSplitBinLCLDDec->hSplitRendPLC->prev_bfi != 0 ) + { + /* cross-fade recovered frame into good frame */ +#ifdef SPLIT_REND_LCLD_5MS + ivas_splitBinRendPLC_xf( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real, Cldfb_Out_Imag, (int16_t) hSplitBinLCLDDec->iChannels, hSplitBinLCLDDec->iNumBlocks, hSplitBinLCLDDec->iNumIterations ); +#else ivas_splitBinRendPLC_xf( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real, Cldfb_Out_Imag, (int16_t) hSplitBinLCLDDec->iChannels ); +#endif + } +#ifdef SPLIT_REND_LCLD_5MS } +#endif } else { /* do PLC for lost split renderer frame */ +#ifdef SPLIT_REND_LCLD_5MS + ivas_splitBinRendPLC( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real, Cldfb_Out_Imag, (int16_t) hSplitBinLCLDDec->iChannels, hSplitBinLCLDDec->iNumBlocks, hSplitBinLCLDDec->iNumIterations ); +#else ivas_splitBinRendPLC( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real, Cldfb_Out_Imag, (int16_t) hSplitBinLCLDDec->iChannels ); +#endif } /* save PLC state */ +#ifdef SPLIT_REND_LCLD_5MS + ivas_splitBinRendPLCsaveState( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real, Cldfb_Out_Imag, (int16_t) hSplitBinLCLDDec->iChannels, hSplitBinLCLDDec->iNumBlocks, hSplitBinLCLDDec->iNumIterations ); +#else ivas_splitBinRendPLCsaveState( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real, Cldfb_Out_Imag, (int16_t) hSplitBinLCLDDec->iChannels ); +#endif pop_wmops(); diff --git a/lib_rend/ivas_splitRend_lcld_enc.c b/lib_rend/ivas_splitRend_lcld_enc.c index b8dafa8a122e9ab2ce845020fcee96c2b907e7d0..c18d188d1d3801a58a22c053266153607204bfa0 100644 --- a/lib_rend/ivas_splitRend_lcld_enc.c +++ b/lib_rend/ivas_splitRend_lcld_enc.c @@ -47,11 +47,21 @@ * *------------------------------------------------------------------------*/ +#ifdef SPLIT_REND_LCLD_5MS +ivas_error ivas_splitBinLCLDEncOpen( + BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc, + const int32_t iSampleRate, + const int16_t iChannels, + const int32_t iDataRate, + const int16_t iNumBlocks, + const int16_t iNumIterations ) +#else ivas_error ivas_splitBinLCLDEncOpen( BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc, const int32_t iSampleRate, const int16_t iChannels, const int32_t iDataRate ) +#endif { BIN_HR_SPLIT_LCLD_ENC_HANDLE splitBinLCLDEnc; ivas_error error; @@ -61,13 +71,20 @@ ivas_error ivas_splitBinLCLDEncOpen( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); } - splitBinLCLDEnc->pLcld_enc = NULL; // place holder for CLDFB encoder handle + splitBinLCLDEnc->pLcld_enc = NULL; /* place holder for CLDFB encoder handle*/ splitBinLCLDEnc->iChannels = iChannels; +#ifdef SPLIT_REND_LCLD_5MS + if ( ( error = CreateLCLDEncoder( &( splitBinLCLDEnc->psLCLDEncoder ), iSampleRate, iChannels, iDataRate, 1, iNumBlocks, (int16_t) CLDFB_NO_COL_MAX / iNumBlocks ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = CreateLCLDEncoder( &( splitBinLCLDEnc->psLCLDEncoder ), iSampleRate, iChannels, iDataRate, 1 ) ) != IVAS_ERR_OK ) { return error; } +#endif if ( ( splitBinLCLDEnc->pppfLCLDReal = (float ***) malloc( iChannels * sizeof( float ** ) ) ) == NULL ) { @@ -90,6 +107,11 @@ ivas_error ivas_splitBinLCLDEncOpen( } } +#ifdef SPLIT_REND_LCLD_5MS + splitBinLCLDEnc->iNumIterations = iNumIterations; + splitBinLCLDEnc->iNumBlocks = iNumBlocks; +#endif + #ifdef CLDFB_DEBUG splitBinLCLDEnc->numFrame = 0; char cldfbFilename[50] = "cldfb_in_ref.qmf"; @@ -158,8 +180,11 @@ void ivas_splitBinLCLDEncProcess( const int32_t available_bits, IVAS_SPLIT_REND_BITS_HANDLE pBits ) { +#ifdef SPLIT_REND_LCLD_5MS + int32_t iBitsWritten, itr, available_bits_itr, rem_itr, available_bits_local; +#else int32_t iBitsWritten; - +#endif push_wmops( "ivas_splitBinLCLDEncProcess" ); assert( hSplitBinLCLDEnc != NULL ); @@ -167,7 +192,26 @@ void ivas_splitBinLCLDEncProcess( assert( Cldfb_In_Imag != NULL ); assert( pBits != NULL ); +#ifdef SPLIT_REND_LCLD_5MS + available_bits_local = available_bits; +#endif /* A conversion is needed for the 3d pointer interface here ........ */ +#ifdef SPLIT_REND_LCLD_5MS + for ( itr = 0; itr < hSplitBinLCLDEnc->iNumIterations; itr++ ) + { + + rem_itr = hSplitBinLCLDEnc->iNumIterations - itr; + available_bits_itr = available_bits_local / rem_itr; + + for ( int32_t n = 0; n < hSplitBinLCLDEnc->iChannels; n++ ) + { + for ( int32_t k = 0; k < hSplitBinLCLDEnc->iNumBlocks; k++ ) + { + hSplitBinLCLDEnc->pppfLCLDReal[n][k] = Cldfb_In_Real[n][hSplitBinLCLDEnc->iNumBlocks * itr + k]; + hSplitBinLCLDEnc->pppfLCLDImag[n][k] = Cldfb_In_Imag[n][hSplitBinLCLDEnc->iNumBlocks * itr + k]; + } + } +#else for ( int32_t n = 0; n < hSplitBinLCLDEnc->iChannels; n++ ) { for ( int32_t k = 0; k < CLDFB_NO_COL_MAX; k++ ) @@ -176,55 +220,83 @@ void ivas_splitBinLCLDEncProcess( hSplitBinLCLDEnc->pppfLCLDImag[n][k] = Cldfb_In_Imag[n][k]; } } +#endif #ifdef CLDFB_DEBUG - int16_t readByte = 0; - for ( int16_t k = 0; k < CLDFB_NO_COL_MAX; k++ ) - { - for ( int16_t b = 0; b < CLDFB_NO_CHANNELS_MAX; b++ ) + int16_t readByte = 0; +#ifdef SPLIT_REND_LCLD_5MS + for ( int16_t k = 0; k < hSplitBinLCLDEnc->iNumBlocks; k++ ) +#else + for ( int16_t k = 0; k < CLDFB_NO_COL_MAX; k++ ) +#endif { - for ( int16_t n = 0; n < hSplitBinLCLDEnc->iChannels; n++ ) + for ( int16_t b = 0; b < CLDFB_NO_CHANNELS_MAX; b++ ) { - readByte = fread( &Cldfb_In_Real[n][k][b], sizeof( float ), 1, hSplitBinLCLDEnc->cldfbIn ); - if ( readByte != 1 ) - break; - readByte = fread( &Cldfb_In_Imag[n][k][b], sizeof( float ), 1, hSplitBinLCLDEnc->cldfbIn ); + for ( int16_t n = 0; n < hSplitBinLCLDEnc->iChannels; n++ ) + { +#ifdef SPLIT_REND_LCLD_5MS + readByte = fread( &hSplitBinLCLDEnc->pppfLCLDReal[n][k][b], sizeof( float ), 1, hSplitBinLCLDEnc->cldfbIn ); + if ( readByte != 1 ) + break; + readByte = fread( &hSplitBinLCLDEnc->pppfLCLDReal[n][k][b], sizeof( float ), 1, hSplitBinLCLDEnc->cldfbIn ); +#else + readByte = fread( &Cldfb_In_Real[n][k][b], sizeof( float ), 1, hSplitBinLCLDEnc->cldfbIn ); + if ( readByte != 1 ) + break; + readByte = fread( &Cldfb_In_Imag[n][k][b], sizeof( float ), 1, hSplitBinLCLDEnc->cldfbIn ); +#endif + } } } - } - if ( readByte == 1 ) - { - printf( "Frame Read = %d\n", ++hSplitBinLCLDEnc->numFrame ); - } - else - { - printf( "Writing zeroes...\n" ); - for ( int16_T k = 0; k < CLDFB_NO_COL_MAX; k++ ) + if ( readByte == 1 ) { - for ( int16_t b = 0; b < CLDFB_NO_CHANNELS_MAX; b++ ) + printf( "Frame Read = %d\n", ++hSplitBinLCLDEnc->numFrame ); + } + else + { + printf( "Writing zeroes...\n" ); +#ifdef SPLIT_REND_LCLD_5MS + for ( int16_T k = 0; k < hSplitBinLCLDEnc->iNumBlocks; k++ ) +#else + for ( int16_T k = 0; k < CLDFB_NO_COL_MAX; k++ ) +#endif { - for ( int16_t n = 0; n < hSplitBinLCLDEnc->iChannels; n++ ) + for ( int16_t b = 0; b < CLDFB_NO_CHANNELS_MAX; b++ ) { - hSplitBinLCLDEnc->pppfLCLDReal[n][k][b] = 0.f; - hSplitBinLCLDEnc->pppfLCLDImag[n][k][b] = 0.f; + for ( int16_t n = 0; n < hSplitBinLCLDEnc->iChannels; n++ ) + { + hSplitBinLCLDEnc->pppfLCLDReal[n][k][b] = 0.f; + hSplitBinLCLDEnc->pppfLCLDImag[n][k][b] = 0.f; + } } } } - } #endif - +#ifdef SPLIT_REND_LCLD_5MS + EncodeLCLDFrame( hSplitBinLCLDEnc->psLCLDEncoder, hSplitBinLCLDEnc->pppfLCLDReal, hSplitBinLCLDEnc->pppfLCLDImag, &iBitsWritten, available_bits_itr, pBits ); +#else EncodeLCLDFrame( hSplitBinLCLDEnc->psLCLDEncoder, hSplitBinLCLDEnc->pppfLCLDReal, hSplitBinLCLDEnc->pppfLCLDImag, &iBitsWritten, available_bits, pBits ); +#endif +#ifdef SPLIT_REND_LCLD_5MS + available_bits_local -= iBitsWritten; +#ifdef DEBUGGING + assert( available_bits_local >= 0 ); +#endif +#else #ifdef DEBUGGING if ( iBitsWritten > available_bits ) assert( iBitsWritten <= available_bits ); #endif +#endif #ifdef CLDFB_DEBUG - printf( "Bits written = %d\n", iBitsWritten ); + printf( "Bits written = %d\n", iBitsWritten ); +#endif +#ifdef SPLIT_REND_LCLD_5MS + } #endif - pop_wmops(); return; diff --git a/lib_rend/ivas_splitRendererPLC.c b/lib_rend/ivas_splitRendererPLC.c index 4eca5672c41fea18521a7505f1038cc8e2e34a7d..197be5a39447cb641198aa8ac2d8b0e9a09e9a4b 100644 --- a/lib_rend/ivas_splitRendererPLC.c +++ b/lib_rend/ivas_splitRendererPLC.c @@ -74,6 +74,10 @@ static void adaptive_polar_ext_plc( float xf_alp[CLDFB_PLC_XF], float xf_bet[CLDFB_PLC_XF] #endif +#ifdef SPLIT_REND_LCLD_5MS + , + const int16_t iNumCols +#endif ) { float uth[CLDFB_NO_COL_MAX], uthu[CLDFB_NO_COL_MAX], urh[CLDFB_NO_COL_MAX]; @@ -82,6 +86,10 @@ static void adaptive_polar_ext_plc( float start_real, start_imag, abs_fac, abs_fac_powj, comp_fac, fac_powj_real, fac_powj_imag, temp, abs2inv; float fac_ph_real, fac_ph_imag, rat_real, rat_imag, abs_temp; int32_t k, j; +#ifndef SPLIT_REND_LCLD_5MS + int16_t iNumCols; + iNumCols = CLDFB_NO_COL_MAX; +#endif /* reset of accumulators */ ph_adj = 0.0f; @@ -91,7 +99,7 @@ static void adaptive_polar_ext_plc( sth = 0.0f; /* calculate per-sample phase and magnitude evolution in preceding frame */ - for ( k = 0; k < CLDFB_NO_COL_MAX; k++ ) + for ( k = 0; k < iNumCols; k++ ) { urh[k] = sqrtf( prev_imag[k] * prev_imag[k] + prev_real[k] * prev_real[k] ); if ( urh[k] < EPSILON ) @@ -134,14 +142,14 @@ static void adaptive_polar_ext_plc( } } - if ( k == CLDFB_NO_COL_MAX ) + if ( k == iNumCols ) { /* mean and stdev of per-sample magnitude ratios */ - drho *= 1.0f / ( CLDFB_NO_COL_MAX - 1 ); - temp = srho - ( CLDFB_NO_COL_MAX - 1 ) * SQR( drho ); + drho *= 1.0f / ( iNumCols - 1 ); + temp = srho - ( iNumCols - 1 ) * SQR( drho ); if ( temp > 0 ) { - srho = sqrtf( temp * ( 1.0f / ( CLDFB_NO_COL_MAX - 2 ) ) ); + srho = sqrtf( temp * ( 1.0f / ( iNumCols - 2 ) ) ); } else { @@ -149,11 +157,11 @@ static void adaptive_polar_ext_plc( } /* mean and stdev of per-sample phase differences */ - dth *= 1.0f / ( CLDFB_NO_COL_MAX - 1 ); - temp = sth - ( CLDFB_NO_COL_MAX - 1 ) * SQR( dth ); + dth *= 1.0f / ( iNumCols - 1 ); + temp = sth - ( iNumCols - 1 ) * SQR( dth ); if ( temp > 0 ) { - sth = sqrtf( temp * ( 1.0f / ( CLDFB_NO_COL_MAX - 2 ) ) ); + sth = sqrtf( temp * ( 1.0f / ( iNumCols - 2 ) ) ); } else { @@ -173,12 +181,12 @@ static void adaptive_polar_ext_plc( /* Calculate start value for evolution from last samples of previous frame */ fac_powj_real = fac_real; fac_powj_imag = fac_imag; - start_real = prev_real[CLDFB_NO_COL_MAX - 1]; - start_imag = prev_imag[CLDFB_NO_COL_MAX - 1]; + start_real = prev_real[iNumCols - 1]; + start_imag = prev_imag[iNumCols - 1]; for ( j = 1; j < START_VAL_AVG_LEN; j++ ) { - start_real += fac_powj_real * prev_real[CLDFB_NO_COL_MAX - j - 1] - fac_powj_imag * prev_imag[CLDFB_NO_COL_MAX - j - 1]; - start_imag += fac_powj_imag * prev_real[CLDFB_NO_COL_MAX - j - 1] + fac_powj_real * prev_imag[CLDFB_NO_COL_MAX - j - 1]; + start_real += fac_powj_real * prev_real[iNumCols - j - 1] - fac_powj_imag * prev_imag[iNumCols - j - 1]; + start_imag += fac_powj_imag * prev_real[iNumCols - j - 1] + fac_powj_real * prev_imag[iNumCols - j - 1]; temp = fac_powj_real * fac_real - fac_powj_imag * fac_imag; fac_powj_imag = fac_powj_imag * fac_real + fac_powj_real * fac_imag; fac_powj_real = temp; @@ -187,8 +195,8 @@ static void adaptive_polar_ext_plc( start_imag *= 1.0f / START_VAL_AVG_LEN; #else /* take last sample of previous frame as start value */ - start_real = prev_real[CLDFB_NO_COL_MAX - 1]; - start_imag = prev_imag[CLDFB_NO_COL_MAX - 1]; + start_real = prev_real[iNumCols - 1]; + start_imag = prev_imag[iNumCols - 1]; #endif #if DO_PERTURB != 0 @@ -211,7 +219,7 @@ static void adaptive_polar_ext_plc( /* apply complex evolution for first substitution sample */ rec_real[0] = rat_real * start_real - rat_imag * start_imag; rec_imag[0] = rat_imag * start_real + rat_real * start_imag; - for ( j = 2; j < CLDFB_NO_COL_MAX; j++ ) + for ( j = 2; j < iNumCols; j++ ) { /* make evolution less static: apply per samples differences as in preceding frame */ rat_real = ( prev_real[j] * prev_real[j - 1] + prev_imag[j] * prev_imag[j - 1] ); @@ -244,13 +252,13 @@ static void adaptive_polar_ext_plc( #endif rat_real *= abs2inv; rat_imag *= abs2inv; - rec_real[j + CLDFB_NO_COL_MAX - 2] = rat_real * rec_real[j + CLDFB_NO_COL_MAX - 3] - rat_imag * rec_imag[j + CLDFB_NO_COL_MAX - 3]; - rec_imag[j + CLDFB_NO_COL_MAX - 2] = rat_imag * rec_real[j + CLDFB_NO_COL_MAX - 3] + rat_real * rec_imag[j + CLDFB_NO_COL_MAX - 3]; + rec_real[j + iNumCols - 2] = rat_real * rec_real[j + iNumCols - 3] - rat_imag * rec_imag[j + iNumCols - 3]; + rec_imag[j + iNumCols - 2] = rat_imag * rec_real[j + iNumCols - 3] + rat_real * rec_imag[j + iNumCols - 3]; } #else rec_real[0] = fac_real * start_real - fac_imag * start_imag; rec_imag[0] = fac_imag * start_real + fac_real * start_imag; - for ( j = 1; j < CLDFB_NO_COL_MAX + CLDFB_PLC_XF; j++ ) + for ( j = 1; j < iNumCols + CLDFB_PLC_XF; j++ ) { rec_real[j] = fac_real * rec_real[j - 1] - fac_imag * rec_imag[j - 1]; rec_imag[j] = fac_imag * rec_real[j - 1] + fac_real * rec_imag[j - 1]; @@ -261,8 +269,8 @@ static void adaptive_polar_ext_plc( /* apply crossfade */ for ( j = 0; j < CLDFB_PLC_XF; j++ ) { - rec_real[CLDFB_NO_COL_MAX + j] *= xf_alp[j]; - rec_imag[CLDFB_NO_COL_MAX + j] *= xf_alp[j]; + rec_real[iNumCols + j] *= xf_alp[j]; + rec_imag[iNumCols + j] *= xf_alp[j]; xf_bet[j] = 1 - xf_alp[j]; } #endif @@ -273,7 +281,7 @@ static void adaptive_polar_ext_plc( Ruu_real[0] = SQR( prev_real[0] ) + SQR( prev_imag[0] ); Ruu_real[1] = 0; Ruu_imag[1] = 0; - for ( j = 1; j < CLDFB_NO_COL_MAX; j++ ) + for ( j = 1; j < iNumCols; j++ ) { Ruu_real[0] += SQR( prev_real[j] ) + SQR( prev_imag[j] ); Ruu_real[1] += prev_real[j] * prev_real[j - 1] + prev_imag[j] * prev_imag[j - 1]; @@ -296,12 +304,12 @@ static void adaptive_polar_ext_plc( fac_powj_imag = fac_imag; abs_fac = sqrtf( SQR( fac_real ) + SQR( fac_imag ) ); abs_fac_powj = abs_fac; - for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + for ( j = 0; j < iNumCols; j++ ) { comp_fac = 1 - abs_fac_powj; - rec_real[j] = prev_real[CLDFB_NO_COL_MAX - 1] * fac_powj_real - prev_imag[CLDFB_NO_COL_MAX - 1] * fac_powj_imag + + rec_real[j] = prev_real[iNumCols - 1] * fac_powj_real - prev_imag[iNumCols - 1] * fac_powj_imag + prev_real[j] * comp_fac; - rec_imag[j] = prev_real[CLDFB_NO_COL_MAX - 1] * fac_powj_imag + prev_imag[CLDFB_NO_COL_MAX - 1] * fac_powj_real + + rec_imag[j] = prev_real[iNumCols - 1] * fac_powj_imag + prev_imag[iNumCols - 1] * fac_powj_real + prev_imag[j] * comp_fac; abs_fac_powj = abs_fac_powj * abs_fac; temp = fac_powj_real * fac_real - fac_powj_imag * fac_imag; @@ -317,8 +325,8 @@ static void adaptive_polar_ext_plc( for ( j = 0; j < CLDFB_PLC_XF; j++ ) { xf_bet[j] = 1 - abs_fac_powj; - rec_real[j + CLDFB_NO_COL_MAX] = rec_real[CLDFB_NO_COL_MAX - 1] * fac_powj_real - rec_imag[CLDFB_NO_COL_MAX - 1] * fac_powj_imag; - rec_imag[j + CLDFB_NO_COL_MAX] = rec_real[CLDFB_NO_COL_MAX - 1] * fac_powj_imag + rec_imag[CLDFB_NO_COL_MAX - 1] * fac_powj_real; + rec_real[j + iNumCols] = rec_real[iNumCols - 1] * fac_powj_real - rec_imag[iNumCols - 1] * fac_powj_imag; + rec_imag[j + iNumCols] = rec_real[iNumCols - 1] * fac_powj_imag + rec_imag[iNumCols - 1] * fac_powj_real; abs_fac_powj = abs_fac_powj * abs_fac; temp = fac_powj_real * fac_real - fac_powj_imag * fac_imag; fac_powj_imag = fac_powj_real * fac_imag + fac_powj_imag * fac_real; @@ -329,7 +337,7 @@ static void adaptive_polar_ext_plc( } else { - for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + for ( j = 0; j < iNumCols; j++ ) { rec_real[j] = prev_real[j]; rec_imag[j] = prev_imag[j]; @@ -338,8 +346,8 @@ static void adaptive_polar_ext_plc( for ( j = 0; j < CLDFB_PLC_XF; j++ ) { xf_bet[j] = 1; - rec_real[j + CLDFB_NO_COL_MAX] = 0; - rec_imag[j + CLDFB_NO_COL_MAX] = 0; + rec_real[j + iNumCols] = 0; + rec_imag[j + iNumCols] = 0; } #endif } @@ -401,16 +409,30 @@ void ivas_splitBinRendPLCClose( * *------------------------------------------------------------------------*/ +#ifdef SPLIT_REND_LCLD_5MS +void ivas_splitBinRendPLCsaveState( + SPLIT_REND_PLC_HANDLE hSplitRendPLC, + float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const int16_t num_chs, + const int16_t iNumBlocks, + const int16_t iNumIterations ) +#else void ivas_splitBinRendPLCsaveState( SPLIT_REND_PLC_HANDLE hSplitRendPLC, float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const int16_t num_chs ) +#endif { int16_t k, n; - /* Save Cldfb frame */ +/* Save Cldfb frame */ +#ifdef SPLIT_REND_LCLD_5MS + for ( k = 0; k < ( iNumBlocks * iNumIterations ); k++ ) +#else for ( k = 0; k < CLDFB_NO_COL_MAX; k++ ) +#endif { for ( n = 0; n < num_chs; n++ ) { @@ -429,11 +451,21 @@ void ivas_splitBinRendPLCsaveState( * Cross-fade of preceding bad frame into good frame *------------------------------------------------------------------------*/ +#ifdef SPLIT_REND_LCLD_5MS +void ivas_splitBinRendPLC_xf( + SPLIT_REND_PLC_HANDLE hSplitRendPLC, + float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const int16_t num_chs, + const int16_t iNumBlocks, + const int16_t iNumIterations ) +#else void ivas_splitBinRendPLC_xf( SPLIT_REND_PLC_HANDLE hSplitRendPLC, float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const int16_t num_chs ) +#endif { int16_t n, i, k; @@ -452,8 +484,13 @@ void ivas_splitBinRendPLC_xf( #if CLDFB_PLC_XF > 0 for ( k = 0; k < CLDFB_PLC_XF; k++ ) { +#ifdef SPLIT_REND_LCLD_5MS + Cldfb_RealBuffer_Binaural[n][k][i] = hSplitRendPLC->CldfbPLC_state.xf_bet[n][i][k] * Cldfb_RealBuffer_Binaural[n][k][i] + hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinReal[n][k + ( iNumBlocks * iNumIterations )][i]; + Cldfb_ImagBuffer_Binaural[n][k][i] = hSplitRendPLC->CldfbPLC_state.xf_bet[n][i][k] * Cldfb_ImagBuffer_Binaural[n][k][i] + hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinImag[n][k + ( iNumBlocks * iNumIterations )][i]; +#else Cldfb_RealBuffer_Binaural[n][k][i] = hSplitRendPLC->CldfbPLC_state.xf_bet[n][i][k] * Cldfb_RealBuffer_Binaural[n][k][i] + hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinReal[n][k + CLDFB_NO_COL_MAX][i]; Cldfb_ImagBuffer_Binaural[n][k][i] = hSplitRendPLC->CldfbPLC_state.xf_bet[n][i][k] * Cldfb_ImagBuffer_Binaural[n][k][i] + hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinImag[n][k + CLDFB_NO_COL_MAX][i]; +#endif } #endif } @@ -469,11 +506,21 @@ void ivas_splitBinRendPLC_xf( * Conceal bad frame *------------------------------------------------------------------------*/ +#ifdef SPLIT_REND_LCLD_5MS +void ivas_splitBinRendPLC( + SPLIT_REND_PLC_HANDLE hSplitRendPLC, + float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const int16_t num_chs, + const int16_t iNumBlocks, + const int16_t iNumIterations ) +#else void ivas_splitBinRendPLC( SPLIT_REND_PLC_HANDLE hSplitRendPLC, float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const int16_t num_chs ) +#endif { int32_t i, n, k; float fade_fac; @@ -481,6 +528,11 @@ void ivas_splitBinRendPLC( #if CLDFB_PLC_XF > 0 float xf_alp[CLDFB_PLC_XF]; #endif +#ifdef SPLIT_REND_LCLD_5MS + int16_t iNumCols, fade_start_cntr, mute_cntr, fade_val; + + iNumCols = iNumBlocks * iNumIterations; +#endif /* Indicate that next transition will be from a bad frame */ hSplitRendPLC->prev_bfi = 1; @@ -497,7 +549,11 @@ void ivas_splitBinRendPLC( { for ( i = 0; i < CLDFB_NO_CHANNELS_MAX; i++ ) { +#ifdef SPLIT_REND_LCLD_5MS + for ( k = 0; k < iNumCols; k++ ) +#else for ( k = 0; k < CLDFB_NO_COL_MAX; k++ ) +#endif { prev_real[k] = hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinReal[n][k][i]; prev_imag[k] = hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinImag[n][k][i]; @@ -507,10 +563,18 @@ void ivas_splitBinRendPLC( #if CLDFB_PLC_XF > 0 , xf_alp, hSplitRendPLC->CldfbPLC_state.xf_bet[n][i] +#endif +#ifdef SPLIT_REND_LCLD_5MS + , + iNumCols #endif ); +#ifdef SPLIT_REND_LCLD_5MS + for ( k = 0; k < iNumCols; k++ ) +#else for ( k = 0; k < CLDFB_NO_COL_MAX; k++ ) +#endif { Cldfb_RealBuffer_Binaural[n][k][i] = rec_real[k]; hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinReal[n][k][i] = rec_real[k]; @@ -519,7 +583,11 @@ void ivas_splitBinRendPLC( } #if CLDFB_PLC_XF > 0 +#ifdef SPLIT_REND_LCLD_5MS + for ( k = iNumCols; k < iNumCols + CLDFB_PLC_XF; k++ ) +#else for ( k = CLDFB_NO_COL_MAX; k < CLDFB_NO_COL_MAX + CLDFB_PLC_XF; k++ ) +#endif { hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinReal[n][k][i] = rec_real[k]; hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinImag[n][k][i] = rec_imag[k]; @@ -529,7 +597,41 @@ void ivas_splitBinRendPLC( } - /* Check bf counter */ +/* Check bf counter */ +#ifdef SPLIT_REND_LCLD_5MS + fade_start_cntr = SR_PLC_FADE_START * CLDFB_NO_COL_MAX / iNumCols; + mute_cntr = SR_PLC_MUTE * CLDFB_NO_COL_MAX / iNumCols; + + if ( hSplitRendPLC->bf_count++ >= fade_start_cntr ) + { + if ( hSplitRendPLC->bf_count < mute_cntr ) + { + fade_val = ( ( hSplitRendPLC->bf_count - fade_start_cntr ) * iNumCols ) / CLDFB_NO_COL_MAX; + fade_fac = powf( 10, fade_val * SR_PLC_FADE_DEGREE / 20.0f ); + + for ( n = 0; n < num_chs; n++ ) + { + for ( k = 0; k < iNumCols; k++ ) + { + v_multc( &Cldfb_RealBuffer_Binaural[n][k][0], fade_fac, &Cldfb_RealBuffer_Binaural[n][k][0], (int16_t) CLDFB_NO_CHANNELS_MAX ); + v_multc( &Cldfb_ImagBuffer_Binaural[n][k][0], fade_fac, &Cldfb_ImagBuffer_Binaural[n][k][0], (int16_t) CLDFB_NO_CHANNELS_MAX ); + } + } + } + else + { + for ( n = 0; n < num_chs; n++ ) + { + for ( k = 0; k < iNumCols; k++ ) + { + set_zero( &Cldfb_RealBuffer_Binaural[n][k][0], (int16_t) CLDFB_NO_CHANNELS_MAX ); + set_zero( &Cldfb_ImagBuffer_Binaural[n][k][0], (int16_t) CLDFB_NO_CHANNELS_MAX ); + } + } + hSplitRendPLC->bf_count = mute_cntr; + } + } +#else if ( hSplitRendPLC->bf_count++ >= SR_PLC_FADE_START ) { if ( hSplitRendPLC->bf_count < SR_PLC_MUTE ) @@ -545,6 +647,7 @@ void ivas_splitBinRendPLC( hSplitRendPLC->bf_count = SR_PLC_MUTE; } } +#endif return; } diff --git a/lib_rend/ivas_splitRendererPre.c b/lib_rend/ivas_splitRendererPre.c index 7a208b82bd8bb79fbb8ce36596739103e7922ec8..b9dd7e9a7a9ef9be59fe4c3f73ac11de37808604 100644 --- a/lib_rend/ivas_splitRendererPre.c +++ b/lib_rend/ivas_splitRendererPre.c @@ -1795,16 +1795,28 @@ void ivas_init_split_rend_handles( * *------------------------------------------------------------------------*/ +#ifdef SPLIT_REND_LCLD_5MS +static ivas_error split_renderer_open_lc3plus( + SPLIT_REND_WRAPPER *hSplitRendWrapper, + const IVAS_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, + const int32_t OutSampleRate, + const int16_t num_subframes ) +#else static ivas_error split_renderer_open_lc3plus( SPLIT_REND_WRAPPER *hSplitRendWrapper, const IVAS_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, const int32_t OutSampleRate, const int16_t is_5ms_frame ) +#endif { ivas_error error; int16_t i, delayBufferLength; LC3PLUS_CONFIG config; +#ifdef SPLIT_REND_LCLD_5MS + config.lc3plus_frame_duration_us = pSplitRendConfig->codec_frame_size_ms * 1000; + config.ivas_frame_duration_us = ( pSplitRendConfig->dof == 0 ) ? config.lc3plus_frame_duration_us * num_subframes : 20000; +#else if ( is_5ms_frame ) { config.lc3plus_frame_duration_us = pSplitRendConfig->codec_frame_size_ms * 1000; @@ -1815,6 +1827,7 @@ static ivas_error split_renderer_open_lc3plus( config.lc3plus_frame_duration_us = 5000; config.ivas_frame_duration_us = 20000; } +#endif config.samplerate = OutSampleRate; config.channels = BINAURAL_CHANNELS; @@ -1872,6 +1885,15 @@ static ivas_error split_renderer_open_lc3plus( * *------------------------------------------------------------------------*/ +#ifdef SPLIT_REND_LCLD_5MS +ivas_error ivas_split_renderer_open( + SPLIT_REND_WRAPPER *hSplitRendWrapper, + const IVAS_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, + const int32_t OutSampleRate, + const int16_t cldfb_in_flag, + const int16_t pcm_out_flag, + const int16_t num_subframes ) +#else ivas_error ivas_split_renderer_open( SPLIT_REND_WRAPPER *hSplitRendWrapper, const IVAS_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, @@ -1879,6 +1901,7 @@ ivas_error ivas_split_renderer_open( const int16_t cldfb_in_flag, const int16_t pcm_out_flag, const int16_t is_5ms_frame ) +#endif { ivas_error error, ch, num_ch; #ifndef SPLIT_REND_WITH_HEAD_ROT @@ -1985,17 +2008,34 @@ ivas_error ivas_split_renderer_open( { if ( pSplitRendConfig->codec == IVAS_SPLIT_REND_CODEC_LC3PLUS ) { +#ifdef SPLIT_REND_LCLD_5MS + if ( ( error = split_renderer_open_lc3plus( hSplitRendWrapper, pSplitRendConfig, OutSampleRate, num_subframes ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = split_renderer_open_lc3plus( hSplitRendWrapper, pSplitRendConfig, OutSampleRate, is_5ms_frame ) ) != IVAS_ERR_OK ) { return error; } +#endif } else { +#ifdef SPLIT_REND_LCLD_5MS + int16_t iNumBlocksPerFrame; + iNumBlocksPerFrame = ( CLDFB_NO_COL_MAX * pSplitRendConfig->codec_frame_size_ms ) / 20; + + if ( ( error = ivas_splitBinLCLDEncOpen( &hSplitRendWrapper->hSplitBinLCLDEnc, OutSampleRate, BINAURAL_CHANNELS, ivas_get_lcld_bitrate( pSplitRendConfig->splitRendBitRate, hSplitRendWrapper->multiBinPoseData.poseCorrectionMode ), iNumBlocksPerFrame, 1 ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_splitBinLCLDEncOpen( &hSplitRendWrapper->hSplitBinLCLDEnc, OutSampleRate, BINAURAL_CHANNELS, ivas_get_lcld_bitrate( pSplitRendConfig->splitRendBitRate, hSplitRendWrapper->multiBinPoseData.poseCorrectionMode ) ) ) != IVAS_ERR_OK ) { return error; } +#endif } } @@ -2155,6 +2195,9 @@ static ivas_error ivas_renderMultiTDBinToSplitBinaural( uint8_t useLc3plus; float *in_delayed[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; int16_t i; +#ifdef SPLIT_REND_LCLD_5MS + int32_t num_slots; +#endif push_wmops( "ivas_renderMultiTDBinToSplitBinaural" ); @@ -2187,10 +2230,14 @@ static ivas_error ivas_renderMultiTDBinToSplitBinaural( actual_md_bits = pBits->bits_written; if ( ( hSplitBin->multiBinPoseData.poseCorrectionMode == IVAS_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) || ( !useLc3plus && !pcm_out_flag ) ) { +#ifndef SPLIT_REND_LCLD_5MS if ( !useLc3plus && codec_frame_size_ms != 20 && !pcm_out_flag ) { return IVAS_ERROR( IVAS_ERR_INVALID_INPUT_BUFFER_SIZE, "Unsupported framing for LCLD codec!" ); } +#else + num_slots = ( hSplitBin->multiBinPoseData.poseCorrectionMode == IVAS_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ? CLDFB_NO_COL_MAX : ( hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ); +#endif num_cldfb_bands = hSplitBin->hCldfbHandles->cldfbAna[0]->no_channels; /* CLDFB Analysis*/ @@ -2214,7 +2261,11 @@ static ivas_error ivas_renderMultiTDBinToSplitBinaural( #endif for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { +#ifdef SPLIT_REND_LCLD_5MS + for ( slot_idx = 0; slot_idx < num_slots; slot_idx++ ) +#else for ( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX; slot_idx++ ) +#endif { cldfbAnalysis_ts( &( in_delayed[pos_idx * BINAURAL_CHANNELS + ch][num_cldfb_bands * slot_idx] ), Cldfb_In_BinReal[pos_idx * BINAURAL_CHANNELS + ch][slot_idx], Cldfb_In_BinImag[pos_idx * BINAURAL_CHANNELS + ch][slot_idx], @@ -2240,10 +2291,17 @@ static ivas_error ivas_renderMultiTDBinToSplitBinaural( if ( !useLc3plus ) { +#ifdef SPLIT_REND_LCLD_5MS + available_bits = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC ); + actual_md_bits = pBits->bits_written - actual_md_bits; + available_bits -= actual_md_bits; + pBits->codec_frame_size_ms = codec_frame_size_ms; +#else available_bits = SplitRendBitRate * L_FRAME48k / 48000; actual_md_bits = pBits->bits_written - actual_md_bits; available_bits -= actual_md_bits; pBits->codec_frame_size_ms = 20; +#endif ivas_splitBinLCLDEncProcess( hSplitBin->hSplitBinLCLDEnc, Cldfb_In_BinReal, Cldfb_In_BinImag, available_bits, pBits ); } @@ -2270,7 +2328,11 @@ static ivas_error ivas_renderMultiTDBinToSplitBinaural( { if ( !useLc3plus ) { +#ifdef SPLIT_REND_LCLD_5MS + bit_len = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC ); +#else bit_len = SplitRendBitRate / FRAMES_PER_SEC; +#endif } else { @@ -2389,10 +2451,18 @@ ivas_error ivas_renderMultiBinToSplitBinaural( /* Needs to be done at runtime. If this was in another API function, * there would be no guarantee that the user did not change * the split rendering config before calling the main rendering function */ +#ifdef SPLIT_REND_LCLD_5MS + if ( ( error = ivas_split_rend_choose_default_codec( &splitCodec, &codec_frame_size_ms, cldfb_in_flag, pcm_out_flag, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_split_rend_choose_default_codec( &splitCodec, &codec_frame_size_ms, cldfb_in_flag, pcm_out_flag ) ) != IVAS_ERR_OK ) { return error; } +#endif + if ( cldfb_in_flag == 0 ) { @@ -2427,31 +2497,50 @@ ivas_error ivas_renderMultiBinToSplitBinaural( if ( splitCodec == IVAS_SPLIT_REND_CODEC_LCLD ) { +#ifdef SPLIT_REND_LCLD_5MS + available_bits = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC ); + actual_md_bits = pBits->bits_written - actual_md_bits; + available_bits -= actual_md_bits; + pBits->codec_frame_size_ms = codec_frame_size_ms; +#else available_bits = SplitRendBitRate * L_FRAME48k / 48000; actual_md_bits = pBits->bits_written - actual_md_bits; available_bits -= actual_md_bits; - +#endif ivas_splitBinLCLDEncProcess( hSplitBin->hSplitBinLCLDEnc, Cldfb_In_BinReal, Cldfb_In_BinImag, available_bits, pBits ); } else { +#ifdef SPLIT_REND_LCLD_5MS + int16_t ch, slot_idx, num_slots, ivas_fs; + ivas_fs = (int16_t) hSplitBin->hLc3plusEnc->config.ivas_frame_duration_us / 1000; + num_slots = (int16_t) ( CLDFB_NO_COL_MAX * ivas_fs ) / 20; +#else int16_t ch, slot_idx; - +#endif /* CLDFB synthesis of main pose */ for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { float *Cldfb_In_BinReal_p[CLDFB_NO_COL_MAX]; float *Cldfb_In_BinImag_p[CLDFB_NO_COL_MAX]; +#ifdef SPLIT_REND_LCLD_5MS + for ( slot_idx = 0; slot_idx < num_slots; slot_idx++ ) +#else for ( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX; slot_idx++ ) +#endif { Cldfb_In_BinReal_p[slot_idx] = Cldfb_In_BinReal[ch][slot_idx]; Cldfb_In_BinImag_p[slot_idx] = Cldfb_In_BinImag[ch][slot_idx]; } #ifndef SPLIT_REND_WITH_HEAD_ROT cldfbSynthesis( Cldfb_In_BinReal_p, Cldfb_In_BinImag_p, output[ch], hSplitBin->hCldfbHandles->cldfbAna[0]->no_channels * CLDFB_NO_COL_MAX, hSplitBin->hCldfbHandles->cldfbAna[ch] ); +#else +#ifdef SPLIT_REND_LCLD_5MS + cldfbSynthesis( Cldfb_In_BinReal_p, Cldfb_In_BinImag_p, output[ch], hSplitBin->hCldfbHandles->cldfbSyn[0]->no_channels * num_slots, hSplitBin->hCldfbHandles->cldfbSyn[ch] ); #else cldfbSynthesis( Cldfb_In_BinReal_p, Cldfb_In_BinImag_p, output[ch], hSplitBin->hCldfbHandles->cldfbSyn[0]->no_channels * CLDFB_NO_COL_MAX, hSplitBin->hCldfbHandles->cldfbSyn[ch] ); +#endif #endif } @@ -2488,7 +2577,6 @@ ivas_error ivas_renderMultiBinToSplitBinaural( } /*zero pad*/ - /*TODO: do this inside the LCLD ENC codec */ if ( pcm_out_flag ) { bit_len = SplitRendBitRate / FRAMES_PER_SEC; @@ -2497,7 +2585,11 @@ ivas_error ivas_renderMultiBinToSplitBinaural( { if ( splitCodec == IVAS_SPLIT_REND_CODEC_LCLD ) { +#ifdef SPLIT_REND_LCLD_5MS + bit_len = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC ); +#else bit_len = SplitRendBitRate / FRAMES_PER_SEC; +#endif } else { diff --git a/lib_rend/ivas_splitRenderer_utils.c b/lib_rend/ivas_splitRenderer_utils.c index ac1f15abcd318ebbb725584308081bd12c487231..c330a63f881406d02751fadba9b1fcb546a193a6 100644 --- a/lib_rend/ivas_splitRenderer_utils.c +++ b/lib_rend/ivas_splitRenderer_utils.c @@ -724,7 +724,11 @@ ivas_error ivas_split_rend_validate_config( if ( pSplitRendConfig->codec_frame_size_ms != 0 ) /* 0 means "default for current codec", will be set to actual value at a later stage */ { +#ifdef SPLIT_REND_LCLD_5MS + if ( pSplitRendConfig->codec == IVAS_SPLIT_REND_CODEC_LCLD && pSplitRendConfig->codec_frame_size_ms != 5 && pSplitRendConfig->codec_frame_size_ms != 10 && pSplitRendConfig->codec_frame_size_ms != 20 ) +#else if ( pSplitRendConfig->codec == IVAS_SPLIT_REND_CODEC_LCLD && pSplitRendConfig->codec_frame_size_ms != 20 ) +#endif { return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "Invalid framing for LCLD codec" ); } @@ -1049,12 +1053,22 @@ void ivas_init_multi_bin_pose_data( * *------------------------------------------------------------------------*/ +#ifdef SPLIT_REND_LCLD_5MS +ivas_error ivas_split_rend_choose_default_codec( + IVAS_SPLIT_REND_CODEC *pCodec, /* i/o: pointer to codec setting */ + int16_t *pCodec_frame_size_ms, /* i/o: pointer to codec frame size setting */ + const int16_t cldfb_in_flag, /* i : flag indicating rendering in TD */ + const int16_t pcm_out_flag, /* i : flag to indicate PCM output */ + const int16_t num_subframes /* i : number of subframes */ +) +#else ivas_error ivas_split_rend_choose_default_codec( IVAS_SPLIT_REND_CODEC *pCodec, /* i/o: pointer to codec setting */ int16_t *pCodec_frame_size_ms, /* i/o: pointer to codec frame size setting */ const int16_t cldfb_in_flag, /* i : flag indicating rendering in TD */ const int16_t pcm_out_flag /* i : flag to indicate PCM output */ ) +#endif { if ( pcm_out_flag == 0 ) { @@ -1073,7 +1087,11 @@ ivas_error ivas_split_rend_choose_default_codec( switch ( *pCodec ) { case IVAS_SPLIT_REND_CODEC_LCLD: +#ifdef SPLIT_REND_LCLD_5MS + *pCodec_frame_size_ms = num_subframes * 5; +#else *pCodec_frame_size_ms = 20; +#endif break; case IVAS_SPLIT_REND_CODEC_LC3PLUS: case IVAS_SPLIT_REND_CODEC_NONE: @@ -1087,3 +1105,18 @@ ivas_error ivas_split_rend_choose_default_codec( return IVAS_ERR_OK; } #endif + +#ifdef SPLIT_REND_LCLD_5MS +/*-------------------------------------------------------------------* + * Function get_bit() + * + * + *-------------------------------------------------------------------*/ + +int32_t get_bit( + const int32_t state, + const int32_t bit_id ) +{ + return ( state & ( 1 << bit_id ) ); +} +#endif diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 47328d279d863cd486d0c29ce6d3dacf0fef06ed..35a7bce0be139ca5fd0de1295995c1d12e3d67ae 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1443,6 +1443,10 @@ typedef struct ivas_binaural_head_rot_split_rendering_lcld_enc_struct FILE *cldfbIn; int16_t numFrame; #endif +#ifdef SPLIT_REND_LCLD_5MS + int16_t iNumIterations; + int16_t iNumBlocks; +#endif } BIN_HR_SPLIT_LCLD_ENC, *BIN_HR_SPLIT_LCLD_ENC_HANDLE; @@ -1476,6 +1480,10 @@ typedef struct ivas_binaural_head_rot_split_rendering_lcld_dec_struct int16_t numFrame; #endif SPLIT_REND_PLC_HANDLE hSplitRendPLC; +#ifdef SPLIT_REND_LCLD_5MS + int16_t iNumBlocks; + int16_t iNumIterations; +#endif } BIN_HR_SPLIT_LCLD_DEC, *BIN_HR_SPLIT_LCLD_DEC_HANDLE; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index c788233a7abef4f87ea7d7553b142a7755b09480..2b98bb020c0046fcbabc874384f7c8d222ca5244 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -3117,8 +3117,18 @@ static void clearInputMasa( return; } - #ifdef SPLIT_REND_WITH_HEAD_ROT +#ifdef SPLIT_REND_LCLD_5MS +static ivas_error initSplitRend( + SPLIT_REND_WRAPPER *pSplitRendWrapper, + IVAS_REND_AudioBuffer *pSplitRendEncBuffer, + const IVAS_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, + IVAS_REND_HeadRotData headRotData, + const int32_t outputSampleRate, + const AUDIO_CONFIG outConfig, + const int16_t cldfb_in_flag, + const int16_t num_subframes ) +#else static ivas_error initSplitRend( SPLIT_REND_WRAPPER *pSplitRendWrapper, IVAS_REND_AudioBuffer *pSplitRendEncBuffer, @@ -3128,6 +3138,7 @@ static ivas_error initSplitRend( const AUDIO_CONFIG outConfig, const int16_t cldfb_in_flag, const int16_t is_5ms_frame ) +#endif { ivas_error error; IVAS_REND_AudioBufferConfig bufConfig; @@ -3143,10 +3154,17 @@ static ivas_error initSplitRend( ivas_renderSplitUpdateNoCorrectionPoseData( pSplit_rend_config, &pSplitRendWrapper->multiBinPoseData ); } +#ifdef SPLIT_REND_LCLD_5MS + if ( ( error = ivas_split_renderer_open( pSplitRendWrapper, pSplit_rend_config, outputSampleRate, cldfb_in_flag, outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM, num_subframes ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_split_renderer_open( pSplitRendWrapper, pSplit_rend_config, outputSampleRate, cldfb_in_flag, outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM, is_5ms_frame ) ) != IVAS_ERR_OK ) { return error; } +#endif /*allocate for CLDFB in and change to TD during process if needed*/ bufConfig.numSamplesPerChannel = MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL; @@ -3880,6 +3898,17 @@ ivas_error IVAS_REND_AddInput( int16_t cldfb_in_flag; cldfb_in_flag = getCldfbRendFlag( hIvasRend, getAudioConfigType( inConfig ) ); +#ifdef SPLIT_REND_LCLD_5MS + if ( ( error = ivas_split_rend_choose_default_codec( &hIvasRend->hRendererConfig->split_rend_config.codec, &hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms, cldfb_in_flag, hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM, hIvasRend->num_subframes ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = initSplitRend( &hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer, &hIvasRend->hRendererConfig->split_rend_config, hIvasRend->headRotData, hIvasRend->sampleRateOut, hIvasRend->outputConfig, cldfb_in_flag, hIvasRend->num_subframes ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_split_rend_choose_default_codec( &hIvasRend->hRendererConfig->split_rend_config.codec, &hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms, cldfb_in_flag, hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) != IVAS_ERR_OK ) { return error; @@ -3889,6 +3918,7 @@ ivas_error IVAS_REND_AddInput( { return error; } +#endif } #endif @@ -4367,6 +4397,12 @@ ivas_error IVAS_REND_GetDelay( { latency_ns += IVAS_FB_DEC_DELAY_NS; } +#ifdef SPLIT_REND_LCLD_5MS + else if ( hIvasRend->inputsSplitPost[i].splitPostRendWrapper.hSplitBinLCLDDec != NULL ) + { + latency_ns += IVAS_FB_DEC_DELAY_NS; + } +#endif max_latency_ns = max( max_latency_ns, latency_ns ); } } @@ -4758,6 +4794,17 @@ int16_t IVAS_REND_FeedRenderConfig( cldfb_in_flag = getCldfbRendFlag( hIvasRend, IVAS_REND_AUDIO_CONFIG_TYPE_UNKNOWN ); closeSplitRend( &hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer ); +#ifdef SPLIT_REND_LCLD_5MS + if ( ( error = ivas_split_rend_choose_default_codec( &hIvasRend->hRendererConfig->split_rend_config.codec, &hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms, cldfb_in_flag, hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM, hIvasRend->num_subframes ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = initSplitRend( &hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer, &hIvasRend->hRendererConfig->split_rend_config, hIvasRend->headRotData, hIvasRend->sampleRateOut, hIvasRend->outputConfig, cldfb_in_flag, hIvasRend->num_subframes ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_split_rend_choose_default_codec( &hIvasRend->hRendererConfig->split_rend_config.codec, &hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms, cldfb_in_flag, hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) != IVAS_ERR_OK ) { return error; @@ -4767,6 +4814,7 @@ int16_t IVAS_REND_FeedRenderConfig( { return error; } +#endif } #endif @@ -6948,6 +6996,10 @@ static ivas_error renderSplitBinauralWithPostRot( int16_t outBufNumSamplesPerChannel, outBufNumColPerChannel; int16_t numSamplesPerChannelCacheSize, numColPerChannelCacheSize; float *readPtr, *writePtr; +#ifdef SPLIT_REND_LCLD_5MS + LC3PLUS_CONFIG config; + int16_t iNumBlocksPerFrame, iNumLCLDIterationsPerFrame; +#endif isPostRendInputCldfb = 0; push_wmops( "renderSplitBinauralWithPostRot" ); @@ -6957,15 +7009,58 @@ static ivas_error renderSplitBinauralWithPostRot( hSplitBin = &splitBinInput->splitPostRendWrapper; convertBitsBufferToInternalBitsBuff( *splitBinInput->hBits, &bits ); +#ifdef SPLIT_REND_LCLD_5MS + config.lc3plus_frame_duration_us = bits.codec_frame_size_ms * 1000; + if ( pCombinedOrientationData->num_subframes != MAX_PARAM_SPATIAL_SUBFRAMES ) + { + if ( bits.codec == IVAS_SPLIT_REND_CODEC_LC3PLUS ) + { + config.ivas_frame_duration_us = ( bits.pose_correction == IVAS_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) ? config.lc3plus_frame_duration_us * pCombinedOrientationData->num_subframes : 20000; + } + else + { + config.ivas_frame_duration_us = ( bits.pose_correction == IVAS_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) ? config.lc3plus_frame_duration_us : 20000; + } + iNumLCLDIterationsPerFrame = 1; + } + else + { + config.ivas_frame_duration_us = 20000; + } + + if ( bits.codec_frame_size_ms > 0 ) + { + iNumLCLDIterationsPerFrame = (int16_t) config.ivas_frame_duration_us / ( 1000 * bits.codec_frame_size_ms ); + iNumLCLDIterationsPerFrame = max( 1, iNumLCLDIterationsPerFrame ); + iNumBlocksPerFrame = CLDFB_NO_COL_MAX * bits.codec_frame_size_ms / 20; + } + else + { + iNumLCLDIterationsPerFrame = 1; + iNumBlocksPerFrame = CLDFB_NO_COL_MAX; + } + + config.channels = BINAURAL_CHANNELS; + config.samplerate = *splitBinInput->base.ctx.pOutSampleRate; +#endif + if ( bits.codec == IVAS_SPLIT_REND_CODEC_LCLD && splitBinInput->splitPostRendWrapper.hSplitBinLCLDDec == NULL ) { +#ifdef SPLIT_REND_LCLD_5MS + if ( ( error = ivas_splitBinLCLDDecOpen( &splitBinInput->splitPostRendWrapper.hSplitBinLCLDDec, *splitBinInput->base.ctx.pOutSampleRate, BINAURAL_CHANNELS, iNumBlocksPerFrame, iNumLCLDIterationsPerFrame ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_splitBinLCLDDecOpen( &splitBinInput->splitPostRendWrapper.hSplitBinLCLDDec, *splitBinInput->base.ctx.pOutSampleRate, BINAURAL_CHANNELS ) ) != IVAS_ERR_OK ) { return error; } +#endif } else if ( bits.codec == IVAS_SPLIT_REND_CODEC_LC3PLUS && splitBinInput->splitPostRendWrapper.hLc3plusDec == NULL ) { +#ifndef SPLIT_REND_LCLD_5MS LC3PLUS_CONFIG config; if ( outAudio.config.numSamplesPerChannel == 240 ) @@ -6981,6 +7076,7 @@ static ivas_error renderSplitBinauralWithPostRot( config.channels = BINAURAL_CHANNELS; config.samplerate = *splitBinInput->base.ctx.pOutSampleRate; +#endif if ( ( error = IVAS_LC3PLUS_DEC_Open( config, &splitBinInput->splitPostRendWrapper.hLc3plusDec ) ) != IVAS_ERR_OK ) { @@ -7024,13 +7120,20 @@ static ivas_error renderSplitBinauralWithPostRot( { isPostRendInputCldfb = 1; } - +#ifdef SPLIT_REND_LCLD_5MS + preRendFrameSize_ms = (int16_t) ( config.ivas_frame_duration_us ) / 1000; +#else preRendFrameSize_ms = bits.codec == IVAS_SPLIT_REND_CODEC_LC3PLUS ? (int16_t) ( hSplitBin->hLc3plusDec->config.ivas_frame_duration_us ) / 1000 : 20; +#endif numSamplesPerChannelCacheSize = (int16_t) ( *splitBinInput->base.ctx.pOutSampleRate * ( preRendFrameSize_ms - bits.codec_frame_size_ms ) / 1000 ); outBufNumColPerChannel = MAX_PARAM_SPATIAL_SUBFRAMES; +#ifdef SPLIT_REND_LCLD_5MS + numColPerChannelCacheSize = ( iNumBlocksPerFrame * iNumLCLDIterationsPerFrame ) - outBufNumColPerChannel; +#else numColPerChannelCacheSize = CLDFB_NO_COL_MAX - outBufNumColPerChannel; +#endif for ( sf_idx = 0; sf_idx < pCombinedOrientationData->num_subframes; sf_idx++ ) { @@ -7053,7 +7156,11 @@ static ivas_error renderSplitBinauralWithPostRot( /* cache the remaining 15ms */ splitBinInput->numCachedSamples = numColPerChannelCacheSize; writePtr = splitBinInput->bufferData; +#ifdef SPLIT_REND_LCLD_5MS + for ( slotIdx = CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; slotIdx < ( iNumBlocksPerFrame * iNumLCLDIterationsPerFrame ); ++slotIdx ) +#else for ( slotIdx = CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; slotIdx < CLDFB_NO_COL_MAX; ++slotIdx ) +#endif { for ( chnlIdx = 0; chnlIdx < BINAURAL_CHANNELS; ++chnlIdx ) { @@ -7121,6 +7228,19 @@ static ivas_error renderSplitBinauralWithPostRot( else { copyBufferTo2dArray( splitBinInput->base.inputBuffer, tmpCrendBuffer ); +#ifdef SPLIT_REND_LCLD_5MS + if ( splitBinInput->numCachedSamples == 0 ) + { + preRendFrameSize_ms = (int16_t) ( config.ivas_frame_duration_us ) / 1000; + numSamplesPerChannelCacheSize = (int16_t) ( *splitBinInput->base.ctx.pOutSampleRate * preRendFrameSize_ms / 1000 ); + numSamplesPerChannelCacheSize -= outAudio.config.numSamplesPerChannel; + splitBinInput->numCachedSamples = numSamplesPerChannelCacheSize; + } + else + { + splitBinInput->numCachedSamples -= outAudio.config.numSamplesPerChannel; + } +#endif } /* apply pose correction if enabled */ @@ -8485,12 +8605,18 @@ ivas_error IVAS_REND_GetSplitBinauralBitstream( cldfb_in_flag = getCldfbRendFlag( hIvasRend, IVAS_REND_AUDIO_CONFIG_TYPE_UNKNOWN ); hIvasRend->splitRendEncBuffer.config.is_cldfb = cldfb_in_flag; - +#ifdef SPLIT_REND_LCLD_5MS + if ( hIvasRend->hRendererConfig->split_rend_config.dof == 0 || hIvasRend->hRendererConfig->split_rend_config.poseCorrectionMode == IVAS_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) + { + hIvasRend->splitRendEncBuffer.config.numSamplesPerChannel = outAudio.config.numSamplesPerChannel; + } +#else if ( hIvasRend->hRendererConfig->split_rend_config.codec == IVAS_SPLIT_REND_CODEC_LC3PLUS && ( hIvasRend->hRendererConfig->split_rend_config.dof == 0 || hIvasRend->hRendererConfig->split_rend_config.poseCorrectionMode == IVAS_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) ) { hIvasRend->splitRendEncBuffer.config.numSamplesPerChannel = hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms * hIvasRend->num_subframes * (int16_t) ( hIvasRend->sampleRateOut / 1000 ); } +#endif else { hIvasRend->splitRendEncBuffer.config.numSamplesPerChannel = (int16_t) ( hIvasRend->sampleRateOut / FRAMES_PER_SEC );