diff --git a/Workspace_msvc/lib_isar.vcxproj b/Workspace_msvc/lib_isar.vcxproj index 5bee827041dc1972467edee3601f784b4573bba5..fceeb731ced2445a5434805d422d30654718782a 100644 --- a/Workspace_msvc/lib_isar.vcxproj +++ b/Workspace_msvc/lib_isar.vcxproj @@ -197,4 +197,4 @@ - \ No newline at end of file + diff --git a/Workspace_msvc/lib_rend.vcxproj b/Workspace_msvc/lib_rend.vcxproj index 27d4a19a693cf86f60b3ce654912c65b4a7cbaa6..1d55ed1942020a6c9b8e85bb05eb8bcd93cdd398 100644 --- a/Workspace_msvc/lib_rend.vcxproj +++ b/Workspace_msvc/lib_rend.vcxproj @@ -138,6 +138,7 @@ + @@ -175,6 +176,7 @@ + diff --git a/Workspace_msvc/lib_rend.vcxproj.filters b/Workspace_msvc/lib_rend.vcxproj.filters index 63e83fc9b5938a8550c46a0c8ffb8fd79aa1f6eb..ebcb9060c5220e6778966be731913242dc30fdf0 100644 --- a/Workspace_msvc/lib_rend.vcxproj.filters +++ b/Workspace_msvc/lib_rend.vcxproj.filters @@ -116,6 +116,9 @@ rend_c + + rend_c + diff --git a/apps/decoder.c b/apps/decoder.c index a812a2a133cfa5b8bafb170fb1291c8926b14274..641445277586061a4bccca81e65d5d51c7aaa444 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -174,7 +174,11 @@ typedef struct static bool parseCmdlIVAS_dec( int16_t argc, char **argv, DecArguments *arg ); static void usage_dec( void ); static ivas_error decodeG192( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtfBinary, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ObjectEditFileReader *objectEditFileReader, ISAR_SPLIT_REND_BITS_DATA *splitRendBits, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +static ivas_error decodeVoIP( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtf, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ObjectEditFileReader *objectEditFileReader, ISAR_SPLIT_REND_BITS_DATA *splitRendBits, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); +#else static ivas_error decodeVoIP( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtfBinary, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ObjectEditFileReader *objectEditFileReader, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); +#endif static ivas_error load_hrtf_from_file( IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtfBinary, IVAS_DEC_HANDLE hIvasDec, const IVAS_AUDIO_CONFIG OutputConfig, const int32_t output_Fs ); #ifdef DEBUGGING static ivas_error printBitstreamInfoVoip( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HANDLE hIvasDec ); @@ -756,7 +760,11 @@ int main( if ( arg.voipMode ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + error = decodeVoIP( arg, hBsReader, &hHrtfBinary, headRotReader, externalOrientationFileReader, refRotReader, referenceVectorReader, objectEditFileReader, &splitRendBits, hIvasDec, pcmBuf ); +#else error = decodeVoIP( arg, hBsReader, &hHrtfBinary, headRotReader, externalOrientationFileReader, refRotReader, referenceVectorReader, objectEditFileReader, hIvasDec, pcmBuf ); +#endif } else { @@ -1952,7 +1960,11 @@ static ivas_error initOnFirstGoodFrame( for ( int16_t i = 0; i < numInitialBadFrames; ++i ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( isSplitRend ) +#else if ( *splitRendWriter != NULL ) +#endif { ISAR_SPLIT_REND_BITS_DATA splitRendBitsZero; splitRendBitsZero.bits_buf = NULL; @@ -1970,7 +1982,12 @@ static ivas_error initOnFirstGoodFrame( return error; } } + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( !isSplitCoded ) +#else else +#endif { if ( *pRemainingDelayNumSamples < *numOutSamples ) { @@ -2179,6 +2196,14 @@ static ivas_error decodeG192( return error; } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( !isSplitRend ) + { + /* Ensure split rendering output struct is not used when not outputting to a split rendering output configuration */ + splitRendBits = NULL; + } +#endif + if ( ( error = IVAS_DEC_is_split_rendering_coded_out( hIvasDec, &isSplitCoded ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_is_split_rendering_coded_out, code: %d\n", error ); @@ -2510,7 +2535,11 @@ static ivas_error decodeG192( } /* decode transport channels, do TSM and feed to renderer */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( ( error = IVAS_DEC_GetSamplesDecoder( hIvasDec, splitRendBits ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_DEC_GetSamplesDecoder( hIvasDec, isSplitRend, splitRendBits ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -3060,6 +3089,9 @@ static ivas_error decodeVoIP( RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ObjectEditFileReader *objectEditFileReader, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ISAR_SPLIT_REND_BITS_DATA *splitRendBits, +#endif IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ) { @@ -3109,6 +3141,29 @@ static ivas_error decodeVoIP( bool parametersAvailableForEditing = false; uint16_t nSamplesRendered; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + SplitFileReadWrite *splitRendWriter = NULL; + int16_t isSplitRend, isSplitCoded; + + if ( ( error = IVAS_DEC_is_split_rendering_enabled( hIvasDec, &isSplitRend ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_is_split_rendering_enabled, code: %d\n", error ); + return error; + } + + if ( !isSplitRend ) + { + /* Ensure split rendering output struct is not used when not outputting to a split rendering format */ + splitRendBits = NULL; + } + + if ( ( error = IVAS_DEC_is_split_rendering_coded_out( hIvasDec, &isSplitCoded ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_is_split_rendering_coded_out, code: %d\n", error ); + return error; + } +#endif + vec_pos_update = 0; if ( ( error = IVAS_DEC_GetRenderFramesizeMs( hIvasDec, &systemTimeInc_ms ) ) != IVAS_ERR_OK ) { @@ -3400,15 +3455,34 @@ static ivas_error decodeVoIP( /* decode and get samples */ while ( nSamplesRendered < nOutSamples ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( isSplitRend ) + { #ifdef SUPPORT_JBM_TRACEFILE - if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, writeJbmTraceFileFrameWrapper, jbmTraceWriter, &bitstreamReadDone, &nSamplesRendered, ¶metersAvailableForEditing, systemTime_ms ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_VoIP_GetSplitBinauralBitstream( hIvasDec, (void *) pcmBuf, splitRendBits, writeJbmTraceFileFrameWrapper, jbmTraceWriter, &bitstreamReadDone, &nSamplesRendered, ¶metersAvailableForEditing, systemTime_ms ) ) != IVAS_ERR_OK ) #else - if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, &bitstreamReadDone, ¶metersAvailableForEditing, systemTime_ms ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_VoIP_GetSplitBinauralBitstream( hIvasDec, (void *) pcmBuf, splitRendBits, &bitstreamReadDone, &nSamplesRendered, ¶metersAvailableForEditing, systemTime_ms ) ) != IVAS_ERR_OK ) #endif + { + fprintf( stderr, "\nError in IVAS_DEC_VoIP_GetSplitBinauralBitstream: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + } + else { - fprintf( stderr, "\nError in IVAS_DEC_VoIP_GetSamples: %s\n", IVAS_DEC_GetErrorMessage( error ) ); - goto cleanup; +#endif +#ifdef SUPPORT_JBM_TRACEFILE + if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, writeJbmTraceFileFrameWrapper, jbmTraceWriter, &bitstreamReadDone, &nSamplesRendered, ¶metersAvailableForEditing, systemTime_ms ) ) != IVAS_ERR_OK ) +#else + if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, &bitstreamReadDone, ¶metersAvailableForEditing, systemTime_ms ) ) != IVAS_ERR_OK ) +#endif + { + fprintf( stderr, "\nError in IVAS_DEC_VoIP_GetSamples: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP } +#endif if ( bitstreamReadDone == true ) { @@ -3488,9 +3562,15 @@ static ivas_error decodeVoIP( /* Once good frame decoded, catch up */ if ( decodedGoodFrame ) { +#ifndef FIX_1119_SPLIT_RENDERING_VOIP SplitFileReadWrite *splitRendWriter = NULL; +#endif +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( ( error = initOnFirstGoodFrame( hIvasDec, arg, numInitialBadFrames, &nOutSamples, &vec_pos_len, delayNumSamples_orig, &delayNumSamples, &delayTimeScale, +#else if ( ( error = initOnFirstGoodFrame( hIvasDec, arg, numInitialBadFrames, &nOutSamples, NULL, delayNumSamples_orig, &delayNumSamples, &delayTimeScale, +#endif &bsFormat, &afWriter, &masaWriter, ismWriters, &nOutChannels, &numObj, &splitRendWriter ) ) != IVAS_ERR_OK ) { fprintf( stderr, "Error in initOnFirstGoodFrame(): %s\n", IVAS_DEC_GetErrorMessage( error ) ); @@ -3506,19 +3586,35 @@ static ivas_error decodeVoIP( /* Write current frame */ if ( decodedGoodFrame ) { - if ( delayNumSamples < nOutSamples ) +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( isSplitRend ) { - if ( ( error = AudioFileWriter_write( afWriter, &pcmBuf[delayNumSamples * nOutChannels], nOutSamples * nOutChannels - ( delayNumSamples * nOutChannels ) ) ) != IVAS_ERR_OK ) + if ( split_rend_write_bitstream_to_file( splitRendWriter, splitRendBits->bits_buf, &splitRendBits->bits_read, &splitRendBits->bits_written ) != IVAS_ERR_OK ) { - fprintf( stderr, "\nOutput audio file writer error\n" ); + fprintf( stderr, "\nUnable to write to bitstream file!\n" ); goto cleanup; } - delayNumSamples = 0; } - else + + if ( !isSplitCoded ) { - delayNumSamples -= nOutSamples; +#endif + if ( delayNumSamples < nOutSamples ) + { + if ( ( error = AudioFileWriter_write( afWriter, &pcmBuf[delayNumSamples * nOutChannels], nOutSamples * nOutChannels - ( delayNumSamples * nOutChannels ) ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nOutput audio file writer error\n" ); + goto cleanup; + } + delayNumSamples = 0; + } + else + { + delayNumSamples -= nOutSamples; + } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP } +#endif /* Write ISM metadata to external file(s) */ if ( decodedGoodFrame && arg.outputConfig == IVAS_AUDIO_CONFIG_EXTERNAL ) @@ -3606,7 +3702,11 @@ static ivas_error decodeVoIP( goto cleanup; } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( nSamplesFlushed && !isSplitCoded ) +#else if ( nSamplesFlushed ) +#endif { /* Write current frame */ if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, nSamplesFlushed * nOutChannels ) ) != IVAS_ERR_OK ) @@ -3677,11 +3777,19 @@ static ivas_error decodeVoIP( *------------------------------------------------------------------------------------------*/ memset( pcmBuf, 0, delayNumSamples_orig[0] * nOutChannels * sizeof( int16_t ) ); - if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, delayNumSamples_orig[0] * nOutChannels ) ) != IVAS_ERR_OK ) + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( afWriter != NULL ) { - fprintf( stderr, "\nError writing output file: %s\n", ivas_error_to_string( error ) ); - goto cleanup; +#endif + if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, delayNumSamples_orig[0] * nOutChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing output file: %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP } +#endif /*------------------------------------------------------------------------------------------* * Printouts after decoding has finished @@ -3726,6 +3834,9 @@ cleanup: EVS_RTPDUMP_DEPACKER_close( &rtpdumpDepacker ); AudioFileWriter_close( &afWriter ); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + split_rend_reader_writer_close( &splitRendWriter ); +#endif JbmOffsetFileWriter_close( &jbmOffsetWriter ); #ifdef SUPPORT_JBM_TRACEFILE JbmTraceFileWriter_close( &jbmTraceWriter ); diff --git a/apps/isar_post_rend.c b/apps/isar_post_rend.c index e6c78bfed5ff938d9609a6494ee4c5cb002f6ced..3159548da417798d404345cf218d866fab139fa0 100644 --- a/apps/isar_post_rend.c +++ b/apps/isar_post_rend.c @@ -1068,6 +1068,19 @@ int main( fprintf( stderr, "\nISAR_POST_REND_FeedSplitBinauralBitstream failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; } + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + /* Set BFI if frame is empty */ + int16_t frameEmpty = (int16_t) ( bitsBuffer.config.bitsWritten == 0 ); + if ( frameEmpty ) + { + if ( ( error = ISAR_POST_REND_SetSplitRendBFI( hIsarPostRend, 1 ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error in ISAR_POST_REND_SetSplitRendBFI(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } + } +#endif } } diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 469f6f0ee67094f8880d3ca592013939156f4354..7820d28a04cdc65c459252ba30d1a613e582da12 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -5217,6 +5217,43 @@ void ivas_binaural_add_LFE( float *output_f[] /* o : synthesized core-coder transport channels/DirAC output */ ); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + +/*---------------------------------------------------------------------------------* + * Multi-pose ring buffer Prototypes +*-----------------------------------------------------------------------------------*/ + +ivas_error ivas_CLDFB_RINGBUF_Open( + ISAR_CLDFB_RINGBUF_HANDLE *ph, + const int16_t capacity_columns +); + +void ivas_CLDFB_RINGBUF_Close( + ISAR_CLDFB_RINGBUF_HANDLE *ph +); + +void ivas_CLDFB_RINGBUF_Push( + ISAR_CLDFB_RINGBUF_HANDLE h, + const float *real, + const float *imag, + const int16_t num_bands +); + +void ivas_CLDFB_RINGBUF_Pop( + ISAR_CLDFB_RINGBUF_HANDLE h, + float *real, + float *imag, + const int16_t num_bands +); + +void ivas_CLDFB_RINGBUF_GetByIdx( + ISAR_CLDFB_RINGBUF_HANDLE h, + float **p_real, + float **p_imag, + const int16_t idx +); + +#endif /*----------------------------------------------------------------------------------* * renderer prototypes diff --git a/lib_com/options.h b/lib_com/options.h index 0c8e51e7ec81c84fa3fcdba9e882430b974300ff..8826aa3420f1c5d07dc6cca2e78a927140656619 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -171,7 +171,8 @@ #define NONBE_1377_REND_DIRATT_CONF /* Eri: Issue 1377: Error in directivity attenuation configuration for both IVAS_dec and IVAS_rend */ #define FIX_1377_HANDLE_ERROR_CODE /* Eri: Add missing error code handling from IVAS_REND_SetObjectIDs */ #define FIX_1053_REVERB_RECONFIGURATION -#define TMP_FIX_1119_SPLIT_RENDERING_VOIP /* FhG: Add error check for unsupported config: split rendering with VoIP mode */ +#define FIX_1119_SPLIT_RENDERING_VOIP /* FhG: Add split rendering support to decoder in VoIP mode */ +#define TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR /* FhG: Temporary workaround for incorrect implementation of decoder flush with split rendering */ #define NONBE_1122_KEEP_EVS_MODE_UNCHANGED /* FhG: Disables fix for issue 1122 in EVS mode to keep BE tests green. This switch should be removed once the 1122 fix is added to EVS via a CR. */ #define FIX_938_COMPILER_WARNING /* FhG: Fix compiler warning in ivas_mdct_core_reconstruct() */ #define FIX_1376_MISSING_ISM_METADATA /* FhG: IVAS_rend: throw error if there exists an ISM input without a corresponding metadata file path */ diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c index 7d1336f45d563c2dfeaecb6d57253ffde298f288..142cac7e50c4a9bcd7045e83230561ddfcd2331f 100644 --- a/lib_dec/ivas_dirac_dec.c +++ b/lib_dec/ivas_dirac_dec.c @@ -1657,7 +1657,9 @@ static void binRenderer_split( float Cldfb_ImagBuffer_Binaural[][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Rotated Binaural signals */ float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ +#ifndef FIX_1119_SPLIT_RENDERING_VOIP const int16_t slot_idx_start, +#endif const int16_t num_freq_bands, const int16_t nchan_out ) { @@ -1687,8 +1689,16 @@ static void binRenderer_split( { for ( ch = 0; ch < nchan_out; ch++ ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ivas_CLDFB_RINGBUF_Push( + hSplitBinRend->hMultiBinCldfbData[pos_idx * BINAURAL_CHANNELS + ch], + Cldfb_RealBuffer_Binaural_loc[pos_idx][ch][slot_idx], + Cldfb_ImagBuffer_Binaural_loc[pos_idx][ch][slot_idx], + num_freq_bands ); +#else mvr2r( Cldfb_RealBuffer_Binaural_loc[pos_idx][ch][slot_idx], hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_idx_start + slot_idx], num_freq_bands ); mvr2r( Cldfb_ImagBuffer_Binaural_loc[pos_idx][ch][slot_idx], hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_idx_start + slot_idx], num_freq_bands ); +#endif } } } @@ -2443,7 +2453,11 @@ void ivas_dirac_dec_render_sf( if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { binRenderer_split( st_ivas->hBinRenderer, st_ivas->hSplitBinRend, st_ivas->hCombinedOrientationData, hSpatParamRendCom->subframe_nbslots[subframe_idx], - Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer, slot_idx_start, hSpatParamRendCom->num_freq_bands, st_ivas->hDecoderConfig->nchan_out ); + Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer, +#ifndef FIX_1119_SPLIT_RENDERING_VOIP + slot_idx_start, +#endif + hSpatParamRendCom->num_freq_bands, st_ivas->hDecoderConfig->nchan_out ); } else { diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 4d1d4decd9c344577d3fd7f8d3f49646d99fe44d..3576f19440641aa1d6312b66ebe82a00e6ef764c 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -1240,6 +1240,10 @@ ivas_error ivas_init_decoder_front( } } +#ifdef TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR + st_ivas->flushing = 0; +#endif + return error; } diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index ea4226932a7d679b317a09c5c20d0bd99d86cd2b..81994844110522b848771d9a23385b3bb033b50e 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -1399,6 +1399,12 @@ ivas_error ivas_jbm_dec_render( if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { nchan_out_syn_output = BINAURAL_CHANNELS * st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses; +#ifdef TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR + if ( st_ivas->flushing ) + { + nchan_out_syn_output = BINAURAL_CHANNELS; + } +#endif } else { diff --git a/lib_dec/ivas_mc_param_dec.c b/lib_dec/ivas_mc_param_dec.c index 22827d8b658e683e69f91fdc829bd46ac55b7206..e912222b579eb78c267f389129837e3a28ea5bcd 100644 --- a/lib_dec/ivas_mc_param_dec.c +++ b/lib_dec/ivas_mc_param_dec.c @@ -1787,8 +1787,16 @@ void ivas_param_mc_dec_render( { for ( ch = 0; ch < nchan_out_cldfb; ch++ ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ivas_CLDFB_RINGBUF_Push( + st_ivas->hSplitBinRend->hMultiBinCldfbData[pos_idx * BINAURAL_CHANNELS + ch], + Cldfb_RealBuffer_Binaural[pos_idx][ch][slot_idx], + Cldfb_ImagBuffer_Binaural[pos_idx][ch][slot_idx], + hParamMC->num_freq_bands ); +#else mvr2r( Cldfb_RealBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_idx_start + slot_idx], hParamMC->num_freq_bands ); mvr2r( Cldfb_ImagBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_idx_start + slot_idx], hParamMC->num_freq_bands ); +#endif } } } diff --git a/lib_dec/ivas_mc_paramupmix_dec.c b/lib_dec/ivas_mc_paramupmix_dec.c index 8ef994fb4fff87aed97f06743677a6be8da8d3e1..a95490b5c47469f3d10a74f45b857dbaabc08cc7 100644 --- a/lib_dec/ivas_mc_paramupmix_dec.c +++ b/lib_dec/ivas_mc_paramupmix_dec.c @@ -790,8 +790,16 @@ static void ivas_mc_paramupmix_dec_sf( { for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ivas_CLDFB_RINGBUF_Push( + st_ivas->hSplitBinRend->hMultiBinCldfbData[pos_idx * BINAURAL_CHANNELS + ch], + Cldfb_RealBuffer_Binaural[pos_idx][ch][slot_idx], + Cldfb_ImagBuffer_Binaural[pos_idx][ch][slot_idx], + maxBand ); +#else mvr2r( Cldfb_RealBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_index_start + slot_idx], maxBand ); mvr2r( Cldfb_ImagBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_index_start + slot_idx], maxBand ); +#endif } } } diff --git a/lib_dec/ivas_omasa_dec.c b/lib_dec/ivas_omasa_dec.c index 5d4cb7c0fa95721ec5bc30ab54e7ea395199dab5..43d881dd47c486fd52c1dc4362e4d4689fb568f2 100644 --- a/lib_dec/ivas_omasa_dec.c +++ b/lib_dec/ivas_omasa_dec.c @@ -782,9 +782,13 @@ ivas_error ivas_omasa_dirac_td_binaural_jbm( float data_separated_objects[BINAURAL_CHANNELS][L_FRAME48k]; ivas_error error; float *p_sepobj[BINAURAL_CHANNELS]; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float *re, *im; +#else int16_t slot_idx_start; slot_idx_start = st_ivas->hSpatParamRendCom->slots_rendered; +#endif for ( n = 0; n < BINAURAL_CHANNELS; n++ ) { @@ -825,9 +829,14 @@ ivas_error ivas_omasa_dirac_td_binaural_jbm( { cldfbAnalysis_ts( &( p_rend_obj[n][num_cldfb_bands * slot_idx] ), Cldfb_RealBuffer, Cldfb_ImagBuffer, num_cldfb_bands, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n] ); - /* note: this intentionally differs from OSBA by: no scaling by 0.5 */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ivas_CLDFB_RINGBUF_GetByIdx( st_ivas->hSplitBinRend->hMultiBinCldfbData[n], &re, &im, slot_idx - cldfb_slots ); + v_add( re, Cldfb_RealBuffer, re, num_cldfb_bands ); + v_add( im, Cldfb_ImagBuffer, im, num_cldfb_bands ); +#else v_add( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[n][slot_idx_start + slot_idx], Cldfb_RealBuffer, st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[n][slot_idx_start + slot_idx], num_cldfb_bands ); v_add( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[n][slot_idx_start + slot_idx], Cldfb_ImagBuffer, st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[n][slot_idx_start + slot_idx], num_cldfb_bands ); +#endif } } } diff --git a/lib_dec/ivas_osba_dec.c b/lib_dec/ivas_osba_dec.c index 7eb3d07356f76d258b206e5fb61efb145bada7e1..00025b6847b2d8f932d833ec503b42a2d417da61 100644 --- a/lib_dec/ivas_osba_dec.c +++ b/lib_dec/ivas_osba_dec.c @@ -137,9 +137,13 @@ ivas_error ivas_osba_dirac_td_binaural_jbm( float output_separated_objects[BINAURAL_CHANNELS][L_FRAME48k]; float *p_sepobj[BINAURAL_CHANNELS]; int16_t channel_offset; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float *re, *im; +#else int16_t slot_idx_start; slot_idx_start = st_ivas->hSpatParamRendCom->slots_rendered; +#endif for ( n = 0; n < BINAURAL_CHANNELS; n++ ) { @@ -158,7 +162,10 @@ ivas_error ivas_osba_dirac_td_binaural_jbm( if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { - int16_t slot_idx, num_cldfb_bands, b, nchan_transport_orig; + int16_t slot_idx, num_cldfb_bands, nchan_transport_orig; +#ifndef FIX_1119_SPLIT_RENDERING_VOIP + int16_t b; +#endif int16_t cldfb_slots; float Cldfb_RealBuffer[CLDFB_NO_CHANNELS_MAX]; float Cldfb_ImagBuffer[CLDFB_NO_CHANNELS_MAX]; @@ -179,6 +186,11 @@ ivas_error ivas_osba_dirac_td_binaural_jbm( { cldfbAnalysis_ts( &( output_f[n][num_cldfb_bands * slot_idx] ), Cldfb_RealBuffer, Cldfb_ImagBuffer, num_cldfb_bands, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n] ); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ivas_CLDFB_RINGBUF_GetByIdx( st_ivas->hSplitBinRend->hMultiBinCldfbData[n], &re, &im, slot_idx - cldfb_slots ); + v_add( re, Cldfb_RealBuffer, re, num_cldfb_bands ); + v_add( im, Cldfb_ImagBuffer, im, num_cldfb_bands ); +#else for ( b = 0; b < num_cldfb_bands; b++ ) { st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[n][slot_idx_start + slot_idx][b] = @@ -187,6 +199,7 @@ ivas_error ivas_osba_dirac_td_binaural_jbm( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[n][slot_idx_start + slot_idx][b] = st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[n][slot_idx_start + slot_idx][b] + Cldfb_ImagBuffer[b]; } +#endif } } } diff --git a/lib_dec/ivas_output_config.c b/lib_dec/ivas_output_config.c index 2175ecf089fcd01e0b077a340ba84de4ee96a381..fa4ff1c7d3459cd4586a99dea30ec4c68304619c 100644 --- a/lib_dec/ivas_output_config.c +++ b/lib_dec/ivas_output_config.c @@ -500,11 +500,21 @@ RENDERER_TYPE ivas_renderer_secondary_select( renderer_type = RENDERER_DISABLE; output_config = st_ivas->hDecoderConfig->output_config; - if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC && output_config == IVAS_AUDIO_CONFIG_BINAURAL ) + if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC && +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ( output_config == IVAS_AUDIO_CONFIG_BINAURAL || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#else + output_config == IVAS_AUDIO_CONFIG_BINAURAL +#endif + ) { renderer_type = RENDERER_BINAURAL_OBJECTS_TD; } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + else if ( st_ivas->ivas_format == SBA_ISM_FORMAT && st_ivas->ism_mode == ISM_SBA_MODE_DISC && ( output_config == IVAS_AUDIO_CONFIG_BINAURAL || output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else else if ( st_ivas->ivas_format == SBA_ISM_FORMAT && st_ivas->ism_mode == ISM_SBA_MODE_DISC && ( output_config == IVAS_AUDIO_CONFIG_BINAURAL || output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) +#endif { renderer_type = RENDERER_BINAURAL_OBJECTS_TD; } diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index a6cd975989778a89cebc7abcfdedc2a538e31210..ac6c6e42ba078e46db565eb0eba71c0faea38026 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -821,6 +821,7 @@ typedef struct renderer_struct * IVAS decoder specific ISAR wrapper structures *----------------------------------------------------------------------------------*/ +#ifndef FIX_1119_SPLIT_RENDERING_VOIP typedef struct { float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; @@ -828,18 +829,29 @@ typedef struct } ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA, *ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA_HANDLE; +#endif typedef struct { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS][2 * CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; /* Double space to account for TSM */ + float Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS][2 * CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; +#else float Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; float Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; +#endif IVAS_AUDIO_CONFIG config; } ISAR_DEC_SPLIT_REND_CLDFB_OUT_DATA, *ISAR_DEC_SPLIT_REND_CLDFB_OUT_DATA_HANDLE; typedef struct { - ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA_HANDLE hMultiBinCldfbData; /*scratch buffer for frame by frame processing*/ - ISAR_SPLIT_REND_BITS_HANDLE hSplitRendBits; /*scratch buffer for frame by frame processing*/ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + TD_RINGBUF_HANDLE hMultiBinTdData; + ISAR_CLDFB_RINGBUF_HANDLE hMultiBinCldfbData[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; +#else + ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA_HANDLE hMultiBinCldfbData; /*scratch buffer for frame by frame processing*/ +#endif + ISAR_SPLIT_REND_BITS_HANDLE hSplitRendBits; /*scratch buffer for frame by frame processing*/ SPLIT_REND_WRAPPER splitrend; ISAR_DEC_SPLIT_REND_CLDFB_OUT_DATA_HANDLE hCldfbDataOut; /*buffer to store cldfb data before binauralization*/ int16_t numTdSamplesPerChannelCached; @@ -1143,6 +1155,10 @@ typedef struct Decoder_Struct int16_t ism_extmeta_active; /* Extended metadata active in decoder */ int16_t ism_extmeta_cnt; /* Change frame counter for extended metadata */ +#ifdef TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR + int16_t flushing; +#endif + } Decoder_Struct; /* clang-format on */ diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index a53d8e1e852181aa3d73333168c61f1162d50226..d4032c36d75542c07232948397c8bb168b10fe59 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -117,7 +117,11 @@ static void store_JbmData( IVAS_DEC_VOIP *hVoIP, JB4_DATAUNIT_HANDLE dataUnit, c static ivas_error evs_dec_main( Decoder_Struct *st_ivas ); static ivas_error input_format_API_to_internal( IVAS_DEC_INPUT_FORMAT input_format, int16_t *bitstream_format_internal, int16_t *sdp_hf_only, const bool is_voip_enabled ); static void init_decoder_config( DECODER_CONFIG_HANDLE hDecoderConfig ); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +static ivas_error ivas_dec_setup_all( IVAS_DEC_HANDLE hIvasDec, uint8_t *nTransportChannels, ISAR_SPLIT_REND_BITS_DATA *splitRendBits ); +#else static ivas_error ivas_dec_setup_all( IVAS_DEC_HANDLE hIvasDec, uint8_t *nTransportChannels, const int16_t isSplitRend, ISAR_SPLIT_REND_BITS_DATA *splitRendBits ); +#endif static ivas_error apa_setup( IVAS_DEC_HANDLE hIvasDec, const bool isInitialized_voip, const uint16_t nTransportChannels ); static PCM_RESOLUTION pcm_type_API_to_internal( const IVAS_DEC_PCM_TYPE pcmType ); static void *pcm_buffer_offset( void *buffer, const IVAS_DEC_PCM_TYPE pcmType, const int32_t offset ); @@ -128,6 +132,10 @@ static ivas_error ivas_dec_reconfig_split_rend( Decoder_Struct *st_ivas ); static ivas_error ivas_dec_init_split_rend( Decoder_Struct *st_ivas ); static void ivas_destroy_handle_isar( ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE *hSplitBinRend_out ); static int16_t get_render_frame_size_ms( IVAS_RENDER_FRAMESIZE render_framesize ); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +static int16_t get_render_frame_size_samples( const DECODER_CONFIG_HANDLE hDecoderConfig ); +static int16_t ivas_dec_split_rend_cldfb_in( const RENDERER_TYPE renderer_type ); +#endif static void update_voip_rendered20ms( IVAS_DEC_HANDLE hIvasDec, const int16_t nSamplesRendered ); /*---------------------------------------------------------------------* @@ -646,6 +654,23 @@ ivas_error IVAS_DEC_GetRenderFramesize( return IVAS_ERR_OK; } + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +/*---------------------------------------------------------------------* + * get_render_frame_size_samples( ) + * + * + *---------------------------------------------------------------------*/ + +static int16_t get_render_frame_size_samples( + const DECODER_CONFIG_HANDLE hDecoderConfig /* i : configuration structure */ +) +{ + return (int16_t) ( hDecoderConfig->output_Fs * hDecoderConfig->render_framesize / ( FRAMES_PER_SEC * IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ) ); +} +#endif + + /*---------------------------------------------------------------------* * IVAS_DEC_GetGetRenderFramesizeSamples( ) * @@ -662,7 +687,11 @@ ivas_error IVAS_DEC_GetRenderFramesizeSamples( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + *render_framesize = get_render_frame_size_samples( hIvasDec->st_ivas->hDecoderConfig ); +#else *render_framesize = (int16_t) ( hIvasDec->st_ivas->hDecoderConfig->output_Fs * hIvasDec->st_ivas->hDecoderConfig->render_framesize / ( FRAMES_PER_SEC * IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ) ); +#endif return IVAS_ERR_OK; } @@ -1127,8 +1156,10 @@ ivas_error IVAS_DEC_ReadFormat( *---------------------------------------------------------------------*/ ivas_error IVAS_DEC_GetSamplesDecoder( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - const int16_t isSplitRend, /* i : split rendering enabled flag */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ +#ifndef FIX_1119_SPLIT_RENDERING_VOIP + const int16_t isSplitRend, /* i : split rendering enabled flag */ +#endif ISAR_SPLIT_REND_BITS_DATA *splitRendBits /* o : output split rendering bits */ ) { @@ -1162,7 +1193,11 @@ ivas_error IVAS_DEC_GetSamplesDecoder( * Setup all decoder parts (IVAS decoder, ISAR) *-----------------------------------------------------------------*/ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( ( error = ivas_dec_setup_all( hIvasDec, &nTransportChannels, splitRendBits ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_dec_setup_all( hIvasDec, &nTransportChannels, isSplitRend, splitRendBits ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1733,6 +1768,199 @@ ivas_error IVAS_DEC_PrepareRenderer( } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +/*---------------------------------------------------------------------* + * isar_get_frame_size( ) + * + * + *---------------------------------------------------------------------*/ + +static int16_t isar_get_frame_size( + Decoder_Struct *st_ivas /* i : IVAS decoder handle */ +) +{ + int32_t output_Fs; + int16_t nSamplesPerChannel; + + output_Fs = st_ivas->hDecoderConfig->output_Fs; + + if ( st_ivas->hDecoderConfig->render_framesize != IVAS_RENDER_FRAMESIZE_20MS && + ( st_ivas->hRenderConfig->split_rend_config.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE || + st_ivas->hRenderConfig->split_rend_config.dof == 0 ) ) + { + nSamplesPerChannel = (int16_t) ( output_Fs / FRAMES_PER_SEC / MAX_PARAM_SPATIAL_SUBFRAMES ); + nSamplesPerChannel *= (int16_t) st_ivas->hDecoderConfig->render_framesize; + } + else + { + nSamplesPerChannel = (int16_t) ( output_Fs / FRAMES_PER_SEC ); + } + + return nSamplesPerChannel; +} + + +/*---------------------------------------------------------------------* + * isar_render_poses( ) + * + * + *---------------------------------------------------------------------*/ + +static ivas_error isar_render_poses( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const int16_t nSamplesAsked, /* i : number of samples wanted by the caller */ + int16_t *nOutSamples, /* o : number of samples per channel written to output buffer */ + bool *needNewFrame /* o : indication that the decoder needs a new frame */ +) +{ + float pcmBuf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES * L_FRAME48k]; + Decoder_Struct *st_ivas; + ivas_error error; + int16_t numPoses; + + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + *needNewFrame = false; + + st_ivas = hIvasDec->st_ivas; + + numPoses = st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses; + + /* init flush buffer for rate switch if not already initizalized */ + if ( hIvasDec->flushbuffer == NULL ) + { + hIvasDec->flushbuffer = (void *) malloc( numPoses * BINAURAL_CHANNELS * hIvasDec->nSamplesFrame / IVAS_MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( float ) ); + if ( hIvasDec->flushbuffer == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate flush buffer" ); + } + hIvasDec->pcmType = IVAS_DEC_PCM_FLOAT; + set_zero( (float *) hIvasDec->flushbuffer, numPoses * BINAURAL_CHANNELS * hIvasDec->nSamplesFrame / IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ); + } + + /* render */ + if ( ( error = IVAS_DEC_GetSamplesRenderer( hIvasDec, nSamplesAsked, IVAS_DEC_PCM_FLOAT, pcmBuf, nOutSamples, needNewFrame ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( !hIvasDec->hasBeenFedFirstGoodFrame ) + { + return IVAS_ERR_OK; + } + + if ( !ivas_dec_split_rend_cldfb_in( st_ivas->renderer_type ) ) + { + ivas_TD_RINGBUF_PushInterleaved( st_ivas->hSplitBinRend->hMultiBinTdData, pcmBuf, *nOutSamples ); + } + + return error; +} + + +/*---------------------------------------------------------------------* + * isar_generate_metadata_and_bitstream( ) + * + * + *---------------------------------------------------------------------*/ + +static ivas_error isar_generate_metadata_and_bitstream( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + float **p_head_pose_buf, /* i/o: PCM buffer with head-pose data */ + int16_t nSamples, /* i : duration of audio (in samples per channel) for which metadata should be generated */ + ISAR_SPLIT_REND_BITS_DATA *splitRendBits /* o : output split rendering bits */ +) +{ + ivas_error error; + ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE hSplitBinRend; + int16_t max_band; + int16_t pcm_out_flag; + int16_t cldfb_in_flag; + int16_t ro_md_flag; + IVAS_QUATERNION Quaternion; + int16_t i, j, num_poses, num_cldfb_slots, n_samples_in_cldfb_slot; + float *p_Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX]; + float *p_Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX]; + + hSplitBinRend = st_ivas->hSplitBinRend; + + max_band = (int16_t) ( ( BINAURAL_MAXBANDS * st_ivas->hDecoderConfig->output_Fs ) / 48000 ); + pcm_out_flag = ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0; + cldfb_in_flag = ivas_dec_split_rend_cldfb_in( st_ivas->renderer_type ); + + if ( cldfb_in_flag ) + { + n_samples_in_cldfb_slot = NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); + assert( nSamples % n_samples_in_cldfb_slot == 0 ); + num_cldfb_slots = nSamples / n_samples_in_cldfb_slot; + + num_poses = hSplitBinRend->splitrend.multiBinPoseData.num_poses; + + for ( i = 0; i < BINAURAL_CHANNELS * num_poses; ++i ) + { + for ( j = 0; j < num_cldfb_slots; ++j ) + { + /* Save pointers to first CLDFB column in the ring buffer. Allows us to save + * significant amounts of memory by not copying CLDFB values into a separate buffer. */ + ivas_CLDFB_RINGBUF_GetByIdx( hSplitBinRend->hMultiBinCldfbData[i], &p_Cldfb_RealBuffer_Binaural[i][j], &p_Cldfb_ImagBuffer_Binaural[i][j], 0 ); + + /* Pop the CLDFB column we just saved pointers to. This is fine as long as we use + * the saved columns only before any new columns are pushed to the buffer - the new + * columns could potentially overwrite the old columns we wanted to use. + * This requirement is fulfilled in this case. */ + ivas_CLDFB_RINGBUF_Pop( hSplitBinRend->hMultiBinCldfbData[i], NULL, NULL, CLDFB_NO_CHANNELS_MAX ); + } + } + } + else + { + ivas_TD_RINGBUF_PopChannels( st_ivas->hSplitBinRend->hMultiBinTdData, p_head_pose_buf, nSamples ); + } + + + if ( st_ivas->hBinRendererTd != NULL ) + { + ro_md_flag = 1; + } + else + { + ro_md_flag = 0; + } + + if ( st_ivas->hHeadTrackData != NULL ) + { + Quaternion = st_ivas->hHeadTrackData->Quaternions[0]; + } + else + { + Quaternion.w = -3.0f; + Quaternion.x = 0.0f; + Quaternion.y = 0.0f; + Quaternion.z = 0.0f; + } + + if ( ( error = ISAR_PRE_REND_MultiBinToSplitBinaural( &hSplitBinRend->splitrend, + Quaternion, + st_ivas->hRenderConfig->split_rend_config.splitRendBitRate, + st_ivas->hRenderConfig->split_rend_config.codec, + st_ivas->hRenderConfig->split_rend_config.isar_frame_size_ms, + st_ivas->hRenderConfig->split_rend_config.codec_frame_size_ms, + splitRendBits, + p_Cldfb_RealBuffer_Binaural, + p_Cldfb_ImagBuffer_Binaural, + max_band, p_head_pose_buf, 1, cldfb_in_flag, pcm_out_flag, ro_md_flag ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} +#endif /* FIX_1119_SPLIT_RENDERING_VOIP */ + + /*---------------------------------------------------------------------* * IVAS_DEC_GetSamplesRenderer( ) * @@ -1879,6 +2107,70 @@ ivas_error IVAS_DEC_GetSplitBinauralBitstream( bool *needNewFrame /* o : indication that the decoder needs a new frame */ ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Decoder_Struct *st_ivas; + ivas_error error; + float head_pose_buf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES][L_FRAME48k]; + float *p_head_pose_buf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES]; + int16_t i; + int16_t pcm_out_flag; + int16_t numSamplesPerChannelToOutput; + + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + st_ivas = hIvasDec->st_ivas; + + if ( is_split_rendering_enabled( st_ivas->hDecoderConfig, st_ivas->hRenderConfig ) == 0 ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + pcm_out_flag = ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0; + numSamplesPerChannelToOutput = isar_get_frame_size( st_ivas ); + + if ( ( error = isar_render_poses( hIvasDec, numSamplesPerChannelToOutput, nOutSamples, needNewFrame ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( !hIvasDec->hasBeenFedFirstGoodFrame ) + { + return IVAS_ERR_OK; + } + + for ( i = 0; i < BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES; ++i ) + { + p_head_pose_buf[i] = head_pose_buf[i]; + } + + if ( ( error = isar_generate_metadata_and_bitstream( st_ivas, p_head_pose_buf, *nOutSamples, splitRendBits ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* convert to int16 with limiting for BINAURAL_SPLIT_PCM */ + if ( pcm_out_flag ) + { + if ( st_ivas->hDecoderConfig->render_framesize == IVAS_RENDER_FRAMESIZE_5MS ) + { +#ifndef DISABLE_LIMITER + ivas_limiter_dec( st_ivas->hLimiter, p_head_pose_buf, st_ivas->hDecoderConfig->nchan_out, numSamplesPerChannelToOutput, st_ivas->BER_detect ); +#endif + } + else + { + ivas_limiter_dec( st_ivas->hLimiter, p_head_pose_buf, st_ivas->hDecoderConfig->nchan_out, numSamplesPerChannelToOutput, st_ivas->BER_detect ); + } + +#ifdef DEBUGGING + st_ivas->noClipping += +#endif + ivas_syn_output( p_head_pose_buf, numSamplesPerChannelToOutput, st_ivas->hDecoderConfig->nchan_out, (int16_t *) pcmBuf_out ); + } +#else Decoder_Struct *st_ivas; AUDIO_CONFIG output_config; int32_t output_Fs; @@ -2065,7 +2357,9 @@ ivas_error IVAS_DEC_GetSplitBinauralBitstream( #ifndef TMP_FIX_SPLIT_REND free( st_ivas->hSplitBinRend->hMultiBinCldfbData ); #endif - return error; +#endif + + return IVAS_ERR_OK; } @@ -2076,9 +2370,11 @@ ivas_error IVAS_DEC_GetSplitBinauralBitstream( *---------------------------------------------------------------------*/ static ivas_error ivas_dec_setup_all( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - uint8_t *nTransportChannels, /* o : number of decoded transport PCM channels */ - const int16_t isSplitRend, /* i : split rendering enabled flag */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + uint8_t *nTransportChannels, /* o : number of decoded transport PCM channels */ +#ifndef FIX_1119_SPLIT_RENDERING_VOIP + const int16_t isSplitRend, /* i : split rendering enabled flag */ +#endif ISAR_SPLIT_REND_BITS_DATA *splitRendBits /* o : output split rendering bits */ ) { @@ -2102,7 +2398,11 @@ static ivas_error ivas_dec_setup_all( st_ivas = hIvasDec->st_ivas; /* Setup IVAS split rendering */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( splitRendBits != NULL ) +#else if ( isSplitRend ) +#endif { if ( ( error = isar_set_split_rend_setup( st_ivas->hSplitBinRend, &st_ivas->hRenderConfig->split_rend_config, st_ivas->hCombinedOrientationData, splitRendBits ) ) != IVAS_ERR_OK ) { @@ -2134,7 +2434,11 @@ static ivas_error ivas_dec_setup_all( * - reconfigure the ISAR handle in case of bitrate switching (renderer might change) *-----------------------------------------------------------------*/ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( st_ivas->ini_frame == 0 && splitRendBits != NULL ) +#else if ( st_ivas->ini_frame == 0 && isSplitRend ) +#endif { if ( ( error = ivas_dec_init_split_rend( st_ivas ) ) != IVAS_ERR_OK ) { @@ -3446,26 +3750,44 @@ ivas_error IVAS_DEC_TSM_SetQuality( #endif +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + +/*---------------------------------------------------------------------* + * ivas_dec_voip_get_samples_common( ) + * + * Main function to output one frame in VoIP. Holds common code for + * regular output configs and split rendering configs. + *---------------------------------------------------------------------*/ + +static ivas_error ivas_dec_voip_get_samples_common + +#else /*---------------------------------------------------------------------* * IVAS_DEC_VoIP_GetSamples( ) * * Main function to decode one frame in VoIP *---------------------------------------------------------------------*/ -ivas_error IVAS_DEC_VoIP_GetSamples( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - uint16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ - const IVAS_DEC_PCM_TYPE pcmType, - void *pcmBuf, +ivas_error IVAS_DEC_VoIP_GetSamples +#endif + ( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + uint16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ + const IVAS_DEC_PCM_TYPE pcmType, /* i : type for the decoded PCM resolution */ + void *pcmBuf, /* o : output synthesis signal */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ISAR_SPLIT_REND_BITS_DATA *splitRendBits, /* o : output split rendering bits */ + float **p_head_pose_buf, /* i : PCM buffer with head-pose data */ +#endif #ifdef SUPPORT_JBM_TRACEFILE - JbmTraceFileWriterFn jbmWriterFn, - void *jbmWriter, + JbmTraceFileWriterFn jbmWriterFn, + void *jbmWriter, #endif - bool *bitstreamReadDone, /* o : flag indicating that bitstream was read */ - uint16_t *nSamplesRendered, /* o : number of samples rendered */ - bool *parametersAvailableForEditing, - const uint32_t systemTimestamp_ms /* i : current system timestamp */ -) + bool *bitstreamReadDone, /* o : flag indicating that bitstream was read */ + uint16_t *nSamplesRendered, /* o : number of samples rendered */ + bool *parametersAvailableForEditing, + const uint32_t systemTimestamp_ms /* i : current system timestamp */ + ) { Decoder_Struct *st_ivas; DECODER_CONFIG_HANDLE hDecoderConfig; @@ -3493,12 +3815,20 @@ ivas_error IVAS_DEC_VoIP_GetSamples( return IVAS_ERR_WRONG_PARAMS; } -#ifdef TMP_FIX_1119_SPLIT_RENDERING_VOIP +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( ( hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM || + hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && + splitRendBits == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } +#else if ( hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM || hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) { return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "Split rendering is not integrated with VoIP mode" ); } + #endif /* make sure that the FIFO after decoder/scaler contains at least one sound card frame (i.e. 20ms) */ @@ -3646,7 +3976,11 @@ ivas_error IVAS_DEC_VoIP_GetSamples( { if ( hIvasDec->nSamplesAvailableNext == 0 || hIvasDec->nSamplesAvailableNext == hIvasDec->nSamplesFrame ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( ( error = IVAS_DEC_GetSamplesDecoder( hIvasDec, splitRendBits ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_DEC_GetSamplesDecoder( hIvasDec, 0, 0 ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -3668,20 +4002,165 @@ ivas_error IVAS_DEC_VoIP_GetSamples( } } - /* render IVAS frames directly to the output buffer */ - if ( ( error = IVAS_DEC_GetSamplesRenderer( hIvasDec, nSamplesToRender, pcmType, pcm_buffer_offset( pcmBuf, pcmType, *nSamplesRendered * nOutChannels ), &nSamplesRendered_loop, &tmp ) ) != IVAS_ERR_OK ) +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( splitRendBits != NULL ) { - return error; + /* Render head poses from time-scaled transport channels */ + if ( ( error = isar_render_poses( hIvasDec, nSamplesToRender, &nSamplesRendered_loop, &tmp ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { +#endif + /* render IVAS frames directly to the output buffer */ + if ( ( error = IVAS_DEC_GetSamplesRenderer( hIvasDec, nSamplesToRender, pcmType, pcm_buffer_offset( pcmBuf, pcmType, *nSamplesRendered * nOutChannels ), &nSamplesRendered_loop, &tmp ) ) != IVAS_ERR_OK ) + { + return error; + } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP } +#endif *nSamplesRendered += nSamplesRendered_loop; update_voip_rendered20ms( hIvasDec, nSamplesRendered_loop ); } } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( hIvasDec->hasDecodedFirstGoodFrame && splitRendBits != NULL ) + { + /* Analyse head poses over entire frame, generate ISAR metadata and maybe encode if split coded */ + if ( ( error = isar_generate_metadata_and_bitstream( st_ivas, p_head_pose_buf, *nSamplesRendered, splitRendBits ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Synthesise PCM output if split PCM */ + if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + if ( st_ivas->hDecoderConfig->render_framesize == IVAS_RENDER_FRAMESIZE_5MS ) + { +#ifndef DISABLE_LIMITER + ivas_limiter_dec( st_ivas->hLimiter, p_head_pose_buf, st_ivas->hDecoderConfig->nchan_out, *nSamplesRendered, st_ivas->BER_detect ); +#endif + } + else + { + ivas_limiter_dec( st_ivas->hLimiter, p_head_pose_buf, st_ivas->hDecoderConfig->nchan_out, *nSamplesRendered, st_ivas->BER_detect ); + } + +#ifdef DEBUGGING + st_ivas->noClipping += +#endif + ivas_syn_output( p_head_pose_buf, *nSamplesRendered, st_ivas->hDecoderConfig->nchan_out, (int16_t *) pcmBuf ); + } + } +#endif + return IVAS_ERR_OK; } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + +/*---------------------------------------------------------------------* + * IVAS_DEC_VoIP_GetSamples( ) + * + * Main function to decode one frame in VoIP + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_VoIP_GetSamples( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + uint16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ + const IVAS_DEC_PCM_TYPE pcmType, /* i : type for the decoded PCM resolution */ + void *pcmBuf, /* o : output synthesis signal */ +#ifdef SUPPORT_JBM_TRACEFILE + JbmTraceFileWriterFn jbmWriterFn, + void *jbmWriter, +#endif + bool *bitstreamReadDone, /* o : flag indicating that bitstream was read */ + uint16_t *nSamplesRendered, /* o : number of samples rendered */ + bool *parametersAvailableForEditing, /* o : indicates whether objects editing is available */ + const uint32_t systemTimestamp_ms /* i : current system timestamp */ +) +{ + return ivas_dec_voip_get_samples_common( + hIvasDec, + nSamplesPerChannel, + pcmType, + pcmBuf, + NULL, + NULL, +#ifdef SUPPORT_JBM_TRACEFILE + jbmWriterFn, + jbmWriter, +#endif + bitstreamReadDone, + nSamplesRendered, + parametersAvailableForEditing, + systemTimestamp_ms ); +} + + +/*---------------------------------------------------------------------* + * IVAS_DEC_VoIP_GetSplitBinauralBitstream( ) + * + * Main function to decode one split-rendering frame in VoIP + *---------------------------------------------------------------------*/ + +/*! r: error code */ +ivas_error IVAS_DEC_VoIP_GetSplitBinauralBitstream( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + /* const IVAS_DEC_PCM_TYPE pcmType, */ /* i : type for the decoded PCM resolution */ + void *pcmBuf, /* o : output synthesis signal */ + ISAR_SPLIT_REND_BITS_DATA *splitRendBits, /* o : output split rendering bits */ +#ifdef SUPPORT_JBM_TRACEFILE + JbmTraceFileWriterFn jbmWriterFn, + void *jbmWriter, +#endif + bool *bitstreamReadDone, /* o : flag indicating that bitstream was read */ + uint16_t *nSamplesRendered, /* o : number of samples rendered */ + bool *parametersAvailableForEditing, /* o : indicates whether objects editing is available */ + const uint32_t systemTimestamp_ms /* i : current system timestamp */ +) +{ + int16_t i; + float head_pose_buf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES][L_FRAME48k]; + float *pp_head_pose_buf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES]; + ivas_error error = IVAS_ERR_UNKNOWN; + int16_t nSamplesPerChannel = 0; + + if ( ( error = IVAS_DEC_GetRenderFramesizeSamples( hIvasDec, &nSamplesPerChannel ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Set pointers to beginning of head pose buffers */ + for ( i = 0; i < BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES; ++i ) + { + pp_head_pose_buf[i] = head_pose_buf[i]; + } + + return ivas_dec_voip_get_samples_common( + hIvasDec, + nSamplesPerChannel, + IVAS_DEC_PCM_INT16, + pcmBuf, + splitRendBits, + pp_head_pose_buf, +#ifdef SUPPORT_JBM_TRACEFILE + jbmWriterFn, + jbmWriter, +#endif + bitstreamReadDone, + nSamplesRendered, + parametersAvailableForEditing, + systemTimestamp_ms ); +} +#endif + + /*---------------------------------------------------------------------* * update_voip_rendered20ms( ) * @@ -3732,6 +4211,10 @@ ivas_error IVAS_DEC_Flush( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } +#ifdef TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR + hIvasDec->st_ivas->flushing = 1; +#endif + *nSamplesFlushed = min( nSamplesPerChannel, hIvasDec->nSamplesAvailableNext ); nSamplesToRender = (uint16_t) *nSamplesFlushed; @@ -3747,6 +4230,10 @@ ivas_error IVAS_DEC_Flush( *nSamplesFlushed = 0; } +#ifdef TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR + hIvasDec->st_ivas->flushing = 0; +#endif + return error; } @@ -4775,6 +5262,9 @@ static ivas_error ivas_create_handle_isar( ) { ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE hSplitBinRend; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + int16_t i; +#endif if ( ( hSplitBinRend = (ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE) malloc( sizeof( ISAR_DEC_SPLIT_REND_WRAPPER ) ) ) == NULL ) { @@ -4783,7 +5273,15 @@ static ivas_error ivas_create_handle_isar( isar_init_split_rend_handles( &hSplitBinRend->splitrend ); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + hSplitBinRend->hMultiBinTdData = NULL; + for ( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; ++i ) + { + hSplitBinRend->hMultiBinCldfbData[i] = NULL; + } +#else hSplitBinRend->hMultiBinCldfbData = NULL; +#endif hSplitBinRend->hCldfbDataOut = NULL; hSplitBinRend->numTdSamplesPerChannelCached = 0; @@ -4803,13 +5301,31 @@ static void ivas_destroy_handle_isar( ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE *hSplitBinRend /* i/o: ISAR split binaural rendering handle */ ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + int16_t i; +#endif + if ( *hSplitBinRend != NULL ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( ( *hSplitBinRend )->hMultiBinTdData != NULL ) + { + ivas_TD_RINGBUF_Close( &( *hSplitBinRend )->hMultiBinTdData ); + } + for ( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; ++i ) + { + if ( ( *hSplitBinRend )->hMultiBinCldfbData[i] != NULL ) + { + ivas_CLDFB_RINGBUF_Close( &( *hSplitBinRend )->hMultiBinCldfbData[i] ); + } + } +#else #ifdef TMP_FIX_SPLIT_REND free( ( *hSplitBinRend )->hMultiBinCldfbData ); ( *hSplitBinRend )->hMultiBinCldfbData = NULL; - #endif +#endif + ISAR_PRE_REND_close( &( *hSplitBinRend )->splitrend, NULL ); if ( ( *hSplitBinRend )->hCldfbDataOut != NULL ) @@ -4982,6 +5498,32 @@ static ivas_error ivas_dec_reconfig_split_rend( } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +/*-------------------------------------------------------------------* + * ivas_dec_split_rend_cldfb_in() + * + * + *-------------------------------------------------------------------*/ + +static int16_t ivas_dec_split_rend_cldfb_in( + const RENDERER_TYPE renderer_type /* i : renderer type */ +) +{ + if ( renderer_type == RENDERER_BINAURAL_FASTCONV || + renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM || + renderer_type == RENDERER_BINAURAL_PARAMETRIC || + renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) + { + return 1; + } + else + { + return 0; + } +} +#endif + + /*-------------------------------------------------------------------* * ivas_dec_init_split_rend() * @@ -4995,10 +5537,16 @@ static ivas_error ivas_dec_init_split_rend( ivas_error error; int16_t cldfb_in_flag, pcm_out_flag; int16_t mixed_td_cldfb_flag; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + int16_t i, num_poses; +#endif pcm_out_flag = ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0; cldfb_in_flag = 0; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + cldfb_in_flag = ivas_dec_split_rend_cldfb_in( st_ivas->renderer_type ); +#else if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || @@ -5006,7 +5554,33 @@ static ivas_error ivas_dec_init_split_rend( { cldfb_in_flag = 1; } +#endif + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ISAR_PRE_REND_GetMultiBinPoseData( &st_ivas->hRenderConfig->split_rend_config, &st_ivas->hSplitBinRend->splitrend.multiBinPoseData, ( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->sr_pose_pred_axis : DEFAULT_AXIS ); + num_poses = st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses; + assert( num_poses <= MAX_HEAD_ROT_POSES ); + + if ( cldfb_in_flag ) + { + for ( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) + { + /* note: this is intra-frame heap memory */ + if ( ( error = ivas_CLDFB_RINGBUF_Open( &st_ivas->hSplitBinRend->hMultiBinCldfbData[i], CLDFB_NO_COL_MAX ) ) != IVAS_ERR_OK ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for split rendering structure" ); + } + } + } + else + { + if ( ( error = ivas_TD_RINGBUF_Open( &st_ivas->hSplitBinRend->hMultiBinTdData, get_render_frame_size_samples( st_ivas->hDecoderConfig ), num_poses * BINAURAL_CHANNELS ) ) != IVAS_ERR_OK ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for split rendering structure" ); + } + } +#else #ifdef TMP_FIX_SPLIT_REND /* note: this is intra-frame heap memory */ if ( ( st_ivas->hSplitBinRend->hMultiBinCldfbData = (ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA_HANDLE) malloc( sizeof( ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA ) ) ) == NULL ) @@ -5016,6 +5590,7 @@ static ivas_error ivas_dec_init_split_rend( #endif ISAR_PRE_REND_GetMultiBinPoseData( &st_ivas->hRenderConfig->split_rend_config, &st_ivas->hSplitBinRend->splitrend.multiBinPoseData, ( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->sr_pose_pred_axis : DEFAULT_AXIS ); +#endif if ( cldfb_in_flag == 1 && ( st_ivas->hSplitBinRend->splitrend.multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) ) { diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index 677405b52d19ca9588400d76cf0a59ad4ef7c606..8bc3a1fe1b28686fb1c4564c995ad6659fdf9cc1 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -160,7 +160,9 @@ ivas_error IVAS_DEC_ReadFormat( ivas_error IVAS_DEC_GetSamplesDecoder( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ +#ifndef FIX_1119_SPLIT_RENDERING_VOIP const int16_t isSplitRend, /* i : split rendering enabled flag */ +#endif ISAR_SPLIT_REND_BITS_DATA *splitRendBits /* o : output split rendering bits */ ); @@ -317,6 +319,24 @@ ivas_error IVAS_DEC_VoIP_GetSamples( const uint32_t systemTimestamp_ms /* i : current system timestamp */ ); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +/*! r: error code */ +ivas_error IVAS_DEC_VoIP_GetSplitBinauralBitstream( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + /* const IVAS_DEC_PCM_TYPE pcmType, */ /* i : type for the decoded PCM resolution */ + void *pcmBuf, /* o : output synthesis signal */ + ISAR_SPLIT_REND_BITS_DATA *splitRendBits, /* o : output split rendering bits */ +#ifdef SUPPORT_JBM_TRACEFILE + JbmTraceFileWriterFn jbmWriterFn, + void* jbmWriter, +#endif + bool *bitstreamReadDone, /* o : flag indicating that bitstream was read */ + uint16_t *nSamplesRendered, /* o : number of samples rendered */ + bool *parametersAvailableForEditing, /* o : indicates whether objects editing is available */ + const uint32_t systemTimestamp_ms /* i : current system timestamp */ +); +#endif + ivas_error IVAS_DEC_Flush( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ const int16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ diff --git a/lib_isar/isar_prot.h b/lib_isar/isar_prot.h index 85a99aa9036fece27de1acd48b5c387b3f6406f3..a81c5d34826e51e0e9f880d6ef0fa657c4be6cec 100644 --- a/lib_isar/isar_prot.h +++ b/lib_isar/isar_prot.h @@ -33,18 +33,21 @@ #ifndef ISAR_PROT_H #define ISAR_PROT_H - #include "isar_stat.h" - - #include #include "options.h" #include "ivas_error.h" #include "lib_isar_post_rend.h" + +/* clang-format off */ +/*----------------------------------------------------------------------------------* + * General ISAR prototypes + *----------------------------------------------------------------------------------*/ + ivas_error isar_splitBinPreRendOpen( - ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend, - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData + ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend, /* i/o: binaural pre-renderer handle */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData /* i/o: pose correction data handle */ #ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG , const int32_t output_Fs @@ -52,58 +55,75 @@ ivas_error isar_splitBinPreRendOpen( ); ivas_error split_renderer_open_lc3plus( - SPLIT_REND_WRAPPER *hSplitRendWrapper, - const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, - const int32_t OutSampleRate, - const IVAS_RENDER_FRAMESIZE ivas_frame_size ); + SPLIT_REND_WRAPPER *hSplitRendWrapper, /* i/o: Split renderer pre-renderer handle */ + const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, /* i : Split renderer pre-renderer config */ + const int32_t output_Fs, /* i : output sampling rate */ + const IVAS_RENDER_FRAMESIZE ivas_frame_size /* i : IVAS frame size */ +); void isar_splitBinPreRendClose( - ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend ); + ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend /* i/o: binaural pre-renderer handle */ +); void lc3plusTimeAlignCldfbPoseCorr( - SPLIT_REND_WRAPPER *hSplitBin, - float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] ); + SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renderer handle */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float *Cldfb_In_BinReal[][CLDFB_NO_COL_MAX], /* i/o: Binaural signals, real part */ + float *Cldfb_In_BinImag[][CLDFB_NO_COL_MAX] /* i/o: Binaural signals, imag. part */ +#else + float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: Binaural signals, real part */ + float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* i/o: Binaural signals, imag. part */ +#endif +); ivas_error splitRendLc3plusEncodeAndWrite( - SPLIT_REND_WRAPPER *hSplitBin, - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const int32_t available_bits, - float *in[] ); + SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renderer handle */ + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */ + const int32_t available_bits, /* i : available bit-budget */ + float *in[] /* i/o: PCM in/out buffer */ +); +/*! r: parameter value */ int32_t ISAR_SPLIT_REND_BITStream_read_int32( - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const int32_t bits ); + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */ + const int32_t bits /* i : number of bits to be read */ +); void ISAR_SPLIT_REND_BITStream_write_int32( - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const int32_t val, - const int32_t bits ); + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */ + const int32_t val, /* i : parameter value */ + const int32_t bits /* i : number of bits to be written */ +); ivas_error isar_splitBinLCLDEncOpen( - ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc, + ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc, /* o : ISAR LCLD encoder handle */ const int32_t iSampleRate, const int16_t iChannels, const int32_t iDataRate, const int16_t iNumBlocks, - const int16_t iNumIterations ); + const int16_t iNumIterations +); ivas_error isar_splitBinRendPLCOpen( - ISAR_SPLIT_REND_PLC_HANDLE *phSplitRendPLC, - const int16_t iNumSubSets ); + ISAR_SPLIT_REND_PLC_HANDLE *phSplitRendPLC, /* i/o: ISAR PLC handle */ + const int16_t iNumSubSets +); void isar_splitBinRendPLCClose( - ISAR_SPLIT_REND_PLC_HANDLE *phSplitRendPLC ); + ISAR_SPLIT_REND_PLC_HANDLE *phSplitRendPLC /* i/o: ISAR PLC handle */ +); ivas_error isar_splitBinLCLDDecOpen( - ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec, + ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec, /* i/o: ISAR LCLD decoder handle */ const int32_t iSampleRate, const int16_t iChannels, const int16_t iNumBlocks, - const int16_t iNumIterations ); + const int16_t iNumIterations +); void isar_splitBinLCLDDecClose( - ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec ); + ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec /* o : ISAR LCLD decoder handle */ +); void isar_splitBinRendPLCsaveState( ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC, @@ -111,7 +131,8 @@ void isar_splitBinRendPLCsaveState( 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 ); + const int16_t iNumIterations +); void isar_splitBinRendPLC_xf( ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC, @@ -121,7 +142,8 @@ void isar_splitBinRendPLC_xf( const int16_t iNumBlocks, const int16_t iNumIterations, int32_t **ppiDecodingFailed, - int32_t **ppiDecodingFailedPrev ); + int32_t **ppiDecodingFailedPrev +); void isar_splitBinRendPLC( ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC, @@ -130,7 +152,8 @@ void isar_splitBinRendPLC( const int16_t num_chs, const int16_t iNumBlocks, const int16_t iNumIterations, - int32_t **ppiDecodingFailed ); + int32_t **ppiDecodingFailed +); #ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG void isar_log_cldfb2wav_data( @@ -142,51 +165,66 @@ void isar_log_cldfb2wav_data( const int32_t output_Fs, const int16_t start_slot_idx, const int16_t md_band_idx, - const char *filename ); -#endif + const char *filename +); +#endif void isar_splitBinLCLDDecProcess( - ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE hSplitBinLCLDDec, - ISAR_SPLIT_REND_BITS_HANDLE pBits, - float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - const int16_t bfi ); + ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE hSplitBinLCLDDec, /* i/o: ISAR LCLD decoder handle */ + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */ + float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Binaural signals, real part */ + float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Binaural signals, imag. part */ + const int16_t bfi /* i : BFI flag */ +); void set_fix_rotation_mat( float fix_pos_rot_mat[][BINAURAL_CHANNELS][BINAURAL_CHANNELS], - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData /* i/o: pose correction data handle */ +); void isar_splitBinLCLDEncClose( - ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc ); + ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc /* i/o: ISAR LCLD encoder handle */ +); void isar_splitBinLCLDEncProcess( - ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE hSplitBinLCLDEnc, + ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE hSplitBinLCLDEnc, /* i/o: ISAR LCLD encoder handle */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float *Cldfb_In_Real[][CLDFB_NO_COL_MAX], /* i/o: Binaural signals, real part */ + float *Cldfb_In_Imag[][CLDFB_NO_COL_MAX], /* i/o: Binaural signals, imag. part */ +#else float Cldfb_In_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_In_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - const int32_t available_bits, - ISAR_SPLIT_REND_BITS_HANDLE pBits ); +#endif + const int32_t available_bits, /* i : available bit-budget */ + ISAR_SPLIT_REND_BITS_HANDLE pBits /* i/o: ISAR bits handle */ +); void set_pose_types( - ISAR_SPLIT_REND_POSE_TYPE pose_type[MAX_HEAD_ROT_POSES - 1], - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); + ISAR_SPLIT_REND_POSE_TYPE pose_type[MAX_HEAD_ROT_POSES - 1],/* o : ISAR pose type */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData /* i/o: pose correction data handle */ +); void isar_split_rend_init_huff_cfg( - ISAR_BIN_HR_SPLIT_REND_HUFF_HANDLE pHuff_cfg ); + ISAR_BIN_HR_SPLIT_REND_HUFF_HANDLE pHuff_cfg +); ivas_error isar_splitBinPostRendOpen( - ISAR_BIN_HR_SPLIT_POST_REND_HANDLE *hBinHrSplitPostRend, - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, - const int32_t output_Fs ); + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE *hBinHrSplitPostRend, /* i/o: binaural post-renderer handle */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */ + const int32_t output_Fs /* i : output sampling rate */ +); void isar_splitBinPostRendClose( - ISAR_BIN_HR_SPLIT_POST_REND_HANDLE *hBinHrSplitPostRend ); + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE *hBinHrSplitPostRend /* i/o: binaural post-renderer handle */ +); void isar_SplitRenderer_getdiagdiff( int16_t in_idx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], int16_t out_idx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], const int16_t sign, const int16_t min_val, - const int16_t max_val ); + const int16_t max_val +); void isar_split_rend_get_quant_params( const int16_t num_md_bands, @@ -200,24 +238,24 @@ void isar_split_rend_get_quant_params( int16_t pred_real_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS], int16_t pred_imag_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS], const int16_t ro_flag, - int16_t *num_quant_strats ); + int16_t *num_quant_strats +); void isar_splitBinPostRendMdDec( - ISAR_SPLIT_REND_BITS_HANDLE pBits, - ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend, + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */ + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend, /* i/o: binaural post-renderer handle */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData /* i/o: pose correction data handle */ #ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, - BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend -#else - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData + , + BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend /* i/o: binaural pre-renderer handle */ #endif ); void Quat2EulerDegree( - const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ - float *yaw, /* o : yaw */ - float *pitch, /* o : pitch */ - float *roll /* o : roll */ + const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ + float *yaw, /* o : yaw */ + float *pitch, /* o : pitch */ + float *roll /* o : roll */ ); void isar_mat_mult_2by2_complex( @@ -226,122 +264,141 @@ void isar_mat_mult_2by2_complex( float in_re2[2][2], float in_im2[2][2], float out_re2[2][2], - float out_im2[2][2] ); + float out_im2[2][2] +); void isar_rend_CldfbSplitPostRendProcess( - ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend, - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend, /* i/o: binaural post-renderer handle */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */ const IVAS_QUATERNION QuaternionPost, float Cldfb_RealBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float output[][L_FRAME48k], - const int16_t cldfb_in_flag ); + const int16_t cldfb_in_flag +); void isar_rend_CldfbSplitPreRendProcess( - const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, - const IVAS_QUATERNION headPosition, - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, - float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const int32_t target_md_bits, - const int16_t low_res_pre_rend_rot, - const int16_t ro_md_flag ); + const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, /* i : binaural pre-renderer handle */ + const IVAS_QUATERNION headPosition, /* i : head rotation QUATERNION */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float* Cldfb_In_BinReal[][CLDFB_NO_COL_MAX], /* i : Binaural signals, real part */ + float* Cldfb_In_BinImag[][CLDFB_NO_COL_MAX], /* i : Binaural signals, imag. part */ +#else + float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Binaural signals, real part */ + float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Binaural signals, imag. part */ +#endif + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */ + const int32_t target_md_bits, /* i : ISAR MD bitrate */ + const int16_t low_res_pre_rend_rot, /* i : low time resolution pre-renderer flag */ + const int16_t ro_md_flag /* i : real only metadata for yaw flag */ +); ivas_error isar_renderMultiTDBinToSplitBinaural( - SPLIT_REND_WRAPPER *hSplitBin, - const IVAS_QUATERNION headPosition, - const int32_t SplitRendBitRate, - const int16_t isar_frame_size_ms, - const int16_t codec_frame_size_ms, - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const int16_t max_bands, - float *in[], - const int16_t low_res_pre_rend_rot, - const int16_t pcm_out_flag, - const int16_t ro_md_flag ); + SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renderer handle */ + const IVAS_QUATERNION headPosition, /* i : head rotation QUATERNION */ + const int32_t SplitRendBitRate, /* i : ISAR bitrate */ + const int16_t isar_frame_size_ms, /* i : ISAR bit stream frame size in ms */ + const int16_t codec_frame_size_ms, /* i : ISAR frame length in ms */ + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */ + const int16_t max_bands, /* i : CLDFB bands */ + float *in[], /* i/o: PCM in/out buffer */ + const int16_t low_res_pre_rend_rot, /* i : low time resolution pre-renderer flag */ + const int16_t pcm_out_flag, /* i : flag to indicate PCM output */ + const int16_t ro_md_flag /* i : real only metadata for yaw flag */ +); void isar_init_multi_bin_pose_data( - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData /* i/o: pose correction data handle */ +); void isar_renderSplitGetMultiBinPoseData( - const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, - const ISAR_SPLIT_REND_ROT_AXIS rot_axis ); + const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, /* i : Split renderer pre-renderer config */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */ + const ISAR_SPLIT_REND_ROT_AXIS rot_axis /* i : external control for rotation axis for split rendering */ +); int16_t isar_renderSplitGetRot_axisNumBits( - const int16_t dof ); + const int16_t dof +); ISAR_SPLIT_REND_ROT_AXIS isar_renderSplitGetRot_axisFromCode( const int16_t dof, - const int16_t code ); + const int16_t code +); int16_t isar_renderSplitGetCodeFromRot_axis( const int16_t dof, const ISAR_SPLIT_REND_ROT_AXIS rot_axis, - int16_t *num_bits ); + int16_t *num_bits +); void isar_init_split_post_rend_handles( - ISAR_SPLIT_POST_REND_WRAPPER *hSplitRendWrapper ); + ISAR_SPLIT_POST_REND_WRAPPER *hSplitRendWrapper /* i/o: Split renderer post-renderer handle */ +); void isar_set_split_rend_ht_setup( - SPLIT_REND_WRAPPER *hSplitrend, - IVAS_QUATERNION Quaternions[MAX_PARAM_SPATIAL_SUBFRAMES], - float Rmat[MAX_PARAM_SPATIAL_SUBFRAMES][3][3] ); - + SPLIT_REND_WRAPPER *hSplitrend, /* i/o: Split renderer pre-renderer handle */ + IVAS_QUATERNION Quaternions[MAX_PARAM_SPATIAL_SUBFRAMES], /* i/o: External orientation in quaternions */ + float Rmat[MAX_PARAM_SPATIAL_SUBFRAMES][3][3] /* o : real-space rotation matrix */ +); int32_t isar_get_lc3plus_bitrate( - const int32_t SplitRendBitRate, - const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode, - const int32_t nChannels, - const int32_t codecFrameDurationUs ); + const int32_t SplitRendBitRate, /* i : ISAR bitrate */ + const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode, /* i : ISAR pose correction mode */ + const int32_t nChannels, /* i : number of channels */ + const int32_t lc3plus_frame_duration_us /* i : ISAR frame length in us */ +); ivas_error isar_split_rend_validate_config( - const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, - const int16_t pcm_out_flag ); + const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, /* i : Split renderer pre-renderer config */ + const int16_t pcm_out_flag /* i : flag to indicate PCM output */ +); +/*! r: LCLD codec bitrate */ int32_t isar_get_lcld_bitrate( - const int32_t SplitRendBitRate, - const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode ); - + const int32_t SplitRendBitRate, /* i : ISAR bitrate */ + const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode /* i : ISAR pose correction mode */ +); +/*! r: ISAR MD bitrate */ int32_t isar_get_split_rend_md_target_brate( - const int32_t SplitRendBitRate, - const int16_t pcm_out_flag ); + const int32_t SplitRendBitRate, /* i : ISAR bitrate */ + const int16_t pcm_out_flag /* i : flag to indicate PCM output */ +); ivas_error isar_framesize_to_ms( - const IVAS_RENDER_FRAMESIZE frame_size, /* i : frame size enum */ - int16_t *ms /* o : frame size in ms */ + const IVAS_RENDER_FRAMESIZE frame_size, /* i : frame size enum */ + int16_t *ms /* o : frame size in ms */ ); ivas_error isar_split_rend_choose_default_codec( - ISAR_SPLIT_REND_CODEC *pCodec, /* i/o: pointer to codec setting */ - int16_t *pIsar_frame_size_ms, /* i/o: pointer to isar frame size 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 */ + ISAR_SPLIT_REND_CODEC *pCodec, /* i/o: pointer to codec setting */ + int16_t *pIsar_frame_size_ms, /* i/o: pointer to ISAR frame size 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 */ ); -void ISAR_SPLIT_REND_BITStream_init( - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const int32_t buf_len_bytes, - uint8_t *pbuf ); - void isar_renderSplitUpdateNoCorrectionPoseData( - const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); + const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, /* i : Split renderer pre-renderer config */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData /* i/o: pose correction data handle */ +); int32_t get_bit( const int32_t state, - const int32_t bit_id ); + const int32_t bit_id +); +/*! r: ISAR audio type */ ISAR_POST_REND_AudioConfigType isar_getAudioConfigType( - const IVAS_AUDIO_CONFIG config ); + const IVAS_AUDIO_CONFIG config /* i : audio configuration */ +); void isar_init_split_rend_handles( - SPLIT_REND_WRAPPER *hSplitRendWrapper ); - + SPLIT_REND_WRAPPER *hSplitRendWrapper /* i/o: Split renderer pre-renderer handle */ +); /* clang-format on */ diff --git a/lib_isar/isar_splitRend_lcld_enc.c b/lib_isar/isar_splitRend_lcld_enc.c index 518c4226e658762e0f052a39c8486f33e3bf84f0..412e220adc701bfbbfca67b12459dd15595bdc43 100644 --- a/lib_isar/isar_splitRend_lcld_enc.c +++ b/lib_isar/isar_splitRend_lcld_enc.c @@ -157,10 +157,16 @@ void isar_splitBinLCLDEncClose( void isar_splitBinLCLDEncProcess( ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE hSplitBinLCLDEnc, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float *Cldfb_In_Real[][CLDFB_NO_COL_MAX], /* i/o: Binaural signals, real part */ + float *Cldfb_In_Imag[][CLDFB_NO_COL_MAX], /* i/o: Binaural signals, imag. part */ +#else float Cldfb_In_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_In_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - const int32_t available_bits, - ISAR_SPLIT_REND_BITS_HANDLE pBits ) +#endif + const int32_t available_bits, /* i : available bit-budget */ + ISAR_SPLIT_REND_BITS_HANDLE pBits /* i/o: ISAR bits handle */ +) { int32_t iBitsWritten, itr, available_bits_itr, rem_itr, available_bits_local; push_wmops( "isar_splitBinLCLDEncProcess" ); diff --git a/lib_isar/isar_splitRendererPre.c b/lib_isar/isar_splitRendererPre.c index 372c924ad091da283059d5618e3834f14ab739c9..734daae97719236aa4b692e5948eb65d5393e438 100644 --- a/lib_isar/isar_splitRendererPre.c +++ b/lib_isar/isar_splitRendererPre.c @@ -53,13 +53,16 @@ * Local function declarations *---------------------------------------------------------------------*/ -static void isar_SplitRenderer_GetRotMd( - ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, /* i/o: binaural renderer handle */ - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, - float Cldfb_RealBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Reference Binaural signals */ - float Cldfb_ImagBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Reference Binaural signals */ - const int16_t low_res, - const int16_t ro_md_flag ); +static void isar_SplitRenderer_GetRotMd( ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float *Cldfb_RealBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX], + float *Cldfb_ImagBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX], +#else + float Cldfb_RealBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float Cldfb_ImagBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], +#endif + const int16_t low_res, + const int16_t ro_md_flag ); /*------------------------------------------------------------------------- * Local functions @@ -276,11 +279,21 @@ static void ComputePostPredCov( static void ComputeBandedCrossCov( +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float *Cldfb_RealBuffer1[][CLDFB_NO_COL_MAX], + float *Cldfb_ImagBuffer1[][CLDFB_NO_COL_MAX], +#else float Cldfb_RealBuffer1[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer1[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], +#endif const int16_t ch_start_idx1, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float *Cldfb_RealBuffer2[][CLDFB_NO_COL_MAX], + float *Cldfb_ImagBuffer2[][CLDFB_NO_COL_MAX], +#else float Cldfb_RealBuffer2[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer2[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], +#endif const int16_t ch_start_idx2, float out_cov_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float out_cov_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS], @@ -345,8 +358,13 @@ static void ComputeBandedCrossCov( static void ComputeBandedCov( +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float *Cldfb_RealBuffer[][CLDFB_NO_COL_MAX], + float *Cldfb_ImagBuffer[][CLDFB_NO_COL_MAX], +#else float Cldfb_RealBuffer[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], +#endif const int16_t ch_start_idx, float out_cov_re[][BINAURAL_CHANNELS], float out_cov_im[][BINAURAL_CHANNELS], @@ -1335,9 +1353,14 @@ static void isar_SplitRenderer_quant_code( static void isar_SplitRenderer_GetRotMd( ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, /* i/o: binaural renderer handle */ - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float *Cldfb_RealBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX], /* o : Reference Binaural signals */ + float *Cldfb_ImagBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX], /* o : Reference Binaural signals */ +#else float Cldfb_RealBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Reference Binaural signals */ float Cldfb_ImagBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Reference Binaural signals */ +#endif const int16_t low_res, const int16_t ro_md_flag ) { @@ -1418,15 +1441,21 @@ static void isar_SplitRenderer_GetRotMd( *------------------------------------------------------------------------*/ void isar_rend_CldfbSplitPreRendProcess( - const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, - const IVAS_QUATERNION headPosition, - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, - float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const int32_t target_md_bits, - const int16_t low_res_pre_rend_rot, - const int16_t ro_md_flag ) + const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, /* i : binaural pre-renderer handle */ + const IVAS_QUATERNION headPosition, /* i : head rotation QUATERNION */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float *Cldfb_In_BinReal[][CLDFB_NO_COL_MAX], /* i : Binaural signals, real part */ + float *Cldfb_In_BinImag[][CLDFB_NO_COL_MAX], /* i : Binaural signals, imag. part */ +#else + float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Binaural signals, real part */ + float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Binaural signals, imag. part */ +#endif + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */ + const int32_t target_md_bits, /* i : ISAR MD bitrate */ + const int16_t low_res_pre_rend_rot, /* i : low time resolution pre-renderer flag */ + const int16_t ro_md_flag /* i : real only metadata for yaw flag */ +) { push_wmops( "isar_rend_CldfbSplitPreRendProcess" ); @@ -1873,6 +1902,11 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( uint8_t useLc3plus; float *in_delayed[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; int16_t i; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + int16_t j; + float *p_Cldfb_In_BinReal[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX]; + float *p_Cldfb_In_BinImag[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX]; +#endif int32_t num_slots; push_wmops( "isar_renderMultiTDBinToSplitBinaural" ); @@ -1882,6 +1916,17 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( useLc3plus = hSplitBin->hLc3plusEnc != NULL; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + for ( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; ++i ) + { + for ( j = 0; j < CLDFB_NO_COL_MAX; ++j ) + { + p_Cldfb_In_BinReal[i][j] = Cldfb_In_BinReal[i][j]; + p_Cldfb_In_BinImag[i][j] = Cldfb_In_BinImag[i][j]; + } + } +#endif + if ( useLc3plus ) { /*this should always have the time resolution of pose correction MD. Note that this does not change frame size of LC3plus*/ @@ -1944,7 +1989,21 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( target_md_bits = isar_get_split_rend_md_target_brate( SplitRendBitRate, pcm_out_flag ) * L_FRAME48k / 48000; - isar_rend_CldfbSplitPreRendProcess( hSplitBin->hBinHrSplitPreRend, headPosition, &hSplitBin->multiBinPoseData, Cldfb_In_BinReal, Cldfb_In_BinImag, pBits, target_md_bits, low_res_pre_rend_rot, ro_md_flag ); + isar_rend_CldfbSplitPreRendProcess( + hSplitBin->hBinHrSplitPreRend, + headPosition, + &hSplitBin->multiBinPoseData, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + p_Cldfb_In_BinReal, + p_Cldfb_In_BinImag, +#else + Cldfb_In_BinReal, + Cldfb_In_BinImag, +#endif + pBits, + target_md_bits, + low_res_pre_rend_rot, + ro_md_flag ); } if ( pcm_out_flag == 0 ) @@ -1959,7 +2018,17 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( pBits->codec_frame_size_ms = codec_frame_size_ms; pBits->isar_frame_size_ms = isar_frame_size_ms; - isar_splitBinLCLDEncProcess( hSplitBin->hSplitBinLCLDEnc, Cldfb_In_BinReal, Cldfb_In_BinImag, available_bits, pBits ); + isar_splitBinLCLDEncProcess( + hSplitBin->hSplitBinLCLDEnc, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + p_Cldfb_In_BinReal, + p_Cldfb_In_BinImag, +#else + Cldfb_In_BinReal, + Cldfb_In_BinImag, +#endif + available_bits, + pBits ); } else { @@ -2019,9 +2088,15 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( *------------------------------------------------------------------------*/ void lc3plusTimeAlignCldfbPoseCorr( - SPLIT_REND_WRAPPER *hSplitBin, - float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] ) + SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renderer handle */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float *Cldfb_In_BinReal[][CLDFB_NO_COL_MAX], /* i/o: Binaural signals, real part */ + float *Cldfb_In_BinImag[][CLDFB_NO_COL_MAX] /* i/o: Binaural signals, imag. part */ +#else + float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: Binaural signals, real part */ + float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* ii/: Binaural signals, imag. part */ +#endif +) { float Cldfb_In_BinReal_tmp[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][2][CLDFB_NO_CHANNELS_MAX]; float Cldfb_In_BinImag_tmp[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][2][CLDFB_NO_CHANNELS_MAX]; diff --git a/lib_isar/isar_splitRenderer_utils.c b/lib_isar/isar_splitRenderer_utils.c index 02dd552ef918b6b4e1d604d843c61d94192db62d..962e52ff19264cc19a08cb9f33ca6a30a9648f41 100644 --- a/lib_isar/isar_splitRenderer_utils.c +++ b/lib_isar/isar_splitRenderer_utils.c @@ -78,26 +78,6 @@ void isar_mat_mult_2by2_complex( } -/*------------------------------------------------------------------------- - * Function ISAR_SPLIT_REND_BITStream_init() - * - * - *------------------------------------------------------------------------*/ - -void ISAR_SPLIT_REND_BITStream_init( - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const int32_t buf_len_bytes, - uint8_t *pbuf ) -{ - pBits->bits_buf = pbuf; - pBits->buf_len = buf_len_bytes; - pBits->bits_read = 0; - pBits->bits_written = 0; - - return; -} - - /*------------------------------------------------------------------------- * Function isar_split_rend_huffman_dec_init_min_max_len() * diff --git a/lib_isar/isar_stat.h b/lib_isar/isar_stat.h index 587c3c8ea7309fc6a4fe0fe3cbc66dbebfdcd0f8..4ed75ee97e81e4ff1ebacd476bfc4f36f5732eb3 100644 --- a/lib_isar/isar_stat.h +++ b/lib_isar/isar_stat.h @@ -345,4 +345,17 @@ typedef struct } SPLIT_REND_WRAPPER; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +typedef struct +{ + float *real; + float *imag; + int32_t capacity; + int32_t write_pos; + int32_t read_pos; + int16_t is_full; + +} ISAR_CLDFB_RINGBUF, *ISAR_CLDFB_RINGBUF_HANDLE; +#endif + #endif /* ISAR_STAT_H */ diff --git a/lib_isar/lib_isar_pre_rend.c b/lib_isar/lib_isar_pre_rend.c index 2e6c70b47ec88ce9c6fb09794a448107edf20a66..7203c97b28688060ac96acccfe4b9673fee1142c 100644 --- a/lib_isar/lib_isar_pre_rend.c +++ b/lib_isar/lib_isar_pre_rend.c @@ -294,21 +294,26 @@ void ISAR_PRE_REND_GetMultiBinPoseData( *------------------------------------------------------------------------*/ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( - SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renerer handle */ - const IVAS_QUATERNION headPosition, /* i: head rotation QUATERNION */ - const int32_t SplitRendBitRate, /* i: Split renderer bitrate */ - ISAR_SPLIT_REND_CODEC splitCodec, /* i/o: Split renderer codec */ - const int16_t isar_frame_size_ms, /* i: ISAR framesize */ - int16_t codec_frame_size_ms, /* i/o: ISAR transport codec framesize */ - ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits struct handle */ + SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renerer handle */ + const IVAS_QUATERNION headPosition, /* i : head rotation QUATERNION */ + const int32_t SplitRendBitRate, /* i : Split renderer bitrate */ + ISAR_SPLIT_REND_CODEC splitCodec, /* i/o: Split renderer codec */ + const int16_t isar_frame_size_ms, /* i : ISAR framesize */ + int16_t codec_frame_size_ms, /* i/o: ISAR transport codec framesize */ + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits struct handle */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float *Cldfb_In_BinReal[][CLDFB_NO_COL_MAX], /* i/o: CLDFB real buffer */ + float *Cldfb_In_BinImag[][CLDFB_NO_COL_MAX], /* i/o: CLDFB imag buffer */ +#else float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB real buffer */ float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB imag buffer */ - const int16_t max_bands, /* i: CLDFB bands */ - float *output[], /* i/o: PCM in/out buffer */ - const int16_t low_res_pre_rend_rot, /* i: low time resolution pre-renderer flag */ - const int16_t cldfb_in_flag, /* i: Flag to indicate CLDFB or time doamin input */ - const int16_t pcm_out_flag, /* i: Flag to indicate PCM output */ - const int16_t ro_md_flag /* i: Flag to indicate real only metadata for yaw */ +#endif + const int16_t max_bands, /* i : CLDFB bands */ + float *output[], /* i/o: PCM in/out buffer */ + const int16_t low_res_pre_rend_rot, /* i : low time resolution pre-renderer flag */ + const int16_t cldfb_in_flag, /* i : Flag to indicate CLDFB or time domain input */ + const int16_t pcm_out_flag, /* i : Flag to indicate PCM output */ + const int16_t ro_md_flag /* i : Flag to indicate real only metadata for yaw */ ) { ivas_error error; @@ -406,20 +411,22 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( } else { - int16_t ch, slot_idx; + int16_t ch, slot_idx, num_slots; + num_slots = (int16_t) ( isar_frame_size_ms * 1000000 / CLDFB_SLOT_NS ); + /* 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]; - for ( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX; slot_idx++ ) + for ( slot_idx = 0; slot_idx < num_slots; slot_idx++ ) { Cldfb_In_BinReal_p[slot_idx] = Cldfb_In_BinReal[ch][slot_idx]; Cldfb_In_BinImag_p[slot_idx] = Cldfb_In_BinImag[ch][slot_idx]; } - 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] ); + cldfbSynthesis( Cldfb_In_BinReal_p, Cldfb_In_BinImag_p, output[ch], hSplitBin->hCldfbHandles->cldfbSyn[0]->no_channels * num_slots, hSplitBin->hCldfbHandles->cldfbSyn[ch] ); } pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode; diff --git a/lib_isar/lib_isar_pre_rend.h b/lib_isar/lib_isar_pre_rend.h index 201b46cd0ffc60607d29017f862a775342b32096..f11530e09668fdf8283435026408f0bdf110a792 100644 --- a/lib_isar/lib_isar_pre_rend.h +++ b/lib_isar/lib_isar_pre_rend.h @@ -59,21 +59,26 @@ void ISAR_PRE_REND_GetMultiBinPoseData( ); ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( - SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renerer handle */ - const IVAS_QUATERNION headPosition, /* i: head rotation QUATERNION */ - const int32_t SplitRendBitRate, /* i: Split renderer bitrate */ - ISAR_SPLIT_REND_CODEC splitCodec, /* i/o: Split renderer codec */ - const int16_t isar_frame_size_ms, /* i: ISAR framesize */ - int16_t codec_frame_size_ms, /* i/o: ISAR transport codec framesize */ - ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits struct handle */ + SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renerer handle */ + const IVAS_QUATERNION headPosition, /* i: head rotation QUATERNION */ + const int32_t SplitRendBitRate, /* i: Split renderer bitrate */ + ISAR_SPLIT_REND_CODEC splitCodec, /* i/o: Split renderer codec */ + const int16_t isar_frame_size_ms, /* i: ISAR framesize */ + int16_t codec_frame_size_ms, /* i/o: ISAR transport codec framesize */ + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits struct handle */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + float *Cldfb_In_BinReal[][CLDFB_NO_COL_MAX], /* i/o: CLDFB real buffer */ + float *Cldfb_In_BinImag[][CLDFB_NO_COL_MAX], /* i/o: CLDFB imag buffer */ +#else float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB real buffer */ float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB imag buffer */ - const int16_t max_bands, /* i: CLDFB bands */ - float *output[], /* i/o: PCM in/out buffer */ - const int16_t low_res_pre_rend_rot, /* i: low time resolution pre-renderer flag */ - const int16_t cldfb_in_flag, /* i: Flag to indicate CLDFB or time doamin input */ - const int16_t pcm_out_flag, /* i: Flag to indicate PCM output */ - const int16_t ro_md_flag /* i: Flag to indicate real only metadata for yaw */ +#endif + const int16_t max_bands, /* i: CLDFB bands */ + float *output[], /* i/o: PCM in/out buffer */ + const int16_t low_res_pre_rend_rot, /* i: low time resolution pre-renderer flag */ + const int16_t cldfb_in_flag, /* i: Flag to indicate CLDFB or time doamin input */ + const int16_t pcm_out_flag, /* i: Flag to indicate PCM output */ + const int16_t ro_md_flag /* i: Flag to indicate real only metadata for yaw */ ); #endif /* LIB_ISAR_PRE_REND_H */ diff --git a/lib_rend/ivas_cldfb_ring_buffer.c b/lib_rend/ivas_cldfb_ring_buffer.c new file mode 100644 index 0000000000000000000000000000000000000000..669227540e063f5d156efa86fd99ad5676c27867 --- /dev/null +++ b/lib_rend/ivas_cldfb_ring_buffer.c @@ -0,0 +1,298 @@ +/****************************************************************************************************** + + (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "ivas_prot.h" +#include +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +/*---------------------------------------------------------------------* + * CLDFB ring-buffer functions needed in split-rendering outputs + *---------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------* + * ivas_cldfb_ringbuf_IsEmpty() + * + * Returns 1 if the ring buffer is empty, or 0 otherwise. + *---------------------------------------------------------------------*/ + +static int16_t ivas_cldfb_ringbuf_IsEmpty( + ISAR_CLDFB_RINGBUF_HANDLE h ) +{ + return (int16_t) ( h->read_pos == h->write_pos && !h->is_full ); +} + + +/*---------------------------------------------------------------------* + * ivas_cldfb_ringbuf_IsFull() + * + * Returns 1 if the ring buffer is full, or 0 otherwise. + *---------------------------------------------------------------------*/ + +static int16_t ivas_cldfb_ringbuf_IsFull( + ISAR_CLDFB_RINGBUF_HANDLE h ) +{ + return h->is_full; +} + + +/*---------------------------------------------------------------------* + * ivas_CLDFB_RINGBUF_Open() + * + * Allocates a ring buffer for CLDFB data with the given capacity of CLDFB columns. + * Each column is expected to contain at most CLDFB_NO_CHANNELS_MAX frequency bands. + * + * May return IVAS_ERR_FAILED_ALLOC on failed allocation, or IVAS_ERR_OK otherwise. + *---------------------------------------------------------------------*/ + +ivas_error ivas_CLDFB_RINGBUF_Open( + ISAR_CLDFB_RINGBUF_HANDLE *ph, + const int16_t capacity_columns ) +{ + ISAR_CLDFB_RINGBUF_HANDLE h; + int32_t capacity; + + capacity = (int32_t) capacity_columns * CLDFB_NO_CHANNELS_MAX; + + if ( ( h = malloc( sizeof( ISAR_CLDFB_RINGBUF ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for CLDFB ring buffer\n" ); + } + h->real = NULL; + h->imag = NULL; + h->capacity = 0; + h->write_pos = 0; + h->read_pos = 0; + h->is_full = 0; + *ph = h; + + if ( ( h->real = malloc( capacity * sizeof( float ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for CLDFB ring buffer\n" ); + } + if ( ( h->imag = malloc( capacity * sizeof( float ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for CLDFB ring buffer\n" ); + } + h->capacity = capacity; + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * ivas_CLDFB_RINGBUF_Close() + * + * Dellocates CLDFB ring buffer. The given handle will be set to NULL. + *---------------------------------------------------------------------*/ + +void ivas_CLDFB_RINGBUF_Close( + ISAR_CLDFB_RINGBUF_HANDLE *ph ) +{ + ISAR_CLDFB_RINGBUF_HANDLE h; + + if ( ph == NULL ) + { + return; + } + h = *ph; + + if ( h == NULL ) + { + return; + } + + if ( h->real != NULL ) + { + free( h->real ); + } + if ( h->imag != NULL ) + { + free( h->imag ); + } + + free( h ); + *ph = NULL; + + return; +} + + +/*---------------------------------------------------------------------* + * ivas_CLDFB_RINGBUF_Push() + * + * Push a single column onto the back of the CLDFB ring buffer from real and imag arrays. + *---------------------------------------------------------------------*/ + +void ivas_CLDFB_RINGBUF_Push( + ISAR_CLDFB_RINGBUF_HANDLE h, + const float *real, + const float *imag, + const int16_t num_bands ) +{ + assert( num_bands <= CLDFB_NO_CHANNELS_MAX ); + assert( !ivas_cldfb_ringbuf_IsFull( h ) ); + + mvr2r( real, &h->real[h->write_pos], num_bands ); + mvr2r( imag, &h->imag[h->write_pos], num_bands ); + + h->write_pos += CLDFB_NO_CHANNELS_MAX; + if ( h->write_pos == h->capacity ) + { + h->write_pos = 0; + } + + if ( h->read_pos == h->write_pos ) + { + h->is_full = 1; + } + + return; +} + + +/*---------------------------------------------------------------------* + * ivas_CLDFB_RINGBUF_Pop() + * + * Pops a single column from the front of the CLDFB ring buffer into real and imag arrays. + *---------------------------------------------------------------------*/ + +void ivas_CLDFB_RINGBUF_Pop( + ISAR_CLDFB_RINGBUF_HANDLE h, + float *real, + float *imag, + const int16_t num_bands ) +{ + assert( num_bands <= CLDFB_NO_CHANNELS_MAX ); + assert( !ivas_cldfb_ringbuf_IsEmpty( h ) ); + + if ( real != NULL ) + { + mvr2r( &h->real[h->read_pos], real, num_bands ); + } + if ( imag != NULL ) + { + mvr2r( &h->imag[h->read_pos], imag, num_bands ); + } + + h->read_pos += CLDFB_NO_CHANNELS_MAX; + if ( h->read_pos == h->capacity ) + { + h->read_pos = 0; + } + + h->is_full = 0; + + return; +} + + +/*---------------------------------------------------------------------* + * ivas_cldfb_ringbuf_total_size() + * + * Returns total number of buffered samples (including number of channels) + *---------------------------------------------------------------------*/ + +static int32_t ivas_cldfb_ringbuf_total_size( + ISAR_CLDFB_RINGBUF_HANDLE h ) +{ + if ( ivas_cldfb_ringbuf_IsFull( h ) ) + { + return h->capacity; + } + + if ( h->read_pos <= h->write_pos ) + { + return h->write_pos - h->read_pos; + } + + /* else wrap around */ + return h->write_pos + h->capacity - h->read_pos; +} + + +/*---------------------------------------------------------------------* + * ivas_CLDFB_RINGBUF_GetByIdx() + * + * Get pointers into a specific column in the CLDFB ring buffer based on given index. + * Non-negative indices access from the front of the ring buffer, negative indexes access + * from the back, similar to Python arrays. For example: + * + * - index 0 accesses the front of the buffer, i.e. the oldest CLDFB column in the queue. + * - index -1 accesses the back of the buffer, i.e. the newest (last pushed) CLDFB column in the queue. + *---------------------------------------------------------------------*/ + +void ivas_CLDFB_RINGBUF_GetByIdx( + ISAR_CLDFB_RINGBUF_HANDLE h, + float **p_real, + float **p_imag, + const int16_t col_idx ) +{ + int32_t idx = col_idx * CLDFB_NO_CHANNELS_MAX; + int32_t num_floats = ivas_cldfb_ringbuf_total_size( h ); + int32_t offset; + + assert( -num_floats <= idx && idx <= num_floats ); + + if ( idx >= 0 ) + { + offset = h->read_pos + idx; + if ( h->capacity <= offset ) + { + offset -= h->capacity; + } + } + else + { + if ( -idx <= h->write_pos ) + { + offset = h->write_pos + idx; + } + else + { + offset = h->write_pos + h->capacity + idx; + } + } + + *p_real = &h->real[offset]; + *p_imag = &h->imag[offset]; + + return; +} +#endif diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index 11a3a16aae1a74300bbcd9126a9b3d761dc2df18..5571d91b50dea82b769287ae9a7e7b5db02cc1dd 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -822,8 +822,12 @@ static void ivas_dirac_dec_binaural_internal( { for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe]; i++ ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ivas_CLDFB_RINGBUF_Push( st_ivas->hSplitBinRend->hMultiBinCldfbData[ch], tmp_Cldfb_out_re[ch][i], tmp_Cldfb_out_im[ch][i], CLDFB_NO_CHANNELS_MAX ); +#else mvr2r( tmp_Cldfb_out_re[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX ); mvr2r( tmp_Cldfb_out_im[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX ); +#endif } } } @@ -873,14 +877,21 @@ static void ivas_dirac_dec_binaural_internal( mvr2r( st_ivas->hDiracDecBin[0]->ChCrossIm, hDiracDecBin->ChCrossIm, hSpatParamRendCom->num_freq_bands ); ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, +#else hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, +#endif subFrameTotalEne, IIReneLimiter, st_ivas->hMasaIsmData ); ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, +#else hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, +#endif nchanSeparateChannels, st_ivas->hMasaIsmData ); - /* re-use reverb and decorr from main direction for the sides */ ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, max_band_decorr, numInChannels, config_data.processReverb, subframe, tmp_Cldfb_out_re, tmp_Cldfb_out_im, @@ -891,8 +902,12 @@ static void ivas_dirac_dec_binaural_internal( { for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe]; i++ ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ivas_CLDFB_RINGBUF_Push( st_ivas->hSplitBinRend->hMultiBinCldfbData[pos_idx * BINAURAL_CHANNELS + ch], tmp_Cldfb_out_re[ch][i], tmp_Cldfb_out_im[ch][i], CLDFB_NO_CHANNELS_MAX ); +#else mvr2r( tmp_Cldfb_out_re[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[pos_idx * BINAURAL_CHANNELS + ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX ); mvr2r( tmp_Cldfb_out_im[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[pos_idx * BINAURAL_CHANNELS + ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX ); +#endif } } diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 1e9c4df5a06fa4c3572f7a4f228c74632999c196..d20958172afb319f75552cdad93bdc105fad93a4 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -1593,6 +1593,66 @@ void ivas_rend_closeCldfbRend( CLDFB_REND_WRAPPER *pCldfbRend ); +/*----------------------------------------------------------------------------------* + * Time domain ring buffer prototypes + *----------------------------------------------------------------------------------*/ + +ivas_error ivas_TD_RINGBUF_Open( + TD_RINGBUF_HANDLE *ph, /* i/o: Ring buffer handle */ + const int16_t capacity_per_channel, /* i : Number of samples stored per channel */ + const int16_t num_channels /* i : Number of channels */ +); + +void ivas_TD_RINGBUF_Close( + TD_RINGBUF_HANDLE *ph /* i/o: Ring buffer handle */ +); + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +void ivas_TD_RINGBUF_PushInterleaved( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + const float *data, /* i : Input audio in interleaved channels layout */ + const int16_t num_samples_per_channel /* i : Number of samples per channel to push */ +); + +void ivas_TD_RINGBUF_PushChannels( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + const float *p_channels[], /* i : Array of pointers to each input channel */ + const int16_t num_samples_per_channel /* i : Number of samples per channel to store */ +); + +void ivas_TD_RINGBUF_PushConstant( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + const float value, /* i : Value to push */ + const int16_t num_samples_per_channel /* i : Number of samples per channel to push */ +); + +void ivas_TD_RINGBUF_PopChannels( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + float *p_channels[], /* i : Array of pointers to each output channel */ + const int16_t num_samples_per_channel /* i : Number of samples per channel to pop */ +); +#else +void ivas_TD_RINGBUF_Push( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + const float *data, /* i : Input data */ + const uint16_t num_samples_per_channel /* i : Number of samples per channel to store */ +); + +void ivas_TD_RINGBUF_PushZeros( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + const uint16_t num_samples_per_channel /* i : Number of zeros per channel to store */ +); + +void ivas_TD_RINGBUF_Pop( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + float *data, /* i : Output data */ + const uint16_t num_samples_per_channel /* i : Number of samples per channel to retrieve*/ +); +#endif + +int16_t ivas_TD_RINGBUF_Size( + const TD_RINGBUF_HANDLE h /* i : Ring buffer handle */ +); /* clang-format on */ diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index bba88de8efe8f7b4c322391d13484180fb2b15fa..fe039cacb0dee30993cfc599a09795844e043711 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1375,6 +1375,22 @@ typedef struct } CLDFB_REND_WRAPPER; +/*----------------------------------------------------------------------------------* + * Time domain ring buffer structure + *----------------------------------------------------------------------------------*/ + +typedef struct +{ + float *data; /* samples in interleaved layout, e.g. for channels A, B, C, samples are stored: A1, B1, C1, A2, B2, C2, ... */ + int32_t capacity; /* max number of float values that can be stored */ + int16_t num_channels; + int32_t write_pos; + int32_t read_pos; + int16_t is_full; + +} TD_RINGBUF_DATA, *TD_RINGBUF_HANDLE; + + /*----------------------------------------------------------------------------------* * MASA external renderer structure *----------------------------------------------------------------------------------*/ diff --git a/lib_rend/ivas_td_ring_buffer.c b/lib_rend/ivas_td_ring_buffer.c new file mode 100644 index 0000000000000000000000000000000000000000..98b3e4d15b8de980fcf8fa1b3d289ed1147ea48a --- /dev/null +++ b/lib_rend/ivas_td_ring_buffer.c @@ -0,0 +1,425 @@ +/****************************************************************************************************** + + (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include +#include +#include "ivas_error_utils.h" +#include "ivas_prot_rend.h" +#include "options.h" +#include "wmc_auto.h" + + +/*-----------------------------------------------------------------------* + * Local function prototypes + *-----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------* + * ivas_td_ringbuf_total_size() + * + * Returns total number of buffered samples (including number of channels) + *---------------------------------------------------------------------*/ + +static int32_t ivas_td_ringbuf_total_size( + TD_RINGBUF_HANDLE h ) +{ + if ( h->is_full ) + { + return h->capacity; + } + + if ( h->read_pos <= h->write_pos ) + { + return h->write_pos - h->read_pos; + } + /* else wrap around */ + return h->write_pos + h->capacity - h->read_pos; +} + + +static int16_t ivas_td_ringbuf_has_space_for_num_samples( + TD_RINGBUF_HANDLE h, + const int32_t num_samples ) +{ + return (int16_t) ( ivas_td_ringbuf_total_size( h ) + num_samples <= h->capacity ); +} + + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +static void ivas_td_ringbuf_push_interleaved( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + const float *data, /* i : Input audio in interleaved channels layout */ + const int16_t num_samples_per_channel, /* i : Number of samples per channel to push */ + const int16_t read_stride /* i: : 1 for normal operation, 0 for reading from a single input value */ +) +{ + int32_t s, read_s; + + assert( h != NULL ); + assert( data != NULL ); + assert( read_stride == 0 || read_stride == 1 ); + assert( ivas_td_ringbuf_has_space_for_num_samples( h, (int32_t) num_samples_per_channel * h->num_channels ) ); + + for ( s = 0, read_s = 0; s < (int32_t) num_samples_per_channel * h->num_channels; ++s, read_s += read_stride ) + { + h->data[h->write_pos] = data[read_s]; + ++h->write_pos; + + if ( h->write_pos == h->capacity ) + { + h->write_pos = 0; + } + } + + if ( h->read_pos == h->write_pos ) + { + h->is_full = 1; + } + + return; +} +#endif + + +/*-----------------------------------------------------------------------* + * Global function definitions + *-----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_Open() + * + * Allocates a ring buffer for TD data with the given capacity of TD samples per channel. + * + * May return IVAS_ERR_FAILED_ALLOC on failed allocation, or IVAS_ERR_OK otherwise. + *---------------------------------------------------------------------*/ + +ivas_error ivas_TD_RINGBUF_Open( + TD_RINGBUF_HANDLE *ph, /* i/o: Ring buffer handle */ + const int16_t capacity_per_channel, /* i : Number of samples stored per channel */ + const int16_t num_channels /* i : Number of channels */ +) +{ + TD_RINGBUF_HANDLE h; + int32_t capacity; + + capacity = (int32_t) capacity_per_channel * num_channels; + + h = malloc( sizeof( TD_RINGBUF_DATA ) ); + if ( h == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for TD ring buffer\n" ); + } + h->data = NULL; + h->capacity = 0; + h->num_channels = num_channels; + h->write_pos = 0; + h->read_pos = 0; + h->is_full = 0; + *ph = h; + + h->data = malloc( capacity * sizeof( float ) ); + if ( h->data == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for TD ring buffer\n" ); + } + h->capacity = capacity; + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_Close() + * + * Dellocates TD ring buffer. The given handle will be set to NULL. + *---------------------------------------------------------------------*/ + +void ivas_TD_RINGBUF_Close( + TD_RINGBUF_HANDLE *ph /* i/o: Ring buffer handle */ +) +{ + TD_RINGBUF_HANDLE h; + + if ( ph == NULL ) + { + return; + } + h = *ph; + + if ( h == NULL ) + { + return; + } + + if ( h->data != NULL ) + { + free( h->data ); + } + + free( h ); + *ph = NULL; + + return; +} + + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_PushInterleaved() + * + * Pushes samples from a buffer with interleaved channel layout onto the back of the TD ring buffer. + *---------------------------------------------------------------------*/ + +void ivas_TD_RINGBUF_PushInterleaved( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + const float *data, /* i : Input audio in interleaved channels layout */ + const int16_t num_samples_per_channel /* i : Number of samples per channel to push */ +) +{ + ivas_td_ringbuf_push_interleaved( h, data, num_samples_per_channel, 1 ); + + return; +} + + +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_PushChannels() + * + * Pushes samples from channel pointers onto the back of the TD ring buffer. + *---------------------------------------------------------------------*/ + +void ivas_TD_RINGBUF_PushChannels( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + const float *p_channels[], /* i : Array of pointers to each input channel */ + const int16_t num_samples_per_channel /* i : Number of samples per channel to push */ +) +#else +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_Push() + * + * Push samples onto the back of the TD ring buffer. + * Returns total number of buffered samples (includes number of channels) + *---------------------------------------------------------------------*/ + +void ivas_TD_RINGBUF_Push( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + const float *data, /* i : Input data */ + const uint16_t num_samples_per_channel /* i : Number of samples per channel to store */ +) +#endif +{ + int32_t s; + int16_t c; + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + assert( h != NULL ); + assert( p_channels != NULL ); + for ( c = 0; c < h->num_channels; ++c ) + { + assert( p_channels[c] != NULL ); + } +#endif + assert( ivas_td_ringbuf_has_space_for_num_samples( h, (int32_t) num_samples_per_channel * h->num_channels ) ); + + for ( s = 0; s < num_samples_per_channel; ++s ) + { + for ( c = 0; c < h->num_channels; ++c ) + { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + h->data[h->write_pos] = p_channels[c][s]; +#else + h->data[h->write_pos] = *( data + c * num_samples_per_channel + s ); +#endif + ++h->write_pos; + + if ( h->write_pos == h->capacity ) + { + h->write_pos = 0; + } + } + } + + if ( h->read_pos == h->write_pos ) + { + h->is_full = 1; + } + + return; +} + + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_PushConstant() + * + * Pushes samples with a constant value onto the back of the TD ring buffer. + *---------------------------------------------------------------------*/ + +void ivas_TD_RINGBUF_PushConstant( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + const float value, /* i : Value to push */ + const int16_t num_samples_per_channel /* i : Number of samples per channel to push */ +) +{ + ivas_td_ringbuf_push_interleaved( h, &value, num_samples_per_channel, 0 ); + + return; +} +#else +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_PushZeros() + * + * Push zero samples onto the back of the TD ring buffer. + *---------------------------------------------------------------------*/ + +void ivas_TD_RINGBUF_PushZeros( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + const uint16_t num_samples_per_channel /* i : Number of zeros per channel to store */ +) +{ + uint16_t c, s; + + assert( ivas_td_ringbuf_has_space_for_num_samples( h, num_samples_per_channel * h->num_channels ) ); + if ( !num_samples_per_channel ) + { + return; + } + + for ( s = 0; s < num_samples_per_channel; ++s ) + { + for ( c = 0; c < h->num_channels; ++c ) + { + h->data[h->write_pos] = 0.f; + ++h->write_pos; + + if ( h->write_pos == h->capacity ) + { + h->write_pos = 0; + } + } + } + + if ( h->read_pos == h->write_pos ) + { + h->is_full = 1; + } + + return; +} +#endif + + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_PopChannels() + * + * Pops samples from the front of the TD ring buffer to an array of channel pointers. + *---------------------------------------------------------------------*/ + +void ivas_TD_RINGBUF_PopChannels( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + float *p_channels[], /* i : Array of pointers to each output channel */ + const int16_t num_samples_per_channel /* i : Number of samples per channel to pop */ +) +#else +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_Pop() + * + * Pop samples from the front of the TD ring buffer. + *---------------------------------------------------------------------*/ + +void ivas_TD_RINGBUF_Pop( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + float *data, /* i : Output data */ + const uint16_t num_samples_per_channel /* i : Number of samples per channel to retrieve */ +) +#endif +{ + int32_t s; + int16_t c; + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + assert( h != NULL ); + assert( p_channels != NULL ); + for ( c = 0; c < h->num_channels; ++c ) + { + assert( p_channels[c] != NULL ); + } +#endif + assert( ivas_td_ringbuf_total_size( h ) >= (int32_t) num_samples_per_channel * h->num_channels ); + + for ( s = 0; s < num_samples_per_channel; ++s ) + { + for ( c = 0; c < h->num_channels; ++c ) + { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + p_channels[c][s] = h->data[h->read_pos]; +#else + *( data + c * num_samples_per_channel + s ) = h->data[h->read_pos]; +#endif + ++h->read_pos; + + if ( h->read_pos == h->capacity ) + { + h->read_pos = 0; + } + } + } + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( num_samples_per_channel != 0 ) + { + h->is_full = 0; + } +#else + if ( h->is_full ) + { + h->is_full = 0; + } +#endif + + return; +} + + +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_Size() + * + * Returns number of buffered samples per channel. + *---------------------------------------------------------------------*/ + +int16_t ivas_TD_RINGBUF_Size( + const TD_RINGBUF_HANDLE h /* i : Ring buffer handle */ +) +{ + return (int16_t) ( ivas_td_ringbuf_total_size( h ) / h->num_channels ); +} diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index e7e7003b0f116b5743514b73b4cd1e45cf40d176..e1dd767ad9271315968baed4cb71cced718038f0 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -7597,6 +7597,19 @@ static ivas_error getSamplesInternal( int16_t ch; int16_t i, ro_md_flag; float *tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS], tmpBinaural_buff[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP /* Temporary fix. Proper implementation of port 391 can only be added once port 369 is complete. */ + float *p_Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX]; + float *p_Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX]; + + for ( ch = 0; ch < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; ++ch ) + { + for ( i = 0; i < CLDFB_NO_COL_MAX; ++i ) + { + p_Cldfb_RealBuffer_Binaural[ch][i] = Cldfb_RealBuffer_Binaural[ch][i]; + p_Cldfb_ImagBuffer_Binaural[ch][i] = Cldfb_ImagBuffer_Binaural[ch][i]; + } + } +#endif for ( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ ) { @@ -7634,8 +7647,13 @@ static ivas_error getSamplesInternal( hIvasRend->hRendererConfig->split_rend_config.isar_frame_size_ms, hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms, &bits, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + p_Cldfb_RealBuffer_Binaural, + p_Cldfb_ImagBuffer_Binaural, +#else Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, +#endif ( const int16_t )( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ), tmpBinaural, 1,