diff --git a/Workspace_msvc/lib_rend.vcxproj b/Workspace_msvc/lib_rend.vcxproj index c39806d47edcb1f3165b7ddbdcd9643b9e71c6ec..b76f3211cbbeb550c4df1977e072f6db0734bc9a 100644 --- a/Workspace_msvc/lib_rend.vcxproj +++ b/Workspace_msvc/lib_rend.vcxproj @@ -138,6 +138,7 @@ + @@ -175,6 +176,7 @@ + @@ -209,4 +211,4 @@ - \ No newline at end of file + diff --git a/Workspace_msvc/lib_rend.vcxproj.filters b/Workspace_msvc/lib_rend.vcxproj.filters index 2494e2ee2e8a44233535a78999c15448adf0ce04..0892a4dcb09d82b426c470d29851041668907dde 100644 --- a/Workspace_msvc/lib_rend.vcxproj.filters +++ b/Workspace_msvc/lib_rend.vcxproj.filters @@ -109,6 +109,9 @@ rend_c + + rend_c + rend_c diff --git a/apps/decoder.c b/apps/decoder.c index 5221ec6281b31839bdffbab23f4de4387487157c..03f09be6dd6f159e93b4d13feba27845f5961113 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -158,7 +158,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 ); static void do_object_editing_fx( IVAS_EDITABLE_PARAMETERS *editableParameters, ObjectEditFileReader *objectEditFileReader ); @@ -632,7 +636,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 { @@ -1701,7 +1709,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; @@ -1719,7 +1731,12 @@ static ivas_error initOnFirstGoodFrame( return error; } } + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( !isSplitCoded ) +#else else +#endif { if ( *pRemainingDelayNumSamples < *numOutSamples ) { @@ -1919,6 +1936,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 ); @@ -2180,7 +2205,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; } @@ -2622,6 +2651,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 ) { @@ -2671,6 +2703,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 ) { @@ -2962,15 +3017,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, (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, (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, (void *) pcmBuf, writeJbmTraceFileFrameWrapper, jbmTraceWriter, &bitstreamReadDone, &nSamplesRendered, ¶metersAvailableForEditing, systemTime_ms ) ) != IVAS_ERR_OK ) +#else + if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, (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 ) { @@ -3050,9 +3124,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 ) { goto cleanup; @@ -3067,19 +3147,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 ) @@ -3167,7 +3263,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 ) @@ -3238,11 +3338,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 @@ -3287,6 +3395,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 aa799c3f24d6cf55080f09bbefdeec1d2598b2d6..272d2b9c42d89391cb69372d589e491842cddfce 100644 --- a/apps/isar_post_rend.c +++ b/apps/isar_post_rend.c @@ -1109,6 +1109,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_fx.h b/lib_com/ivas_prot_fx.h index 88de3e85c438db83f10b04f1bd79e8845b97d3f5..a01dedfbab4b4c97d98a09940b9fbb47eec1291f 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -6733,6 +6733,44 @@ void ivas_binaural_hrtf_close_fx( HRTFS_FASTCONV_HANDLE *hHrtfFastConv /* i/o: decoder binaural hrtf handle */ ); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + +/*---------------------------------------------------------------------------------* + * Multi-pose ring buffer Prototypes +*-----------------------------------------------------------------------------------*/ + +ivas_error ivas_CLDFB_RINGBUF_Open( + ISAR_CLDFB_RINGBUF_HANDLE *ph, + const Word16 capacity_columns +); + +void ivas_CLDFB_RINGBUF_Close( + ISAR_CLDFB_RINGBUF_HANDLE *ph +); + +void ivas_CLDFB_RINGBUF_Push( + ISAR_CLDFB_RINGBUF_HANDLE h, + const Word32 *real, + const Word32 *imag, + const Word16 num_bands +); + +void ivas_CLDFB_RINGBUF_Pop( + ISAR_CLDFB_RINGBUF_HANDLE h, + Word32 *real, + Word32 *imag, + const Word16 num_bands +); + +void ivas_CLDFB_RINGBUF_GetByIdx( + ISAR_CLDFB_RINGBUF_HANDLE h, + Word32 **p_real, + Word32 **p_imag, + const Word16 idx +); + +#endif + /*----------------------------------------------------------------------------------* * renderer prototypes *----------------------------------------------------------------------------------*/ diff --git a/lib_com/options.h b/lib_com/options.h index c967fd23313cf405c84fc2afebf1c25e4cc66026..a3a96d070928df75b0c35b6ae02b285f9cad51d2 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -103,7 +103,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_fx.c b/lib_dec/ivas_dirac_dec_fx.c index 6e30bc084031b0268c4a1865f7db633dc795938a..c9d9b2c384f8caa3808c5f58f4e2618817e58440 100644 --- a/lib_dec/ivas_dirac_dec_fx.c +++ b/lib_dec/ivas_dirac_dec_fx.c @@ -2189,7 +2189,9 @@ static void binRenderer_split_fx( Word32 Cldfb_ImagBuffer_Binaural_fx[][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Rotated Binaural signals */ Word32 RealBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ Word32 ImagBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ +#ifndef FIX_1119_SPLIT_RENDERING_VOIP const Word16 slot_idx_start, +#endif const Word16 num_freq_bands, const Word16 nchan_out ) { @@ -2222,8 +2224,16 @@ static void binRenderer_split_fx( { 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 Copy32( Cldfb_RealBuffer_Binaural_loc[pos_idx][ch][slot_idx], hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_idx_start + slot_idx], num_freq_bands ); Copy32( Cldfb_ImagBuffer_Binaural_loc[pos_idx][ch][slot_idx], hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_idx_start + slot_idx], num_freq_bands ); +#endif } } } @@ -3867,7 +3877,11 @@ void ivas_dirac_dec_render_sf_fx( } binRenderer_split_fx( st_ivas->hBinRenderer, st_ivas->hSplitBinRend, st_ivas->hCombinedOrientationData, hSpatParamRendCom->subframe_nbslots[subframe_idx], - Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, Cldfb_RealBuffer_fx, Cldfb_ImagBuffer_fx, slot_idx_start, hSpatParamRendCom->num_freq_bands, st_ivas->hDecoderConfig->nchan_out ); + Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, Cldfb_RealBuffer_fx, Cldfb_ImagBuffer_fx, +#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_fx.c b/lib_dec/ivas_init_dec_fx.c index fc3dbd85cb89cf33fe53c7732c5e74acc450302b..dff92f4e4b92fbaa66580d5f1a546857e70a8303 100644 --- a/lib_dec/ivas_init_dec_fx.c +++ b/lib_dec/ivas_init_dec_fx.c @@ -1476,6 +1476,11 @@ ivas_error ivas_init_decoder_front( } } +#ifdef TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR + st_ivas->flushing = 0; + move16(); +#endif + return error; } diff --git a/lib_dec/ivas_jbm_dec_fx.c b/lib_dec/ivas_jbm_dec_fx.c index eb287aefaa5ede330ba3e551b620983eb411e952..57101b4de1136f27631f598ab9ae3833cd8d2081 100644 --- a/lib_dec/ivas_jbm_dec_fx.c +++ b/lib_dec/ivas_jbm_dec_fx.c @@ -2478,13 +2478,46 @@ ivas_error ivas_jbm_dec_render_fx( IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + const Word32 *p_output_fx_const[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; + + nchan_out_syn_output = i_mult( BINAURAL_CHANNELS, st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ); + + /* Save TD signals for pose correction if they are to be used. + * + * NOTE: Here BASOP differs from the float version. In float, we push samples to TD ring buffer in lib_dec.c function isar_render_poses. */ + IF( st_ivas->hSplitBinRend->hMultiBinTdData != NULL ) + { + FOR( i = 0; i < nchan_out_syn_output; i++ ) + { + p_output_fx_const[i] = p_output_fx[i]; + } + ivas_TD_RINGBUF_PushChannels( st_ivas->hSplitBinRend->hMultiBinTdData, p_output_fx_const, *nSamplesRendered ); + } + +#ifdef TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR + if ( st_ivas->flushing ) + { + nchan_out_syn_output = BINAURAL_CHANNELS; + move16(); + } +#endif +#else FOR( i = 0; i < st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses * BINAURAL_CHANNELS; i++ ) { Copy32( p_output_fx[i], st_ivas->hSplitBinRend->hMultiBinCldfbData->output_fx[i], *nSamplesRendered ); } +#endif } - nchan_out_syn_output = nchan_out; - move16(); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ELSE + { +#endif + nchan_out_syn_output = nchan_out; + move16(); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + } +#endif IF( is_split_rendering_enabled( st_ivas->hDecoderConfig, st_ivas->hRenderConfig ) == 0 ) { diff --git a/lib_dec/ivas_mc_param_dec_fx.c b/lib_dec/ivas_mc_param_dec_fx.c index 1aa07241eb15cdd0aacefe6fb4c87fa539d9b79f..619d1e3f8c6db25396df32809790b736cc4e3602 100644 --- a/lib_dec/ivas_mc_param_dec_fx.c +++ b/lib_dec/ivas_mc_param_dec_fx.c @@ -2203,8 +2203,16 @@ void ivas_param_mc_dec_render_fx( { 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_fx[pos_idx][ch][slot_idx], + Cldfb_ImagBuffer_Binaural_fx[pos_idx][ch][slot_idx], + hParamMC->num_freq_bands ); +#else Copy32( Cldfb_RealBuffer_Binaural_fx[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[add( i_mult( pos_idx, BINAURAL_CHANNELS ), ch )][add( slot_idx_start, slot_idx )], hParamMC->num_freq_bands ); Copy32( Cldfb_ImagBuffer_Binaural_fx[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[add( i_mult( pos_idx, BINAURAL_CHANNELS ), ch )][add( slot_idx_start, slot_idx )], hParamMC->num_freq_bands ); +#endif } } } diff --git a/lib_dec/ivas_mc_paramupmix_dec_fx.c b/lib_dec/ivas_mc_paramupmix_dec_fx.c index 75b9de19e69ae72d14bd5aafbb8813bd54de3f19..fd0bb54ccf39fe069de97dd955abdd04af703f69 100644 --- a/lib_dec/ivas_mc_paramupmix_dec_fx.c +++ b/lib_dec/ivas_mc_paramupmix_dec_fx.c @@ -901,8 +901,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_fx[pos_idx][ch][slot_idx], + Cldfb_ImagBuffer_Binaural_fx[pos_idx][ch][slot_idx], + maxBand ); +#else Copy32( Cldfb_RealBuffer_Binaural_fx[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[add( i_mult( pos_idx, BINAURAL_CHANNELS ), ch )][add( slot_index_start, slot_idx )], maxBand ); Copy32( Cldfb_ImagBuffer_Binaural_fx[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[add( i_mult( pos_idx, BINAURAL_CHANNELS ), ch )][add( slot_index_start, slot_idx )], maxBand ); +#endif } } } diff --git a/lib_dec/ivas_omasa_dec_fx.c b/lib_dec/ivas_omasa_dec_fx.c index 7fdbe3c884e107fea06abb9a5638322d9e144f3e..c8da321a9131e66a73c0158f77c9a07a50a0c510 100644 --- a/lib_dec/ivas_omasa_dec_fx.c +++ b/lib_dec/ivas_omasa_dec_fx.c @@ -1222,10 +1222,14 @@ ivas_error ivas_omasa_dirac_td_binaural_jbm_fx( ivas_error error; Word32 *p_sepobj_fx[BINAURAL_CHANNELS]; // Q11 Word32 data_separated_objects_fx[BINAURAL_CHANNELS][L_FRAME48k]; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Word32 *re, *im; +#else Word16 slot_idx_start; slot_idx_start = st_ivas->hSpatParamRendCom->slots_rendered; move16(); +#endif FOR( n = 0; n < BINAURAL_CHANNELS; n++ ) { @@ -1284,9 +1288,16 @@ ivas_error ivas_omasa_dirac_td_binaural_jbm_fx( Scale_sig32( Cldfb_RealBuffer, num_cldfb_bands, sub( Q6, q_cldfb ) ); Scale_sig32( Cldfb_ImagBuffer, num_cldfb_bands, sub( Q6, q_cldfb ) ); + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ivas_CLDFB_RINGBUF_GetByIdx( st_ivas->hSplitBinRend->hMultiBinCldfbData[n], &re, &im, sub( slot_idx, cldfb_slots ) ); + v_add_fx( re, Cldfb_RealBuffer, re, num_cldfb_bands ); + v_add_fx( im, Cldfb_ImagBuffer, im, num_cldfb_bands ); +#else /* note: this intentionally differs from OSBA by: no scaling by 0.5 */ v_add_fx( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[n][slot_idx_start + slot_idx], Cldfb_RealBuffer, st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[n][slot_idx_start + slot_idx], num_cldfb_bands ); v_add_fx( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[n][slot_idx_start + slot_idx], Cldfb_ImagBuffer, st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[n][slot_idx_start + slot_idx], num_cldfb_bands ); +#endif } } } diff --git a/lib_dec/ivas_osba_dec_fx.c b/lib_dec/ivas_osba_dec_fx.c index 52bc8da86cda3bc065a296006a027c45c5dcac2e..f81a8e8a2303743eb55adb8edf1effccfbb527fb 100644 --- a/lib_dec/ivas_osba_dec_fx.c +++ b/lib_dec/ivas_osba_dec_fx.c @@ -137,10 +137,14 @@ ivas_error ivas_osba_dirac_td_binaural_jbm_fx( Word32 output_separated_objects_fx[BINAURAL_CHANNELS][L_FRAME48k]; Word32 *p_sepobj_fx[BINAURAL_CHANNELS]; Word16 channel_offset; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Word32 *re, *im; +#else Word16 slot_idx_start; slot_idx_start = st_ivas->hSpatParamRendCom->slots_rendered; move16(); +#endif FOR( Word16 i = 0; i < BINAURAL_CHANNELS; i++ ) { @@ -163,7 +167,10 @@ ivas_error ivas_osba_dirac_td_binaural_jbm_fx( ivas_combined_orientation_set_to_start_index( st_ivas->hCombinedOrientationData ); IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { - Word16 slot_idx, num_cldfb_bands, b, nchan_transport_orig; + Word16 slot_idx, num_cldfb_bands, nchan_transport_orig; +#ifndef FIX_1119_SPLIT_RENDERING_VOIP + Word16 b; +#endif Word16 cldfb_slots; Word32 Cldfb_RealBuffer[CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer[CLDFB_NO_CHANNELS_MAX]; @@ -198,6 +205,12 @@ ivas_error ivas_osba_dirac_td_binaural_jbm_fx( Scale_sig32( Cldfb_RealBuffer, num_cldfb_bands, sub( Q6, q_cldfb ) ); Scale_sig32( Cldfb_ImagBuffer, num_cldfb_bands, sub( Q6, q_cldfb ) ); + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ivas_CLDFB_RINGBUF_GetByIdx( st_ivas->hSplitBinRend->hMultiBinCldfbData[n], &re, &im, sub( slot_idx, cldfb_slots ) ); + v_add_fx( re, Cldfb_RealBuffer, re, num_cldfb_bands ); + v_add_fx( im, Cldfb_ImagBuffer, im, num_cldfb_bands ); +#else FOR( b = 0; b < num_cldfb_bands; b++ ) { st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[n][slot_idx_start + slot_idx][b] = @@ -208,6 +221,7 @@ ivas_error ivas_osba_dirac_td_binaural_jbm_fx( L_add( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[n][add( slot_idx_start, slot_idx )][b], Cldfb_ImagBuffer[b] ); move32(); } +#endif } } } diff --git a/lib_dec/ivas_output_config_fx.c b/lib_dec/ivas_output_config_fx.c index 284bd08599ad2602396237350570c549f14f2ed8..1958cea41b4de72853657e0f826a601d5e96ed33 100644 --- a/lib_dec/ivas_output_config_fx.c +++ b/lib_dec/ivas_output_config_fx.c @@ -626,12 +626,28 @@ RENDERER_TYPE ivas_renderer_secondary_select_fx( test(); test(); + test(); + test(); + test(); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + test(); + test(); + test(); + test(); + IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && + ( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) ) +#else IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) ) +#endif { renderer_type = RENDERER_BINAURAL_OBJECTS_TD; move32(); } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ELSE IF( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) && ( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) ) +#else ELSE IF( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) && ( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) ) +#endif { renderer_type = RENDERER_BINAURAL_OBJECTS_TD; move32(); diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index e02105fd8cb37463c0b362d26a4c6d7e51df75f8..4a464705d34a23d136a8b5b5c7573e95112b349a 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -870,6 +870,7 @@ typedef struct renderer_struct * IVAS decoder specific ISAR wrapper structures *----------------------------------------------------------------------------------*/ +#ifndef FIX_1119_SPLIT_RENDERING_VOIP typedef struct { Word32 Cldfb_RealBuffer_Binaural_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; @@ -878,18 +879,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 + Word32 Cldfb_RealBuffer_fx[MAX_OUTPUT_CHANNELS][2 * CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; /* Double space to account for TSM */ + Word32 Cldfb_ImagBuffer_fx[MAX_OUTPUT_CHANNELS][2 * CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; +#else Word32 Cldfb_RealBuffer_fx[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_fx[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 { +#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*/ - ISAR_SPLIT_REND_BITS_HANDLE hSplitRendBits; /*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*/ Word16 numTdSamplesPerChannelCached; @@ -1012,7 +1024,7 @@ typedef struct decoder_tc_buffer_structure #ifdef JBM_MEMORY_OPT Word32 *tc_fx[MAX_INTERN_CHANNELS]; /* pointers into the buffer to the beginning of each tc */ #else - Word32 *tc_fx[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; /* pointers into the buffer to the beginning of each tc Q11 for ivas */ + Word32 *tc_fx[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; /* pointers into the buffer to the beginning of each tc Q11 for ivas */ #endif Word16 no_channels; /*Stores no of channels in tc_fx with values*/ Word16 q_tc_fx; @@ -1200,6 +1212,10 @@ typedef struct Decoder_Struct Word16 ism_extmeta_active; /* Extended metadata active in decoder */ Word16 ism_extmeta_cnt; /* Change frame counter for extended metadata */ +#ifdef TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR + Word16 flushing; +#endif + } Decoder_Struct; /* clang-format on */ diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index cf23f0e646fb04cd20ecbf673675f28e1ea1bb67..e911a5fca55eddc30366d708ed6168467813b2ee 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -150,7 +150,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 Word16 isSplitRend, /* i : split rendering enabled flag */ +#endif ISAR_SPLIT_REND_BITS_DATA *splitRendBits /* o : output split rendering bits */ ); @@ -305,6 +307,24 @@ ivas_error IVAS_DEC_VoIP_GetSamples( const UWord32 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 */ + Word16 *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 */ + UWord16 *nSamplesRendered, /* o : number of samples rendered */ + bool *parametersAvailableForEditing, /* o : indicates whether objects editing is available */ + const UWord32 systemTimestamp_ms /* i : current system timestamp */ +); +#endif + ivas_error IVAS_DEC_Flush( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ const Word16 nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ diff --git a/lib_dec/lib_dec_fx.c b/lib_dec/lib_dec_fx.c index 73c8c9a405216f37d00e984a3a3189e341b5fa88..7d3ee4ffd60a96f22d16cb19eb72b70bedd4f7de 100644 --- a/lib_dec/lib_dec_fx.c +++ b/lib_dec/lib_dec_fx.c @@ -116,9 +116,17 @@ static void store_JbmData( IVAS_DEC_VOIP *hVoIP, JB4_DATAUNIT_HANDLE dataUnit, c static ivas_error evs_dec_main_fx( Decoder_Struct *st_ivas ); static ivas_error input_format_API_to_internal( IVAS_DEC_INPUT_FORMAT input_format, Word16 *bitstream_format_internal, Word16 *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, UWord8 *nTransportChannels, ISAR_SPLIT_REND_BITS_DATA *splitRendBits ); +#else static ivas_error ivas_dec_setup_all( IVAS_DEC_HANDLE hIvasDec, UWord8 *nTransportChannels, const Word16 isSplitRend, ISAR_SPLIT_REND_BITS_DATA *splitRendBits ); +#endif static ivas_error apa_setup( IVAS_DEC_HANDLE hIvasDec, const bool isInitialized_voip, const UWord16 nTransportChannels ); static Word16 get_render_frame_size_ms( IVAS_RENDER_FRAMESIZE render_framesize ); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +static Word16 get_render_frame_size_samples( const DECODER_CONFIG_HANDLE hDecoderConfig ); +static Word16 ivas_dec_split_rend_cldfb_in( const RENDERER_TYPE renderer_type ); +#endif static void update_voip_rendered20ms( IVAS_DEC_HANDLE hIvasDec, const Word16 nSamplesRendered ); static ivas_error isar_set_split_rend_setup( ISAR_DEC_SPLIT_REND_WRAPPER *hSplitBinRend, const ISAR_SPLIT_REND_CONFIG_DATA *hSplitBinConfig, const COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, ISAR_SPLIT_REND_BITS_DATA *splitRendBits ); static ivas_error ivas_dec_reconfig_split_rend( Decoder_Struct *st_ivas ); @@ -761,6 +769,40 @@ ivas_error IVAS_DEC_GetRenderFramesize( } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +/*---------------------------------------------------------------------* + * get_render_frame_size_samples( ) + * + * + *---------------------------------------------------------------------*/ + +static Word16 get_render_frame_size_samples( + const DECODER_CONFIG_HANDLE hDecoderConfig /* i : configuration structure */ +) +{ + Word16 tmp; + tmp = (Word16) Mpy_32_16_1( hDecoderConfig->output_Fs, INV_FR_P_S_MX_PRM_SPL_SBFR_Q15 ); + + IF( EQ_16( hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_5MS ) ) + { + /* correct value already in tmp */ + } + ELSE IF( EQ_16( hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_10MS ) ) + { + tmp = shl( tmp, 1 ); + } + ELSE IF( EQ_16( hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_20MS ) ) + { + tmp = shl( tmp, 2 ); + } + ELSE + { + tmp = 0; + } + return tmp; +} +#endif + /*---------------------------------------------------------------------* * IVAS_DEC_GetGetRenderFramesizeSamples( ) * @@ -772,7 +814,9 @@ ivas_error IVAS_DEC_GetRenderFramesizeSamples( Word16 *render_framesize /* o : render framesize in samples Q0 */ ) { +#ifndef FIX_1119_SPLIT_RENDERING_VOIP Word16 tmp; +#endif test(); test(); @@ -781,6 +825,9 @@ 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 tmp = (Word16) Mpy_32_16_1( hIvasDec->st_ivas->hDecoderConfig->output_Fs, INV_FR_P_S_MX_PRM_SPL_SBFR_Q15 ); IF( EQ_16( hIvasDec->st_ivas->hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_5MS ) ) @@ -799,6 +846,7 @@ ivas_error IVAS_DEC_GetRenderFramesizeSamples( { *render_framesize = 0; } +#endif move16(); return IVAS_ERR_OK; @@ -1118,6 +1166,281 @@ ivas_error IVAS_DEC_FeedFrame_Serial( return IVAS_ERR_OK; } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +/*---------------------------------------------------------------------* + * isar_get_frame_size( ) + * + * + *---------------------------------------------------------------------*/ + +static Word16 isar_get_frame_size( + Decoder_Struct *st_ivas /* i : IVAS decoder handle */ +) +{ + Word32 output_Fs; + Word16 nSamplesPerChannel; + + output_Fs = st_ivas->hDecoderConfig->output_Fs; + + test(); + test(); + IF( NE_32( st_ivas->hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_20MS ) && + ( EQ_32( st_ivas->hRenderConfig->split_rend_config.poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) || + EQ_32( st_ivas->hRenderConfig->split_rend_config.dof, 0 ) ) ) + { + nSamplesPerChannel = extract_l( ar_div( output_Fs, FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ); + nSamplesPerChannel = imult1616( nSamplesPerChannel, st_ivas->hDecoderConfig->render_framesize ); + } + ELSE + { + nSamplesPerChannel = extract_l( ar_div( 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 Word16 nSamplesAsked, /* i : number of samples wanted by the caller */ + Word16 *nOutSamples, /* o : number of samples per channel written to output buffer */ + bool *needNewFrame /* o : indication that the decoder needs a new frame */ +) +{ +#ifndef FIX_1119_SPLIT_RENDERING_VOIP + // Note for reviewers: Code in this function was moved and adapted from IVAS_DEC_GetSplitBinauralBitstream, + // see #else branch of FIX_1119_SPLIT_RENDERING_VOIP there for reference +#endif + Word16 pcmBuf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES * L_FRAME48k]; + Decoder_Struct *st_ivas; + ivas_error error; + Word16 numPoses; + + test(); + IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + *needNewFrame = false; + move16(); + + st_ivas = hIvasDec->st_ivas; + + numPoses = st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses; + move16(); + + /* init flush buffer for rate switch if not already initizalized */ + IF( hIvasDec->flushbuffer == NULL ) + { + /* hIvasDec->flushbuffer = (void *) malloc( sizeof( Word16 ) * numPoses * BINAURAL_CHANNELS * hIvasDec->nSamplesFrame / IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ); */ + /* set16_fx( (Word16 *) hIvasDec->flushbuffer, 0, numPoses * BINAURAL_CHANNELS * hIvasDec->nSamplesFrame / IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ); */ + Word16 num_samples_flushbuffer; + num_samples_flushbuffer = mult0( mult0( numPoses, BINAURAL_CHANNELS ), shl( div_l( hIvasDec->nSamplesFrame, IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ), 1 ) ); + hIvasDec->flushbuffer = (void *) malloc( L_mult0( sizeof( Word16 ), num_samples_flushbuffer ) ); + set16_fx( (Word16 *) hIvasDec->flushbuffer, 0, num_samples_flushbuffer ); + } + + /* render */ + IF( NE_32( ( error = IVAS_DEC_GetSamplesRenderer( hIvasDec, nSamplesAsked, pcmBuf, nOutSamples, needNewFrame ) ), IVAS_ERR_OK ) ) + { + return error; + } + + IF( !hIvasDec->hasBeenFedFirstGoodFrame ) + { + return IVAS_ERR_OK; + } + + /* NOTE: Here BASOP differs from the float version. In float, we push samples to TD ring buffer here. In BASOP, TD signals are only available in 16 bit here. + * To save TD signals in 32-bit precision, samples are pushed via ivas_TD_RINGBUF_PushChannels in ivas_jbm_dec_render_fx within IVAS_DEC_GetSamplesRenderer. */ + + return error; +} + + +/*---------------------------------------------------------------------* + * isar_generate_metadata_and_bitstream( ) + * + * + *---------------------------------------------------------------------*/ + +static ivas_error isar_generate_metadata_and_bitstream( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + Word32 **p_head_pose_buf, /* i/o: PCM buffer with head-pose data */ + Word16 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 */ + Word16 Q_out[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS] /* o : Q-format of each channel of p_head_pose_buf */ +) +{ +#ifndef FIX_1119_SPLIT_RENDERING_VOIP + // Note for reviewers: Code in this function was moved and adapted from IVAS_DEC_GetSplitBinauralBitstream, + // see #else branch of FIX_1119_SPLIT_RENDERING_VOIP there for reference +#endif + ivas_error error; + ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE hSplitBinRend; + Word16 max_band; + Word16 pcm_out_flag; + Word16 cldfb_in_flag; + Word16 ro_md_flag; + IVAS_QUATERNION Quaternion; + Word16 i, j, num_poses, num_cldfb_slots, n_samples_in_cldfb_slot; + Word32 *p_Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX]; + Word32 *p_Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX]; + + hSplitBinRend = st_ivas->hSplitBinRend; + + max_band = extract_l( ar_div( imult3216( st_ivas->hDecoderConfig->output_Fs, BINAURAL_MAXBANDS ), 48000 ) ); + move16(); + cldfb_in_flag = ivas_dec_split_rend_cldfb_in( st_ivas->renderer_type ); + move16(); + pcm_out_flag = 0; + move16(); + if ( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + pcm_out_flag = 1; + move16(); + } + + n_samples_in_cldfb_slot = NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); + assert( nSamples % n_samples_in_cldfb_slot == 0 ); + num_cldfb_slots = int_div_s_x( nSamples, n_samples_in_cldfb_slot ); + + num_poses = hSplitBinRend->splitrend.multiBinPoseData.num_poses; + move16(); + + IF( cldfb_in_flag ) + { + FOR( i = 0; i < imult1616( 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; + move16(); + } + ELSE + { + ro_md_flag = 0; + move16(); + } + + IF( st_ivas->hHeadTrackData != NULL ) + { + Quaternion = st_ivas->hHeadTrackData->Quaternions[0]; + /* Copy of a struct: 4x Word32 and 1x Word32 */ + move32(); + move32(); + move32(); + move32(); + move16(); + } + ELSE + { + Quaternion.w_fx = -12582912; + move32(); + Quaternion.x_fx = 0; + move32(); + Quaternion.y_fx = 0; + move32(); + Quaternion.z_fx = 0; + move32(); + } + Word16 q1 = 31, q2 = 31, Q_buff; + move32(); + move32(); + Q_out[0] = 31; + move32(); + + IF( EQ_16( cldfb_in_flag, 1 ) ) + { + FOR( i = 0; i < i_mult( BINAURAL_CHANNELS, num_poses ); i++ ) + { + FOR( j = 0; j < num_cldfb_slots; j++ ) + { + q1 = s_min( q1, L_norm_arr( p_Cldfb_RealBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX ) ); + q2 = s_min( q2, L_norm_arr( p_Cldfb_ImagBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX ) ); + } + } + Q_buff = s_min( q1, q2 ); + FOR( i = 0; i < i_mult( BINAURAL_CHANNELS, num_poses ); i++ ) + { + FOR( j = 0; j < num_cldfb_slots; j++ ) + { + scale_sig32( p_Cldfb_RealBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX, Q_buff ); + scale_sig32( p_Cldfb_ImagBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX, Q_buff ); + } + } + Q_buff = add( Q_buff, Q6 ); + } + ELSE + { + /*TD input*/ + /*if CLDFB handles have been allocated then assume valid multi binaural input in out[][] buffer and perform CLDFB analysis*/ + /* local float2fix, to be removed */ + num_poses = hSplitBinRend->splitrend.multiBinPoseData.num_poses; + move16(); + + FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) + { + Q_out[0] = s_min( Q_out[0], L_norm_arr( p_head_pose_buf[i], L_FRAME48k ) ); + } + + FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) + { + scale_sig32( p_head_pose_buf[i], L_FRAME48k, Q_out[0] ); + } + Q_out[0] = add( Q_out[0], Q11 ); + Q_out[1] = Q_out[0]; + move16(); + Q_buff = Q31 + Q6; // likely unneeded + move16(); + } + + IF( NE_32( ( 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, Q_buff, &Q_out[0] ) ), + IVAS_ERR_OK ) ) + { + return error; + } + + return IVAS_ERR_OK; +} +#endif /* FIX_1119_SPLIT_RENDERING_VOIP */ + /*---------------------------------------------------------------------* * IVAS_DEC_GetSamplesRenderer( ) @@ -1275,6 +1598,80 @@ 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; + Word32 head_pose_buf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES][L_FRAME48k]; + Word32 *p_head_pose_buf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES]; + Word16 i; + Word16 pcm_out_flag; + Word16 numSamplesPerChannelToOutput; + Word16 Q_out[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; + + test(); + IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + st_ivas = hIvasDec->st_ivas; + + IF( EQ_16( is_split_rendering_enabled( st_ivas->hDecoderConfig, st_ivas->hRenderConfig ), 0 ) ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + numSamplesPerChannelToOutput = isar_get_frame_size( st_ivas ); + move16(); + pcm_out_flag = 0; + move16(); + if ( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + pcm_out_flag = 1; + move16(); + } + + IF( NE_32( ( 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( NE_32( ( error = isar_generate_metadata_and_bitstream( st_ivas, p_head_pose_buf, *nOutSamples, splitRendBits, Q_out ) ), IVAS_ERR_OK ) ) + { + return error; + } + + /* convert to int16 with limiting for BINAURAL_SPLIT_PCM */ + IF( pcm_out_flag ) + { + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + scale_sig32( p_head_pose_buf[i], numSamplesPerChannelToOutput, sub( Q11, Q_out[i] ) ); // Q11 + } + IF( EQ_32( st_ivas->hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_5MS ) ) + { +#ifndef DISABLE_LIMITER + ivas_limiter_dec_fx( st_ivas->hLimiter, p_head_pose_buf, st_ivas->hDecoderConfig->nchan_out, numSamplesPerChannelToOutput, st_ivas->BER_detect, Q11 ); +#endif + } + ELSE + { + ivas_limiter_dec_fx( st_ivas->hLimiter, p_head_pose_buf, st_ivas->hDecoderConfig->nchan_out, numSamplesPerChannelToOutput, st_ivas->BER_detect, Q11 ); + } + + ivas_syn_output_fx( p_head_pose_buf, Q11, numSamplesPerChannelToOutput, st_ivas->hDecoderConfig->nchan_out, (int16_t *) pcmBuf_out ); + } +#else Decoder_Struct *st_ivas; AUDIO_CONFIG output_config; Word32 output_Fs; @@ -1527,6 +1924,7 @@ ivas_error IVAS_DEC_GetSplitBinauralBitstream( #ifndef TMP_FIX_SPLIT_REND free( st_ivas->hSplitBinRend->hMultiBinCldfbData ); +#endif #endif return IVAS_ERR_OK; @@ -1540,9 +1938,11 @@ ivas_error IVAS_DEC_GetSplitBinauralBitstream( *---------------------------------------------------------------------*/ static ivas_error ivas_dec_setup_all( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - UWord8 *nTransportChannels, /* o : number of decoded transport PCM channels */ - const Word16 isSplitRend, /* i : split rendering enabled flag */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + UWord8 *nTransportChannels, /* o : number of decoded transport PCM channels */ +#ifndef FIX_1119_SPLIT_RENDERING_VOIP + const Word16 isSplitRend, /* i : split rendering enabled flag */ +#endif ISAR_SPLIT_REND_BITS_DATA *splitRendBits /* o : output split rendering bits */ ) { @@ -1567,7 +1967,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 ) { @@ -1602,7 +2006,11 @@ static ivas_error ivas_dec_setup_all( *-----------------------------------------------------------------*/ test(); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + IF( EQ_16( 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 ) { @@ -3406,8 +3814,10 @@ static ivas_error apa_exec_evs_wrapper( *---------------------------------------------------------------------*/ ivas_error IVAS_DEC_GetSamplesDecoder( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - const Word16 isSplitRend, /* i : split rendering enabled flag */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ +#ifndef FIX_1119_SPLIT_RENDERING_VOIP + const Word16 isSplitRend, /* i : split rendering enabled flag */ +#endif ISAR_SPLIT_REND_BITS_DATA *splitRendBits /* o : output split rendering bits */ ) { @@ -3445,7 +3855,11 @@ ivas_error IVAS_DEC_GetSamplesDecoder( * Setup all decoder parts (IVAS decoder, ISAR) *-----------------------------------------------------------------*/ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + IF( NE_32( ( 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; } @@ -4159,25 +4573,43 @@ ivas_error IVAS_DEC_PrepareRenderer( } +#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 */ - UWord16 nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ - Word16 *pcmBuf, /* i/o: buffer for decoded PCM output. The memory must already be allocated and be able to hold the expected number of output samples, based on frame size and number of output channels Q0 */ +ivas_error IVAS_DEC_VoIP_GetSamples +#endif + ( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + UWord16 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 */ + Word16 *pcmBuf, /* o : output synthesis signal */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + ISAR_SPLIT_REND_BITS_DATA *splitRendBits, /* o : output split rendering bits */ + Word32 **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 */ - UWord16 *nSamplesRendered, /* o : number of samples rendered */ - bool *parametersAvailableForEditing, /* o : indicates whether objects editing is available */ - const UWord32 systemTimestamp_ms /* i : current system timestamp */ -) + bool *bitstreamReadDone, /* o : flag indicating that bitstream was read */ + UWord16 *nSamplesRendered, /* o : number of samples rendered */ + bool *parametersAvailableForEditing, /* o : indicates whether objects editing is available */ + const UWord32 systemTimestamp_ms /* i : current system timestamp */ + ) { Decoder_Struct *st_ivas; DECODER_CONFIG_HANDLE hDecoderConfig; @@ -4210,12 +4642,14 @@ ivas_error IVAS_DEC_VoIP_GetSamples( return IVAS_ERR_WRONG_PARAMS; } -#ifdef TMP_FIX_1119_SPLIT_RENDERING_VOIP +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + test(); test(); - IF( EQ_32( hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) || - EQ_32( hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) ) + IF( ( EQ_32( hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) || + EQ_32( hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) ) && + splitRendBits == NULL ) { - return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "Split rendering is not integrated with VoIP mode" ); + return IVAS_ERR_UNEXPECTED_NULL_POINTER; } #endif @@ -4388,7 +4822,11 @@ ivas_error IVAS_DEC_VoIP_GetSamples( test(); IF( hIvasDec->nSamplesAvailableNext == 0 || EQ_16( hIvasDec->nSamplesAvailableNext, hIvasDec->nSamplesFrame ) ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + IF( NE_32( ( error = IVAS_DEC_GetSamplesDecoder( hIvasDec, splitRendBits ) ), IVAS_ERR_OK ) ) +#else IF( ( error = IVAS_DEC_GetSamplesDecoder( hIvasDec, 0, 0 ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -4412,20 +4850,169 @@ ivas_error IVAS_DEC_VoIP_GetSamples( } } - /* render IVAS frames directly to the output buffer */ - IF( NE_32( ( error = IVAS_DEC_GetSamplesRenderer( hIvasDec, nSamplesToRender, pcmBuf + imult1616( *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( NE_32( ( 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( NE_32( ( error = IVAS_DEC_GetSamplesRenderer( hIvasDec, nSamplesToRender, pcmBuf + imult1616( *nSamplesRendered, nOutChannels ), &nSamplesRendered_loop, &tmp ) ), IVAS_ERR_OK ) ) + { + return error; + } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP } +#endif *nSamplesRendered = add( *nSamplesRendered, nSamplesRendered_loop ); update_voip_rendered20ms( hIvasDec, nSamplesRendered_loop ); } } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + IF( hIvasDec->hasDecodedFirstGoodFrame && splitRendBits != NULL ) + { + Word16 Q_out[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; + Word16 i; + + /* Analyse head poses over entire frame, generate ISAR metadata and maybe encode if split coded */ + IF( NE_32( ( error = isar_generate_metadata_and_bitstream( st_ivas, p_head_pose_buf, *nSamplesRendered, splitRendBits, Q_out ) ), IVAS_ERR_OK ) ) + { + return error; + } + + /* Synthesise PCM output if split PCM */ + IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + scale_sig32( p_head_pose_buf[i], *nSamplesRendered, sub( Q11, Q_out[i] ) ); // Q11 + } + + IF( EQ_32( st_ivas->hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_5MS ) ) + { +#ifndef DISABLE_LIMITER + ivas_limiter_dec_fx( st_ivas->hLimiter, p_head_pose_buf, st_ivas->hDecoderConfig->nchan_out, *nSamplesRendered, st_ivas->BER_detect, Q11 ); +#endif + } + ELSE + { + ivas_limiter_dec_fx( st_ivas->hLimiter, p_head_pose_buf, st_ivas->hDecoderConfig->nchan_out, *nSamplesRendered, st_ivas->BER_detect, Q11 ); + } + + ivas_syn_output_fx( p_head_pose_buf, Q11, *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 */ + UWord16 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 */ + Word16 *pcmBuf, /* o : output synthesis signal */ +#ifdef SUPPORT_JBM_TRACEFILE + JbmTraceFileWriterFn jbmWriterFn, + void *jbmWriter, +#endif + bool *bitstreamReadDone, /* o : flag indicating that bitstream was read */ + UWord16 *nSamplesRendered, /* o : number of samples rendered */ + bool *parametersAvailableForEditing, /* o : indicates whether objects editing is available */ + const UWord32 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 */ + Word16 *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 */ + UWord16 *nSamplesRendered, /* o : number of samples rendered */ + bool *parametersAvailableForEditing, /* o : indicates whether objects editing is available */ + const UWord32 systemTimestamp_ms /* i : current system timestamp */ +) +{ + Word16 i; + Word32 head_pose_buf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES][L_FRAME48k]; + Word32 *pp_head_pose_buf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES]; + ivas_error error = IVAS_ERR_UNKNOWN; + Word16 nSamplesPerChannel = 0; + + IF( NE_32( ( 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( ) @@ -4484,6 +5071,11 @@ 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; + move16(); +#endif + *nSamplesFlushed = s_min( nSamplesPerChannel, hIvasDec->nSamplesAvailableNext ); move16(); @@ -4504,6 +5096,11 @@ ivas_error IVAS_DEC_Flush( *nSamplesFlushed = 0; move16(); } +#ifdef TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR + hIvasDec->st_ivas->flushing = 0; + move16(); +#endif + return error; } @@ -5295,6 +5892,9 @@ static ivas_error ivas_create_handle_isar( ) { ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE hSplitBinRend; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Word16 i; +#endif IF( ( hSplitBinRend = (ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE) malloc( sizeof( ISAR_DEC_SPLIT_REND_WRAPPER ) ) ) == NULL ) { @@ -5303,7 +5903,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; @@ -5323,13 +5931,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 + Word16 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 ) @@ -5522,6 +6148,35 @@ static ivas_error ivas_dec_reconfig_split_rend( } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +/*-------------------------------------------------------------------* + * ivas_dec_split_rend_cldfb_in() + * + * + *-------------------------------------------------------------------*/ + +static Word16 ivas_dec_split_rend_cldfb_in( + const RENDERER_TYPE renderer_type /* i : renderer type */ +) +{ + test(); + test(); + test(); + IF( EQ_32( renderer_type, RENDERER_BINAURAL_FASTCONV ) || + EQ_32( renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) || + EQ_32( renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || + EQ_32( renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + return 1; + } + ELSE + { + return 0; + } +} +#endif + + /*-------------------------------------------------------------------* * ivas_dec_init_split_rend() * @@ -5535,11 +6190,19 @@ static ivas_error ivas_dec_init_split_rend( ivas_error error; Word16 cldfb_in_flag, pcm_out_flag; Word16 mixed_td_cldfb_flag; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Word16 i, num_poses; + ISAR_SPLIT_REND_ROT_AXIS head_rot_axis; +#endif pcm_out_flag = ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0; cldfb_in_flag = 0; move16(); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + cldfb_in_flag = ivas_dec_split_rend_cldfb_in( st_ivas->renderer_type ); +#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 ) @@ -5556,8 +6219,44 @@ static ivas_error ivas_dec_init_split_rend( cldfb_in_flag = 1; move16(); } +#endif + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + head_rot_axis = DEFAULT_AXIS; + move32(); + if ( st_ivas->hHeadTrackData != NULL ) + { + head_rot_axis = st_ivas->hHeadTrackData->sr_pose_pred_axis; + move32(); + } + ISAR_PRE_REND_GetMultiBinPoseData( &st_ivas->hRenderConfig->split_rend_config, &st_ivas->hSplitBinRend->splitrend.multiBinPoseData, head_rot_axis ); + + num_poses = st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses; + move16(); + 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( NE_32( ( 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( NE_32( ( error = ivas_TD_RINGBUF_Open( &st_ivas->hSplitBinRend->hMultiBinTdData, get_render_frame_size_samples( st_ivas->hDecoderConfig ), i_mult( num_poses, BINAURAL_CHANNELS ) ) ), IVAS_ERR_OK ) ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for split rendering structure" ); + } + } +#else 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( EQ_16( cldfb_in_flag, 1 ) && ( EQ_16( st_ivas->hSplitBinRend->splitrend.multiBinPoseData.poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) ) ) { diff --git a/lib_isar/isar_prot.h b/lib_isar/isar_prot.h index d2db093596aef285757d9ad7ab0698240f609304..e1b173e02c4655a9e462eb3e0078ad76e5a67788 100644 --- a/lib_isar/isar_prot.h +++ b/lib_isar/isar_prot.h @@ -33,7 +33,6 @@ #ifndef ISAR_PROT_H #define ISAR_PROT_H - #include "isar_stat.h" #include #include "options.h" @@ -42,19 +41,64 @@ #include "enh64.h" /* clang-format off */ +/*----------------------------------------------------------------------------------* + * General ISAR prototypes + *----------------------------------------------------------------------------------*/ + +ivas_error isar_splitBinPreRendOpen( + 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 Word32 output_Fs +#endif +); + +ivas_error split_renderer_open_lc3plus( + 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 Word32 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 /* i/o: binaural pre-renderer handle */ +); + +void lc3plusTimeAlignCldfbPoseCorr( + SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renderer handle */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Word32 *Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX], /* i/o: Binaural signals, real part */ + Word32 *Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX], /* i/o: Binaural signals, imag. part */ +#else + Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], +#endif + Word16 *Q_in +); +ivas_error splitRendLc3plusEncodeAndWrite( + SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renderer handle */ + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */ + const Word32 available_bits, /* i : available bit-budget */ + Word32 *in[], /* i/o: PCM in/out buffer */ + Word16 Q_sig +); + +/*! r: parameter value */ Word32 ISAR_SPLIT_REND_BITStream_read_int32( - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const Word32 bits ); + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */ + const Word32 bits /* i : number of bits to be read */ +); void ISAR_SPLIT_REND_BITStream_write_int32( - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const Word32 val, - const Word32 bits + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */ + const Word32 val, /* i : parameter value */ + const Word32 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 Word32 iSampleRate, const Word16 iChannels, const Word32 iDataRate, @@ -63,15 +107,16 @@ ivas_error isar_splitBinLCLDEncOpen( ); ivas_error isar_splitBinRendPLCOpen( - ISAR_SPLIT_REND_PLC_HANDLE *phSplitRendPLC, - const Word16 iNumSubSets ); + ISAR_SPLIT_REND_PLC_HANDLE *phSplitRendPLC, /* i/o: ISAR PLC handle */ + const Word16 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 Word32 iSampleRate, const Word16 iChannels, const Word16 iNumBlocks, @@ -79,7 +124,7 @@ ivas_error isar_splitBinLCLDDecOpen( ); 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( @@ -126,47 +171,43 @@ void isar_log_cldfb2wav_data( const Word16 md_band_idx, const char *filename ); -#endif - -void isar_SplitRenderer_PostRenderer( - ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinPostRenderer, /* i/o: binaural renderer handle */ - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, - Word32 Cldfb_RealBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o : Reference/out Binaural signals */ - Word32 Cldfb_ImagBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o : Reference/out Binaural signals */ - const IVAS_QUATERNION Quaternion_act, - Word16 *Q_in -); +#endif void isar_splitBinLCLDDecProcess( - ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE hSplitBinLCLDDec, - ISAR_SPLIT_REND_BITS_HANDLE pBits, - Word32 Cldfb_Out_Real_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - Word32 Cldfb_Out_Imag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + 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 */ + Word32 Cldfb_Out_Real_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Binaural signals, real part */ + Word32 Cldfb_Out_Imag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Binaural signals, imag. part */ Word16 *Q_cldfb_final, - const Word16 bfi + const Word16 bfi /* i : BFI flag */ ); void set_fix_rotation_mat_fx( Word32 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 + Word32 *Cldfb_In_Real_fx[][CLDFB_NO_COL_MAX], /* i/o: Binaural signals, real part */ + Word32 *Cldfb_In_Imag_fx[][CLDFB_NO_COL_MAX], /* i/o: Binaural signals, imag. part */ +#else Word32 Cldfb_In_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 Cldfb_In_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - const Word32 available_bits, - ISAR_SPLIT_REND_BITS_HANDLE pBits, +#endif + const Word32 available_bits, /* i : available bit-budget */ + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */ Word16 *q_final ); void set_pose_types_fx( - 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( @@ -174,13 +215,13 @@ void isar_split_rend_init_huff_cfg( ); ivas_error isar_splitBinPostRendOpen( - ISAR_BIN_HR_SPLIT_POST_REND_HANDLE *hBinHrSplitPostRend, - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, - const Word32 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 Word32 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( @@ -191,18 +232,6 @@ void isar_SplitRenderer_getdiagdiff( const Word16 max_val ); -void isar_renderSplitGetMultiBinPoseData_fx( - const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, - const ISAR_SPLIT_REND_ROT_AXIS rot_axis -); - -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 -); - void isar_split_rend_get_quant_params_fx( const Word16 num_md_bands, Word16 pred_real_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], @@ -219,20 +248,20 @@ void isar_split_rend_get_quant_params_fx( ); void isar_splitBinPostRendMdDec_fx( - ISAR_SPLIT_REND_BITS_HANDLE pBits, - ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend, - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData + 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 , - BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend + 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_fx( @@ -251,8 +280,8 @@ void isar_mat_mult_2by2_complex_fx( ); 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, Word32 Cldfb_RealBuffer_Binaural_fx[][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], Word32 Cldfb_ImagBuffer_Binaural_fx[][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], @@ -262,21 +291,21 @@ void isar_rend_CldfbSplitPostRendProcess( const Word16 cldfb_in_flag ); -void isar_init_multi_bin_pose_data_fx( - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); - -/* Copy for encoder, to be removed */ -void isar_init_multi_bin_pose_data_fx_enc( - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData -); - void isar_rend_CldfbSplitPreRendProcess( - const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, - const IVAS_QUATERNION headPosition, - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + 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 + Word32* Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX], /* i : Binaural signals, real part */ +#else Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], +#endif Word16 exp_cldfb_re, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Word32* Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX], /* i : Binaural signals, imag. part */ +#else Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], +#endif Word16 exp_cldfb_im, ISAR_SPLIT_REND_BITS_HANDLE pBits, const Word32 target_md_bits, @@ -284,6 +313,32 @@ void isar_rend_CldfbSplitPreRendProcess( const Word16 ro_md_flag ); +ivas_error isar_renderMultiTDBinToSplitBinaural( + SPLIT_REND_WRAPPER *hSplitBin, + const IVAS_QUATERNION headPosition, + const Word32 SplitRendBitRate, + const Word16 isar_frame_size_ms, + const Word16 codec_frame_size_ms, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + const Word16 max_bands, + // float *in[], + Word32 *in_fx[], // Q11 + Word16 Q_sig, + const Word16 low_res_pre_rend_rot, + const Word16 pcm_out_flag, + const Word16 ro_md_flag +); + +void isar_init_multi_bin_pose_data_fx( + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData /* i/o: pose correction data handle */ +); + +void isar_renderSplitGetMultiBinPoseData_fx( + 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 */ +); + Word16 isar_renderSplitGetRot_axisNumBits( const Word16 dof ); @@ -300,86 +355,56 @@ Word16 isar_renderSplitGetCodeFromRot_axis( ); void isar_init_split_post_rend_handles( - ISAR_SPLIT_POST_REND_WRAPPER *hSplitRendWrapper ); - -ivas_error isar_splitBinPreRendOpen( - ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend, -#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, - const Word32 output_Fs -#else - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData -#endif -); - -void isar_splitBinPreRendClose( - ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend + ISAR_SPLIT_POST_REND_WRAPPER *hSplitRendWrapper /* i/o: Split renderer post-renderer handle */ ); void isar_set_split_rend_ht_setup_fx( - SPLIT_REND_WRAPPER *hSplitrend, - IVAS_QUATERNION Quaternions[MAX_PARAM_SPATIAL_SUBFRAMES], - Word32 Rmat_fx[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 */ + Word32 Rmat_fx[MAX_PARAM_SPATIAL_SUBFRAMES][3][3] /* o : real-space rotation matrix */ ); Word32 isar_get_lc3plus_bitrate( - const Word32 SplitRendBitRate, - const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode, - const Word32 nChannels, - const Word32 codecFrameDurationUs ); + const Word32 SplitRendBitRate, /* i : ISAR bitrate */ + const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode, /* i : ISAR pose correction mode */ + const Word32 nChannels, /* i : number of channels */ + const Word32 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 Word16 is_pcm_out + const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, /* i : Split renderer pre-renderer config */ + const Word16 is_pcm_out /* i : flag to indicate PCM output */ ); +/*! r: LCLD codec bitrate */ Word32 isar_get_lcld_bitrate( - const Word32 SplitRendBitRate, - const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode + const Word32 SplitRendBitRate, /* i : ISAR bitrate */ + const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode /* i : ISAR pose correction mode */ ); -ivas_error splitRendLc3plusEncodeAndWrite( - SPLIT_REND_WRAPPER *hSplitBin, - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const Word32 available_bits, - Word32 *in[], - Word16 Q_sig +/*! r: ISAR MD bitrate */ +Word32 isar_get_split_rend_md_target_brate( + const Word32 SplitRendBitRate, /* i : ISAR bitrate */ + const Word16 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 */ - Word16 *ms /* o : frame size in ms */ -); - -Word32 isar_get_split_rend_md_target_brate( - const Word32 SplitRendBitRate, - const Word16 pcm_out_flag + const IVAS_RENDER_FRAMESIZE frame_size, /* i : frame size enum */ + Word16 *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 */ - Word16 *pIsar_frame_size_ms, /* i/o: pointer to ISAR frame size setting */ - Word16 *pCodec_frame_size_ms, /* i/o: pointer to codec frame size setting */ - const Word16 cldfb_in_flag, /* i : flag indicating rendering in TD */ - const Word16 pcm_out_flag, /* i : flag to indicate PCM output */ - const Word16 num_subframes /* i : number of subframes */ -); - -void ISAR_SPLIT_REND_BITStream_init( - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const Word32 buf_len_bytes, - UWord8 *pbuf -); - -Word16 wrap_a( - Word16 val, - const Word16 min_val, - const Word16 max_val + ISAR_SPLIT_REND_CODEC *pCodec, /* i/o: pointer to codec setting */ + Word16 *pIsar_frame_size_ms, /* i/o: pointer to ISAR frame size setting */ + Word16 *pCodec_frame_size_ms, /* i/o: pointer to codec frame size setting */ + const Word16 cldfb_in_flag, /* i : flag indicating rendering in TD */ + const Word16 pcm_out_flag, /* i : flag to indicate PCM output */ + const Word16 num_subframes /* i : number of subframes */ ); 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 */ ); Word32 get_bit( @@ -387,44 +412,46 @@ Word32 get_bit( const Word32 bit_id ); -ivas_error split_renderer_open_lc3plus( - SPLIT_REND_WRAPPER *hSplitRendWrapper, - const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, - const Word32 OutSampleRate, - const IVAS_RENDER_FRAMESIZE ivas_frame_size -); - +/*! 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 */ ); -ivas_error isar_renderMultiTDBinToSplitBinaural( - SPLIT_REND_WRAPPER *hSplitBin, - const IVAS_QUATERNION headPosition, - const Word32 SplitRendBitRate, - const Word16 isar_frame_size_ms, - const Word16 codec_frame_size_ms, - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const Word16 max_bands, - // float *in[], - Word32 *in_fx[], // Q11 - Word16 Q_sig, - const Word16 low_res_pre_rend_rot, - const Word16 pcm_out_flag, - const Word16 ro_md_flag +/*----------------------------------------------------------------------------------* + * BASOP-only + *----------------------------------------------------------------------------------*/ + +/* Copy for encoder, to be removed */ +void isar_init_multi_bin_pose_data_fx_enc( + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); -void lc3plusTimeAlignCldfbPoseCorr( - SPLIT_REND_WRAPPER *hSplitBin, - Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - Word16 *Q_in + +Word16 wrap_a( + Word16 val, + const Word16 min_val, + const Word16 max_val ); +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 +); + + +void isar_SplitRenderer_PostRenderer( + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinPostRenderer, /* i/o: binaural renderer handle */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + Word32 Cldfb_RealBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o : Reference/out Binaural signals */ + Word32 Cldfb_ImagBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o : Reference/out Binaural signals */ + const IVAS_QUATERNION Quaternion_act, + Word16 *Q_in +); void ivas_cmult_fix( Word32 in1_re_fx, diff --git a/lib_isar/isar_splitRend_lcld_enc.c b/lib_isar/isar_splitRend_lcld_enc.c index e6efe1ff29ed954ee9bf9b865340cba172f83f35..b1249653f805e7ad97c993a46c8b5e7e3984ef24 100644 --- a/lib_isar/isar_splitRend_lcld_enc.c +++ b/lib_isar/isar_splitRend_lcld_enc.c @@ -152,10 +152,15 @@ void isar_splitBinLCLDEncClose( *------------------------------------------------------------------------*/ void isar_splitBinLCLDEncProcess( ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE hSplitBinLCLDEnc, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Word32 *Cldfb_In_Real_fx[][CLDFB_NO_COL_MAX], /* i/o: Binaural signals, real part */ + Word32 *Cldfb_In_Imag_fx[][CLDFB_NO_COL_MAX], /* i/o: Binaural signals, imag part */ +#else Word32 Cldfb_In_Real_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 Cldfb_In_Imag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - const Word32 available_bits, - ISAR_SPLIT_REND_BITS_HANDLE pBits, +#endif + const Word32 available_bits, /* i : available bit-budget */ + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */ Word16 *q_final ) { Word32 iBitsWritten, itr, available_bits_itr, rem_itr, available_bits_local; diff --git a/lib_isar/isar_splitRendererPre.c b/lib_isar/isar_splitRendererPre.c index 71e285a9cbad6587313e87688c5be37d33bc8fe1..dacb1777f12822f5399bc736c6da5b5d7118b4b1 100644 --- a/lib_isar/isar_splitRendererPre.c +++ b/lib_isar/isar_splitRendererPre.c @@ -50,6 +50,25 @@ #endif #include "basop_util.h" +/*---------------------------------------------------------------------* + * Local function declarations + *---------------------------------------------------------------------*/ + +static void isar_SplitRenderer_GetRotMd_fx( ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Word32 *Cldfb_RealBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX], + Word16 exp_cldfb_re, + Word32 *Cldfb_ImagBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX], + Word16 exp_cldfb_im, +#else + Word32 Cldfb_RealBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 exp_cldfb_re, + Word32 Cldfb_ImagBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 exp_cldfb_im, +#endif + const Word16 low_res, + const Word16 ro_md_flag ); /*------------------------------------------------------------------------- * Local functions @@ -505,15 +524,29 @@ static void ComputePostPredCov_fx( static void ComputeBandedCrossCov_fx( +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Word32 *Cldfb_RealBuffer1_fx[][CLDFB_NO_COL_MAX], + Word16 exp_cldfb_re_1, + Word32 *Cldfb_ImagBuffer1_fx[][CLDFB_NO_COL_MAX], + Word16 exp_cldfb_im_1, +#else Word32 Cldfb_RealBuffer1_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word16 exp_cldfb_re_1, Word32 Cldfb_ImagBuffer1_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word16 exp_cldfb_im_1, +#endif const Word16 ch_start_idx1, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Word32 *Cldfb_RealBuffer2_fx[][CLDFB_NO_COL_MAX], + Word16 exp_cldfb_re_2, + Word32 *Cldfb_ImagBuffer2_fx[][CLDFB_NO_COL_MAX], + Word16 exp_cldfb_im_2, +#else Word32 Cldfb_RealBuffer2_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word16 exp_cldfb_re_2, Word32 Cldfb_ImagBuffer2_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word16 exp_cldfb_im_2, +#endif const Word16 ch_start_idx2, Word32 out_cov_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word16 *exp_out_cov_re, @@ -646,10 +679,17 @@ static void ComputeBandedCrossCov_fx( static void ComputeBandedCov_fx( +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Word32 *Cldfb_RealBuffer_fx[][CLDFB_NO_COL_MAX], + Word16 exp_cldfb_re, + Word32 *Cldfb_ImagBuffer_fx[][CLDFB_NO_COL_MAX], + Word16 exp_cldfb_im, +#else Word32 Cldfb_RealBuffer_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word16 exp_cldfb_re, Word32 Cldfb_ImagBuffer_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word16 exp_cldfb_im, +#endif const Word16 ch_start_idx, Word32 out_cov_re_fx[][BINAURAL_CHANNELS], Word16 *exp_cov_re, @@ -2142,14 +2182,20 @@ static void isar_SplitRenderer_quant_code( * * *------------------------------------------------------------------------*/ - static void isar_SplitRenderer_GetRotMd_fx( 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 + Word32 *Cldfb_RealBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX], /* o : Reference Binaural signals */ + Word16 exp_cldfb_re, + Word32 *Cldfb_ImagBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX], /* o : Reference Binaural signals */ + Word16 exp_cldfb_im, +#else Word32 Cldfb_RealBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Reference Binaural signals */ Word16 exp_cldfb_re, Word32 Cldfb_ImagBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Reference Binaural signals */ Word16 exp_cldfb_im, +#endif const Word16 low_res, const Word16 ro_md_flag ) { @@ -2245,17 +2291,25 @@ static void isar_SplitRenderer_GetRotMd_fx( *------------------------------------------------------------------------*/ void isar_rend_CldfbSplitPreRendProcess( - const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, - const IVAS_QUATERNION headPosition, - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + 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 + Word32 *Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX], /* i : Binaural signals, real part */ + Word16 exp_cldfb_re, + Word32 *Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX], + Word16 exp_cldfb_im, +#else Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word16 exp_cldfb_re, Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word16 exp_cldfb_im, - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const Word32 target_md_bits, - const Word16 low_res_pre_rend_rot, - const Word16 ro_md_flag ) +#endif + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits handle */ + const Word32 target_md_bits, /* i : ISAR MD bitrate */ + const Word16 low_res_pre_rend_rot, /* i : low time resolution pre-renderer flag */ + const Word16 ro_md_flag /* i : real only metadata for yaw flag */ +) { push_wmops( "isar_rend_CldfbSplitPreRendProcess" ); @@ -2860,6 +2914,11 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( UWord8 useLc3plus; Word32 *in_delayed_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; Word16 i; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Word16 j; + Word32 *p_Cldfb_In_BinReal[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX]; + Word32 *p_Cldfb_In_BinImag[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX]; +#endif Word32 num_slots; push_wmops( "isar_renderMultiTDBinToSplitBinaural" ); @@ -2869,6 +2928,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_fx[i][j]; + p_Cldfb_In_BinImag[i][j] = Cldfb_In_BinImag_fx[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*/ @@ -2989,7 +3059,25 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( q_final = add( q_final, scale_factor ); Word16 exp_cldfb_re = sub( 31, q_final ); Word16 exp_cldfb_im = sub( 31, q_final ); - isar_rend_CldfbSplitPreRendProcess( hSplitBin->hBinHrSplitPreRend, headPosition, &hSplitBin->multiBinPoseData, Cldfb_In_BinReal_fx, exp_cldfb_re, Cldfb_In_BinImag_fx, exp_cldfb_im, 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, + exp_cldfb_re, + p_Cldfb_In_BinImag, + exp_cldfb_im, +#else + Cldfb_In_BinReal_fx, + exp_cldfb_re, + Cldfb_In_BinImag_fx, + exp_cldfb_im, +#endif + pBits, + target_md_bits, + low_res_pre_rend_rot, + ro_md_flag ); } IF( EQ_16( pcm_out_flag, 0 ) ) @@ -3009,7 +3097,18 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( move16(); pBits->isar_frame_size_ms = isar_frame_size_ms; move16(); - isar_splitBinLCLDEncProcess( hSplitBin->hSplitBinLCLDEnc, Cldfb_In_BinReal_fx, Cldfb_In_BinImag_fx, available_bits, pBits, &q_final ); + isar_splitBinLCLDEncProcess( + hSplitBin->hSplitBinLCLDEnc, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + p_Cldfb_In_BinReal, + p_Cldfb_In_BinImag, +#else + Cldfb_In_BinReal_fx, + Cldfb_In_BinImag_fx, +#endif + available_bits, + pBits, + &q_final ); } ELSE { @@ -3085,9 +3184,14 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( *------------------------------------------------------------------------*/ void lc3plusTimeAlignCldfbPoseCorr( - SPLIT_REND_WRAPPER *hSplitBin, - Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - Word32 Cldfb_In_BinImag_fx[][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 + Word32 *Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX], /* i/o: Binaural signals, real part */ + Word32 *Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX], /* i/o: Binaural signals, imag. part */ +#else + Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: Binaural signals, real part */ + Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: Binaural signals, imag. part */ +#endif Word16 *Q_in ) { Word32 Cldfb_In_BinReal_tmp_fx[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][2][CLDFB_NO_CHANNELS_MAX]; @@ -3107,7 +3211,12 @@ void lc3plusTimeAlignCldfbPoseCorr( } ELSE { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + FOR( Word16 i = 0; i < i_mult( hSplitBin->multiBinPoseData.num_poses, BINAURAL_CHANNELS ); i++ ) +#else FOR( Word16 i = 0; i < CLDFB_NO_COL_MAX; i++ ) +#endif + { for ( Word16 j = 0; j < CLDFB_NO_COL_MAX; j++ ) { diff --git a/lib_isar/isar_splitRenderer_utils.c b/lib_isar/isar_splitRenderer_utils.c index 54e0ec79c781436e31b3a021e1448b0a569c4cc2..6f72ce6516262d58689f0dcccb78e689db370068 100644 --- a/lib_isar/isar_splitRenderer_utils.c +++ b/lib_isar/isar_splitRenderer_utils.c @@ -212,29 +212,6 @@ void isar_mat_mult_2by2_complex_fx( } -/*------------------------------------------------------------------------- - * Function ISAR_SPLIT_REND_BITStream_init() - * - * - *------------------------------------------------------------------------*/ - -void ISAR_SPLIT_REND_BITStream_init( - ISAR_SPLIT_REND_BITS_HANDLE pBits, - const Word32 buf_len_bytes, - UWord8 *pbuf ) -{ - pBits->bits_buf = pbuf; - pBits->buf_len = buf_len_bytes; - move32(); - pBits->bits_read = 0; - move32(); - pBits->bits_written = 0; - move32(); - - 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 351cb4525e3d9f46914c5456e29a444e21c2480c..4576e7c1ddac64c7f7ecb40510cc765f6b4c92ec 100644 --- a/lib_isar/isar_stat.h +++ b/lib_isar/isar_stat.h @@ -256,5 +256,17 @@ typedef struct Word32 lc3plusDelaySamples; } SPLIT_REND_WRAPPER; +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +typedef struct +{ + Word32 *real; + Word32 *imag; + Word16 capacity; + Word16 write_pos; + Word16 read_pos; + Word16 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 1ba5cafc4ed0bfb5c5e7b8502b92475e80997521..49f2f4964a75cbef1004bf1f8137c995ecde5f13 100644 --- a/lib_isar/lib_isar_pre_rend.c +++ b/lib_isar/lib_isar_pre_rend.c @@ -278,21 +278,26 @@ void ISAR_PRE_REND_GetMultiBinPoseData( *------------------------------------------------------------------------*/ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( - SPLIT_REND_WRAPPER *hSplitBin, - const IVAS_QUATERNION headPosition, - const Word32 SplitRendBitRate, - ISAR_SPLIT_REND_CODEC splitCodec, - const Word16 isar_frame_size_ms, /* i: ISAR framesize */ - Word16 codec_frame_size_ms, + SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renerer handle */ + const IVAS_QUATERNION headPosition, /* i : head rotation QUATERNION */ + const Word32 SplitRendBitRate, /* i : Split renderer bitrate */ + ISAR_SPLIT_REND_CODEC splitCodec, /* i/o: Split renderer codec */ + const Word16 isar_frame_size_ms, /* i : ISAR framesize */ + Word16 codec_frame_size_ms, /* i/o: ISAR transport codec framesize */ ISAR_SPLIT_REND_BITS_HANDLE pBits, +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Word32 *Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX], /* i/o: CLDFB real buffer */ + Word32 *Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX], /* i/o: CLDFB imag buffer */ +#else Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - const Word16 max_bands, - Word32 *pOutput_fx[], - const Word16 low_res_pre_rend_rot, - const Word16 cldfb_in_flag, - const Word16 pcm_out_flag, - const Word16 ro_md_flag, +#endif + const Word16 max_bands, /* i : CLDFB bands */ + Word32 *pOutput_fx[], /* i/o: PCM in/out buffer */ + const Word16 low_res_pre_rend_rot, /* i : low time resolution pre-renderer flag */ + const Word16 cldfb_in_flag, /* i : Flag to indicate CLDFB or time domain input */ + const Word16 pcm_out_flag, /* i : Flag to indicate PCM output */ + const Word16 ro_md_flag, /* i : Flag to indicate real only metadata for yaw */ Word16 Q_buff, Word16 *Q_out ) { @@ -415,7 +420,11 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( move16(); FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + FOR( j = 0; j < num_slots; j++ ) +#else FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) +#endif { q1 = s_min( getScaleFactor32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q1 ); q2 = s_min( getScaleFactor32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q2 ); @@ -429,7 +438,11 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + FOR( j = 0; j < num_slots; j++ ) +#else FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) +#endif { Scale_sig32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_re ) ); Scale_sig32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_im ) ); @@ -480,7 +493,9 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( } ELSE { - Word16 ch, slot_idx; + Word16 ch, slot_idx, num_slots; + num_slots = int_div_s_x( shl( isar_frame_size_ms, 3 ), 10 ); + /* CLDFB synthesis of main pose */ FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { @@ -490,7 +505,11 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( move16(); q2 = 31; move16(); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + FOR( j = 0; j < num_slots; j++ ) +#else FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) +#endif { q1 = s_min( getScaleFactor32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q1 ); q2 = s_min( getScaleFactor32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q2 ); @@ -499,13 +518,17 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( q_final = s_min( add( Q_buff_re, q_final ), add( Q_buff_im, q_final ) ); q_final = sub( q_final, 6 ); // guard bits q_final = s_min( q_final, Q25 ); +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + FOR( j = 0; j < num_slots; j++ ) +#else FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) +#endif { Scale_sig32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_re ) ); Scale_sig32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_im ) ); } - 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_fx[slot_idx] = Cldfb_In_BinReal_fx[ch][slot_idx]; move32(); @@ -516,7 +539,7 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( Q_cldfb = q_final; move16(); Scale_sig32( hSplitBin->hCldfbHandles->cldfbSyn[ch]->cldfb_state_fx, hSplitBin->hCldfbHandles->cldfbSyn[ch]->p_filter_length, sub( sub( Q_cldfb, 1 ), hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_cldfb_state ) ); - cldfbSynthesis_ivas_fx( Cldfb_In_BinReal_p_fx, Cldfb_In_BinImag_p_fx, pOutput_fx[ch], hSplitBin->hCldfbHandles->cldfbSyn[0]->no_channels * CLDFB_NO_COL_MAX, 0, 0, hSplitBin->hCldfbHandles->cldfbSyn[ch] ); // Q_cldfb - 1 + cldfbSynthesis_ivas_fx( Cldfb_In_BinReal_p_fx, Cldfb_In_BinImag_p_fx, pOutput_fx[ch], i_mult( hSplitBin->hCldfbHandles->cldfbSyn[0]->no_channels, num_slots ), 0, 0, hSplitBin->hCldfbHandles->cldfbSyn[ch] ); // Q_cldfb - 1 Q_out[ch] = sub( Q_cldfb, 1 ); move16(); hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_cldfb_state = Q_out[ch]; diff --git a/lib_isar/lib_isar_pre_rend.h b/lib_isar/lib_isar_pre_rend.h index 772637db90a82eea23d6f6edd08a189f3a157422..9ee1aae8696f2c27b3b2960c575d2c1f82b1a7d8 100644 --- a/lib_isar/lib_isar_pre_rend.h +++ b/lib_isar/lib_isar_pre_rend.h @@ -70,8 +70,13 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( const Word16 isar_frame_size_ms, /* i : ISAR framesize */ Word16 codec_frame_size_ms, /* i/o: Split renderer codec framesize */ ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: Split renderer bitstream handle */ +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + Word32* Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX], /* i/o: CLDFB real buffer */ + Word32* Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX], /* i/o: CLDFB imag buffer */ +#else Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB real buffer */ Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB imag buffer */ +#endif const Word16 max_bands, /* i : CLDFB bands */ Word32 *pOutput_fx[], /* i : low time resolution pre-renderer flag */ const Word16 low_res_pre_rend_rot, /* i : low time resolution pre-renderer flag */ diff --git a/lib_rend/ivas_cldfb_ring_buffer.c b/lib_rend/ivas_cldfb_ring_buffer.c new file mode 100644 index 0000000000000000000000000000000000000000..49d88e8f31479242a234ffa95585e56425e45f16 --- /dev/null +++ b/lib_rend/ivas_cldfb_ring_buffer.c @@ -0,0 +1,321 @@ +/****************************************************************************************************** + + (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_fx.h" +#include "ivas_prot_fx.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 Word16 ivas_cldfb_ringbuf_IsEmpty( + ISAR_CLDFB_RINGBUF_HANDLE h ) +{ + test(); + return EQ_16( 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 Word16 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 Word16 capacity_columns ) +{ + ISAR_CLDFB_RINGBUF_HANDLE h; + Word16 capacity; + + capacity = i_mult( capacity_columns, CLDFB_NO_CHANNELS_MAX ); + move16(); + + 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; + move16(); + h->write_pos = 0; + move16(); + h->read_pos = 0; + move16(); + h->is_full = 0; + move16(); + *ph = h; + + IF( ( h->real = malloc( capacity * sizeof( Word32 ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for CLDFB ring buffer\n" ); + } + IF( ( h->imag = malloc( capacity * sizeof( Word32 ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for CLDFB ring buffer\n" ); + } + h->capacity = capacity; + move16(); + + 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() + * + * Pushes 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 Word32 *real, + const Word32 *imag, + const Word16 num_bands ) +{ + assert( num_bands <= CLDFB_NO_CHANNELS_MAX ); + assert( !ivas_cldfb_ringbuf_IsFull( h ) ); + + Copy32( real, &h->real[h->write_pos], num_bands ); + Copy32( imag, &h->imag[h->write_pos], num_bands ); + + h->write_pos = add( h->write_pos, CLDFB_NO_CHANNELS_MAX ); + move16(); + IF( EQ_16( h->write_pos, h->capacity ) ) + { + h->write_pos = 0; + move16(); + } + + IF( EQ_16( h->read_pos, h->write_pos ) ) + { + h->is_full = 1; + move16(); + } + + 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, + Word32 *real, + Word32 *imag, + const Word16 num_bands ) +{ + assert( num_bands <= CLDFB_NO_CHANNELS_MAX ); + assert( !ivas_cldfb_ringbuf_IsEmpty( h ) ); + + IF( real != NULL ) + { + Copy32( &h->real[h->read_pos], real, num_bands ); + } + IF( imag != NULL ) + { + Copy32( &h->imag[h->read_pos], imag, num_bands ); + } + + h->read_pos = add( h->read_pos, CLDFB_NO_CHANNELS_MAX ); + move16(); + IF( EQ_16( h->read_pos, h->capacity ) ) + { + h->read_pos = 0; + move16(); + } + + h->is_full = 0; + move16(); + + return; +} + + +/*---------------------------------------------------------------------* + * ivas_cldfb_ringbuf_total_size() + * + * Returns total number of buffered samples (including number of channels) + *---------------------------------------------------------------------*/ + +static Word32 ivas_cldfb_ringbuf_total_size( + ISAR_CLDFB_RINGBUF_HANDLE h ) +{ + IF( ivas_cldfb_ringbuf_IsFull( h ) ) + { + return h->capacity; + } + + IF( LE_16( h->read_pos, h->write_pos ) ) + { + return sub( h->write_pos, h->read_pos ); + } + + /* else wrap around */ + return add( h->write_pos, sub( h->capacity, h->read_pos ) ); +} + + +/*---------------------------------------------------------------------* + * ivas_CLDFB_RINGBUF_GetByIdx() + * + * Gets 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, + Word32 **p_real, + Word32 **p_imag, + const Word16 col_idx ) +{ + Word16 idx = i_mult( col_idx, CLDFB_NO_CHANNELS_MAX ); + move16(); + Word16 num_floats = extract_l( ivas_cldfb_ringbuf_total_size( h ) ); + move16(); + Word16 offset /*, uidx */; // uidx unused in FX code + + assert( -num_floats <= idx && idx <= num_floats ); + + IF( GE_16( idx, 0 ) ) + { + offset = add( h->read_pos, idx ); + move16(); + IF( LE_16( h->capacity, offset ) ) + { + offset = sub( offset, h->capacity ); + move16(); + } + } + ELSE + { + idx = negate( idx ); + move16(); + IF( LE_16( idx, h->write_pos ) ) + { + offset = sub( h->write_pos, idx ); + move16(); + } + ELSE + { + offset = add( h->write_pos, sub( h->capacity, idx ) ); + move16(); + } + } + + *p_real = &h->real[offset]; + move16(); + *p_imag = &h->imag[offset]; + move16(); + + return; +} +#endif diff --git a/lib_rend/ivas_dirac_dec_binaural_functions_fx.c b/lib_rend/ivas_dirac_dec_binaural_functions_fx.c index 60bbce7a9d0ac5525df3ed992f9c7866849a4f5d..e187f494c35dd62ee8d24c9c7263b680ab6c0222 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions_fx.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions_fx.c @@ -1091,8 +1091,12 @@ static void ivas_dirac_dec_binaural_internal_fx( { 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 Copy32( tmp_Cldfb_out_re[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX ); Copy32( tmp_Cldfb_out_im[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX ); +#endif } } } @@ -1152,11 +1156,19 @@ static void ivas_dirac_dec_binaural_internal_fx( Copy( st_ivas->hDiracDecBin[0]->ChCrossIm_e, hDiracDecBin->ChCrossIm_e, hSpatParamRendCom->num_freq_bands ); ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( 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_fx, subFrameTotalEne_e, IIReneLimiter_fx, st_ivas->hMasaIsmData ); ivas_dirac_dec_binaural_determine_processing_matrices_fx( 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 ); q_mat = hDiracDecBin->q_processMtx; @@ -1204,8 +1216,12 @@ static void ivas_dirac_dec_binaural_internal_fx( { 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 Copy32( tmp_Cldfb_out_re[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[pos_idx * BINAURAL_CHANNELS + ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX ); Copy32( tmp_Cldfb_out_im[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[pos_idx * BINAURAL_CHANNELS + ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX ); +#endif } } diff --git a/lib_rend/ivas_prot_rend_fx.h b/lib_rend/ivas_prot_rend_fx.h index 250fea7515e5222ce88904254b9b70510c34341d..c2274202ead7c90cf4c6c736bb14d1bc16c929aa 100644 --- a/lib_rend/ivas_prot_rend_fx.h +++ b/lib_rend/ivas_prot_rend_fx.h @@ -1594,6 +1594,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 Word16 capacity_per_channel, /* i : Number of samples stored per channel */ + const Word16 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 Word32 *data, /* i : Input audio in interleaved channels layout */ + const Word16 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 Word32 *p_channels[], /* i : Array of pointers to each input channel */ + const Word16 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 Word32 value, /* i : Value to push */ + const Word16 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 */ + Word32 *p_channels[], /* i : Array of pointers to each output channel */ + const Word16 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 Word32 *data, /* i : Input data */ + const Word16 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 Word16 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 */ + Word32 *data, /* i : Output data */ + const Word16 num_samples_per_channel /* i : Number of samples per channel to retrieve*/ +); +#endif + +Word16 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 aec8eb3b9b4cffaf491605d5c2680a71970515dc..7fe2f3af753e6ac21489b0b06fe11c595b46199a 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1433,6 +1433,21 @@ typedef struct } CLDFB_REND_WRAPPER; +/*----------------------------------------------------------------------------------* + * Time domain ring buffer structure + *----------------------------------------------------------------------------------*/ + +typedef struct +{ + Word32 *data; /* samples in interleaved layout, e.g. for channels A, B, C, samples are stored: A1, B1, C1, A2, B2, C2, ... */ + Word32 capacity; /* max number of Word32 values that can be stored */ + Word16 num_channels; + Word32 write_pos; + Word32 read_pos; + Word16 is_full; + +} TD_RINGBUF_DATA, *TD_RINGBUF_HANDLE; + /*----------------------------------------------------------------------------------* * Limiter structure *----------------------------------------------------------------------------------*/ diff --git a/lib_rend/ivas_td_ring_buffer_fx.c b/lib_rend/ivas_td_ring_buffer_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..5866c31adc6b272694b7eefa339ba6030c8b09a8 --- /dev/null +++ b/lib_rend/ivas_td_ring_buffer_fx.c @@ -0,0 +1,457 @@ +/****************************************************************************************************** + + (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 "ivas_error_utils.h" +#include "ivas_prot_rend_fx.h" +#include "options.h" +#include "wmc_auto.h" +#include "prot_fx.h" + + +/*-----------------------------------------------------------------------* + * Local function prototypes + *-----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------* + * ivas_td_ringbuf_total_size() + * + * Returns total number of buffered samples (including number of channels) + *---------------------------------------------------------------------*/ + +static Word32 ivas_td_ringbuf_total_size( + TD_RINGBUF_HANDLE h ) +{ + IF( h->is_full ) + { + return h->capacity; + } + + IF( LE_32( h->read_pos, h->write_pos ) ) + { + return L_sub( h->write_pos, h->read_pos ); + } + /* else wrap around */ + return L_add( h->write_pos, L_sub( h->capacity, h->read_pos ) ); +} + + +static Word16 ivas_td_ringbuf_has_space_for_num_samples( + TD_RINGBUF_HANDLE h, + const Word32 num_samples ) +{ + IF( LE_32( L_add( ivas_td_ringbuf_total_size( h ), num_samples ), h->capacity ) ) + { + return 1; + } + return 0; +} + + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +static void ivas_td_ringbuf_push_interleaved( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + const Word32 *data, /* i : Input audio in interleaved channels layout */ + const Word16 num_samples_per_channel, /* i : Number of samples per channel to push */ + const Word16 read_stride /* i: : 1 for normal operation, 0 for reading from a single input value */ +) +{ + Word32 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, num_samples_per_channel * h->num_channels ) ); + + read_s = 0; + move32(); + FOR( s = 0; s < L_mult0( num_samples_per_channel, h->num_channels ); ++s ) + { + h->data[h->write_pos] = data[read_s]; + move32(); + h->write_pos = L_add( h->write_pos, 1 ); + + if ( EQ_32( h->write_pos, h->capacity ) ) + { + h->write_pos = 0; + move16(); + } + read_s = L_add( read_s, L_deposit_l( read_stride ) ); + move32(); + } + + if ( EQ_32( h->read_pos, h->write_pos ) ) + { + h->is_full = 1; + move16(); + } + + return; +} +#endif + + +/*-----------------------------------------------------------------------* + * Global function definitions + *-----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_Open() + * + * Allocate 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 Word16 capacity_per_channel, /* i : Number of samples stored per channel */ + const Word16 num_channels /* i : Number of channels */ +) +{ + TD_RINGBUF_HANDLE h; + Word32 capacity; + + capacity = L_mult0( capacity_per_channel, num_channels ); + move32(); + + 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; + move32(); + h->num_channels = num_channels; + move16(); + h->write_pos = 0; + move32(); + h->read_pos = 0; + move32(); + h->is_full = 0; + move16(); + *ph = h; + + h->data = malloc( capacity * sizeof( Word32 ) ); + IF( h->data == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for TD ring buffer\n" ); + } + h->capacity = capacity; + move32(); + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_Close() + * + * Dellocate 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() + * + * Push 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 Word32 *data, /* i : Input audio in interleaved channels layout */ + const Word16 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() + * + * Push 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 Word32 *p_channels[], /* i : Array of pointers to each input channel */ + const Word16 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 Word32 *data, /* i : Input data */ + const Word16 num_samples_per_channel /* i : Number of samples per channel to store */ +) +#endif +{ + Word32 s; + Word16 c; + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + assert( h != NULL ); + assert( p_channels != NULL ); + for ( c = 0; c < h->num_channels; ++c ) /* Not using BASOP FOR because this loops only does assertions */ + { + assert( p_channels[c] != NULL ); + } +#endif + assert( ivas_td_ringbuf_has_space_for_num_samples( h, 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]; + move32(); +#else + h->data[h->write_pos] = data[L_mac0( s, c, num_samples_per_channel )]; + move32(); +#endif + h->write_pos = L_add( h->write_pos, 1 ); + + if ( EQ_32( h->write_pos, h->capacity ) ) + { + h->write_pos = 0; + move32(); + } + } + } + + if ( EQ_32( h->read_pos, h->write_pos ) ) + { + h->is_full = 1; + move16(); + } + + return; +} + + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_PushConstant() + * + * Push 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 Word32 value, /* i : Value to push */ + const Word16 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 Word16 num_samples_per_channel /* i : Number of zeros per channel to store */ +) +{ + Word32 s; + Word16 c; + + 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; + move32(); + h->write_pos = L_add( h->write_pos, 1 ); + + IF( EQ_32( h->write_pos, h->capacity ) ) + { + h->write_pos = 0; + move32(); + } + } + } + + if ( EQ_32( h->read_pos, h->write_pos ) ) + { + h->is_full = 1; + move16(); + } + + return; +} +#endif + + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_PopChannels() + * + * Pop 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 */ + Word32 *p_channels[], /* i : Array of pointers to each output channel */ + const Word16 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 */ + Word32 *data, /* i : Output data */ + const Word16 num_samples_per_channel /* i : Number of samples per channel to retrieve */ +) +#endif +{ + Word32 s; + Word16 c; + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + assert( h != NULL ); + assert( p_channels != NULL ); + for ( c = 0; c < h->num_channels; ++c ) /* Not using BASOP FOR because this loops only does assertions */ + { + assert( p_channels[c] != NULL ); + } +#endif + assert( ivas_td_ringbuf_total_size( h ) >= 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]; + move32(); +#else + data[L_mac0( s, c, num_samples_per_channel )] = h->data[h->read_pos]; + move32(); +#endif + ++h->read_pos; + + IF( EQ_32( h->read_pos, h->capacity ) ) + { + h->read_pos = 0; + move32(); + } + } + } + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + IF( NE_16( num_samples_per_channel, 0 ) ) + { + h->is_full = 0; + move16(); + } +#else + IF( h->is_full ) + { + h->is_full = 0; + move16(); + } +#endif + + return; +} + + +/*---------------------------------------------------------------------* + * ivas_TD_RINGBUF_Size() + * + * Returns number of buffered samples per channel. + *---------------------------------------------------------------------*/ + +Word16 ivas_TD_RINGBUF_Size( + const TD_RINGBUF_HANDLE h /* i : Ring buffer handle */ +) +{ + return extract_l( ar_div( ivas_td_ringbuf_total_size( h ), L_deposit_l( h->num_channels ) ) ); +} diff --git a/lib_rend/lib_rend_fx.c b/lib_rend/lib_rend_fx.c index 51127a8b5236c7f52115774d0ab3176337dde47d..3a77187247452d81598b74d96e9f4bf68d7b6194 100644 --- a/lib_rend/lib_rend_fx.c +++ b/lib_rend/lib_rend_fx.c @@ -8952,6 +8952,19 @@ static ivas_error getSamplesInternal( } Word32 *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. */ + Word32 *p_Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX]; + Word32 *p_Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX]; + + FOR( i = 0; i < BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES; ++i ) + { + FOR( j = 0; j < CLDFB_NO_COL_MAX; ++j ) + { + p_Cldfb_RealBuffer_Binaural[i][j] = Cldfb_RealBuffer_Binaural[i][j]; + p_Cldfb_ImagBuffer_Binaural[i][j] = Cldfb_ImagBuffer_Binaural[i][j]; + } + } +#endif FOR( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ ) { @@ -9029,10 +9042,20 @@ static ivas_error getSamplesInternal( Q_out[0] = Q_out[0] + *outAudio.pq_fact; } +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + IF( NE_32( ( error = ISAR_PRE_REND_MultiBinToSplitBinaural( hIvasRend->splitRendWrapper, hIvasRend->headRotData.headPositions[0], hIvasRend->hRendererConfig->split_rend_config.splitRendBitRate, hIvasRend->hRendererConfig->split_rend_config.codec, + hIvasRend->hRendererConfig->split_rend_config.isar_frame_size_ms, + hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms, + &bits, + p_Cldfb_RealBuffer_Binaural, p_Cldfb_ImagBuffer_Binaural, + extract_l( Mpy_32_32( hIvasRend->sampleRateOut, 2684355 /*(BINAURAL_MAXBANDS / 48000) in Q31*/ ) ), tmpBinaural, 1, cldfb_in_flag, extract_l( EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ), ro_md_flag, Q_buff, &Q_out[0] ) ), + IVAS_ERR_OK ) ) +#else IF( ( error = ISAR_PRE_REND_MultiBinToSplitBinaural( hIvasRend->splitRendWrapper, hIvasRend->headRotData.headPositions[0], hIvasRend->hRendererConfig->split_rend_config.splitRendBitRate, hIvasRend->hRendererConfig->split_rend_config.codec, hIvasRend->hRendererConfig->split_rend_config.isar_frame_size_ms, hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms, &bits, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, extract_l( Mpy_32_32( hIvasRend->sampleRateOut, 2684355 /*(BINAURAL_MAXBANDS / 48000) in Q31*/ ) ), tmpBinaural, 1, cldfb_in_flag, ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0, ro_md_flag, Q_buff, &Q_out[0] ) ) != IVAS_ERR_OK ) +#endif { return error; }