diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a5f33f3c6f2a01b33e5dabfb61506c855534915a..5d4cdd72f2fa6cf8551963949faa0abdae9a190d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -315,7 +315,7 @@ codec-smoke-test: extends: - .test-job-linux-needs-testv-dir - .rules-merge-request - timeout: "5 minutes" + timeout: "10 minutes" stage: test needs: ["build-codec-linux-cmake"] script: diff --git a/Workspace_msvc/lib_com.vcxproj b/Workspace_msvc/lib_com.vcxproj index 23aa2ae3f0b6722871f7f9d2c37b27e41f46862f..bfe36b1f4812b8e44a7cb32fca8793c1b443c962 100644 --- a/Workspace_msvc/lib_com.vcxproj +++ b/Workspace_msvc/lib_com.vcxproj @@ -78,7 +78,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_util;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) EnableFastChecks diff --git a/Workspace_msvc/lib_debug.vcxproj b/Workspace_msvc/lib_debug.vcxproj index 3b648fae048920ae06aa709785d4b49d2e58d710..9b7b5806615c336f40e3f5850ded7b2c2d4103ec 100644 --- a/Workspace_msvc/lib_debug.vcxproj +++ b/Workspace_msvc/lib_debug.vcxproj @@ -73,7 +73,7 @@ Disabled - ..\lib_com;..\lib_debug;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_util;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) false diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj index 2473e1bc5007f0bbf244d35611445a10c1248edc..760621d7a40ce2113110aed02262c1d0f8f40ff9 100644 --- a/Workspace_msvc/lib_dec.vcxproj +++ b/Workspace_msvc/lib_dec.vcxproj @@ -89,7 +89,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;..\lib_rend;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) EnableFastChecks @@ -282,6 +282,7 @@ + diff --git a/Workspace_msvc/lib_dec.vcxproj.filters b/Workspace_msvc/lib_dec.vcxproj.filters index 0bd4a23fbfa389f044414d87b439fd0f2ab12e38..6284884920f332ea486df52e269e1eb51e5ef8f3 100644 --- a/Workspace_msvc/lib_dec.vcxproj.filters +++ b/Workspace_msvc/lib_dec.vcxproj.filters @@ -521,6 +521,9 @@ dec_ivas_c + + dec_ivas_c + diff --git a/Workspace_msvc/lib_enc.vcxproj b/Workspace_msvc/lib_enc.vcxproj index 3378ac10f0ccb8b95616f87f6d225f38af30bb3d..d9f8e974f0a9fbb885386ff137db1a0b8ef49c0c 100644 --- a/Workspace_msvc/lib_enc.vcxproj +++ b/Workspace_msvc/lib_enc.vcxproj @@ -89,7 +89,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_util;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) EnableFastChecks diff --git a/Workspace_msvc/lib_rend.vcxproj b/Workspace_msvc/lib_rend.vcxproj index 865652649a8a320ff0769bd83170528445da8ab3..4bd0ca9a93af1b4580271f339f0670bdc1a26bac 100644 --- a/Workspace_msvc/lib_rend.vcxproj +++ b/Workspace_msvc/lib_rend.vcxproj @@ -89,7 +89,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) EnableFastChecks diff --git a/Workspace_msvc/lib_util.vcxproj b/Workspace_msvc/lib_util.vcxproj index 5b5e5f30ccdc3697e60b72e2b74750fe06e90598..72ff2dfe6182abfbe7d1a6783c324a3958d398a6 100644 --- a/Workspace_msvc/lib_util.vcxproj +++ b/Workspace_msvc/lib_util.vcxproj @@ -158,6 +158,7 @@ + @@ -183,6 +184,7 @@ + diff --git a/apps/decoder.c b/apps/decoder.c index 9a4a80312dd4914738e4298a24afb4fb0bd7c7a8..9b6b85676508d94c60b728bf651da78c8332a555 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -45,6 +45,9 @@ #include "vector3_pair_file_reader.h" #include "jbm_file_writer.h" #include "evs_rtp_payload.h" +#ifdef VARIABLE_SPEED_DECODING +#include "tsm_scale_file_reader.h" +#endif #ifdef DEBUGGING #include "debug.h" #endif @@ -76,6 +79,14 @@ static #define IVAS_PUBLIC_ORIENT_TRK_REF_VEC ( 3 ) #define IVAS_PUBLIC_ORIENT_TRK_REF_VEC_LEV ( 4 ) +#ifdef VARIABLE_SPEED_DECODING +#define VARIABLE_SPEED_FETCH_FRAMESIZE_MS 20 +#endif +#ifdef JBM_TSM_ON_TCS +#define JBM_FRONTEND_FETCH_FRAMESIZE_MS 20 +#define FRAME_SIZE_NS 20000000L +#endif + typedef struct { char *inputBitstreamFilename; @@ -124,6 +135,20 @@ typedef struct FILE *agcBitstream; /* temporary */ #endif +#endif +#ifdef DEBUG_JBM_CMD_OPTION + bool noBadFrameDelay; +#endif +#ifdef VARIABLE_SPEED_DECODING + bool variableSpeedMode; + bool tsmScaleFileEnabled; + char *tsmScaleFileName; + uint16_t tsmScale; +#endif +#ifdef JBM_TSM_ON_TCS +#ifdef DEBUG_JBM_CMD_OPTION + uint16_t frontendFetchSizeMs; +#endif #endif } DecArguments; @@ -137,6 +162,9 @@ 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, HeadRotFileReader *headRotReader, HeadRotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); static ivas_error decodeVoIP( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HANDLE hIvasDec ); +#ifdef VARIABLE_SPEED_DECODING +static ivas_error decodeVariableSpeed( DecArguments arg, BS_READER_HANDLE hBsReader, HeadRotFileReader *headRotReader, HeadRotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, IVAS_DEC_HANDLE hIvasDec ); +#endif #ifdef DEBUGGING static ivas_error printBitstreamInfoVoip( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HANDLE hIvasDec ); static int16_t app_own_random( int16_t *seed ); @@ -571,8 +599,15 @@ int main( if ( arg.voipMode ) { - +#ifdef JBM_TSM_ON_TCS + if ( ( error = IVAS_DEC_EnableVoIP( hIvasDec, IVAS_DEC_VOIP_MODE_VOIP, 100, 60, arg.inputFormat ) ) != IVAS_ERR_OK ) +#else +#ifdef VARIABLE_SPEED_DECODING + if ( ( error = IVAS_DEC_EnableVoIP( hIvasDec, IVAS_DEC_VOIP_MODE_VOIP, 100, 60, arg.inputFormat ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_DEC_EnableVoIP( hIvasDec, 60, arg.inputFormat ) ) != IVAS_ERR_OK ) +#endif +#endif { fprintf( stderr, "\nCould not enable VOIP: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -580,6 +615,17 @@ int main( error = decodeVoIP( arg, hBsReader, hIvasDec ); } +#ifdef VARIABLE_SPEED_DECODING + else if ( arg.variableSpeedMode ) + { + if ( ( error = IVAS_DEC_EnableVoIP( hIvasDec, IVAS_DEC_VOIP_MODE_VARIABLE_SPEED, arg.tsmScale, 60, arg.inputFormat ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nCould not enable Variable Play Speed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + error = decodeVariableSpeed( arg, hBsReader, headRotReader, refRotReader, referenceVectorReader, hIvasDec ); + } +#endif else { error = decodeG192( arg, hBsReader, headRotReader, refRotReader, referenceVectorReader, hIvasDec, pcmBuf ); @@ -812,6 +858,20 @@ static bool parseCmdlIVAS_dec( #else arg->no_diegetic_pan = 0.f; #endif +#ifdef VARIABLE_SPEED_DECODING + arg->variableSpeedMode = 0; + arg->tsmScale = 100; + arg->tsmScaleFileEnabled = false; + arg->tsmScaleFileName = NULL; +#endif +#ifdef JBM_TSM_ON_TCS +#ifdef DEBUG_JBM_CMD_OPTION + arg->frontendFetchSizeMs = JBM_FRONTEND_FETCH_FRAMESIZE_MS; +#endif +#endif +#ifdef DEBUG_JBM_CMD_OPTION + arg->noBadFrameDelay = false; +#endif /*-----------------------------------------------------------------* * Initialization @@ -938,6 +998,62 @@ static bool parseCmdlIVAS_dec( #endif /* #ifdef DEBUG_MODE_INFO_TWEAK */ #endif /* #ifdef DEBUG_MODE_INFO */ #endif /* #ifdef DEBUGGING */ +#ifdef DEBUG_JBM_CMD_OPTION + else if ( strcmp( argv_to_upper, "-VOIP_NO_BAD_FRAME" ) == 0 ) + { + arg->noBadFrameDelay = true; + i++; + } +#endif +#ifdef VARIABLE_SPEED_DECODING + + else if ( strcmp( argv_to_upper, "-VS" ) == 0 ) + { + i++; + int tmp = 100; + arg->variableSpeedMode = true; + if ( i < argc - 3 ) + { + if ( !is_digits_only( argv[i] ) ) + { + arg->tsmScaleFileEnabled = true; + arg->tsmScaleFileName = argv[i]; + i++; + } + + else + { + if ( ( sscanf( argv[i], "%d", &tmp ) > 0 ) ) + { + i++; + } + } + arg->tsmScale = (uint16_t) tmp; + } + } +#endif +#ifdef JBM_TSM_ON_TCS +#ifdef DEBUG_JBM_CMD_OPTION + else if ( strcmp( argv_to_upper, "-VOIP_FRAMESIZE" ) == 0 ) + { + i++; + int tmp; + if ( i < argc - 3 ) + { + if ( !is_digits_only( argv[i] ) ) + { + return false; + } + + if ( sscanf( argv[i], "%d", &tmp ) > 0 ) + { + i++; + } + arg->frontendFetchSizeMs = (uint16_t) tmp; + } + } +#endif +#endif else if ( strcmp( argv_to_upper, "-MIME" ) == 0 ) { @@ -1246,6 +1362,18 @@ static void usage_dec( void ) fprintf( stdout, "-VOIP : VoIP mode: RTP in G192\n" ); fprintf( stdout, "-VOIP_hf_only=0 : VoIP mode: EVS RTP Payload Format hf_only=0 in rtpdump\n" ); fprintf( stdout, "-VOIP_hf_only=1 : VoIP mode: EVS RTP Payload Format hf_only=1 in rtpdump\n" ); +#ifdef DEBUG_JBM_CMD_OPTION + fprintf( stdout, "-VOIP_no_bad_frame : VoIP mode: do not put out bad frames in the beginning as silence \n" ); +#endif +#ifdef VARIABLE_SPEED_DECODING + fprintf( stdout, "-VS fac : Varaible Speed mode: change speed of playout fac as integer in percent. fac<100 faster, fac>100 slower\n" ); +#endif +#ifdef JBM_TSM_ON_TCS +#ifdef DEBUG_JBM_CMD_OPTION + fprintf( stdout, "-VOIP_framesize : VoIP mode: acoustic frontend fetch frame size (must be multiples of 5!)\n" ); +#endif + +#endif fprintf( stdout, " The decoder may read rtpdump files containing TS26.445 Annex A.2.2\n" ); fprintf( stdout, " EVS RTP Payload Format. The SDP parameter hf_only is required.\n" ); fprintf( stdout, " Reading RFC4867 AMR/AMR-WB RTP payload format is not supported.\n" ); @@ -1937,8 +2065,13 @@ static ivas_error decodeVoIP( uint32_t nextPacketRcvTime_ms = 0; uint32_t systemTime_ms = 0; +#ifdef JBM_TSM_ON_TCS + uint32_t systemTimeInc_ms = (uint32_t) JBM_FRONTEND_FETCH_FRAMESIZE_MS; + int32_t nFramesWritten = 0; +#endif int32_t nFramesFed = 0; + uint8_t au[( IVAS_MAX_BITS_PER_FRAME + 7 ) >> 3]; int16_t auSize; uint16_t rtpSequenceNumber; @@ -2071,10 +2204,27 @@ static ivas_error decodeVoIP( * Main receiving/decoding loop *------------------------------------------------------------------------------------------*/ +#ifdef JBM_TSM_ON_TCS +#ifdef DEBUG_JBM_CMD_OPTION + systemTimeInc_ms = arg.frontendFetchSizeMs; +#endif +#endif + while ( 1 ) { int16_t nOutSamples = 0; - +#if defined( JBM_TSM_ON_TCS ) || defined( VARIABLE_SPEED_DECODING ) + uint16_t nSamplesAvailableNext = 0; +#endif +#ifdef JBM_TSM_ON_TCS +#ifdef DEBUG_JBM_CMD_OPTION + nOutSamples = (int16_t) ( arg.output_Fs / 1000 * arg.frontendFetchSizeMs ); +#else + nOutSamples = (int16_t) ( arg.output_Fs / 1000 * JBM_FRONTEND_FETCH_FRAMESIZE_MS ); +#endif +#else + nOutSamples = (int16_t) ( arg.output_Fs / 50 ); +#endif /* read all packets with a receive time smaller than the system time */ while ( nextPacketRcvTime_ms <= systemTime_ms ) { @@ -2118,15 +2268,24 @@ static ivas_error decodeVoIP( /* we are finished when all packets have been received and jitter buffer is empty */ /* also stop when the input file contains less than two frames, because JBM cannot calculate a delay value and won't start decoding */ +#ifdef JBM_TSM_ON_TCS + /* last clause should make sure that for BE tests we end up with the same number of samples...*/ + if ( nextPacketRcvTime_ms == (uint32_t) ( -1 ) && ( IVAS_DEC_VoIP_IsEmpty( hIvasDec, nOutSamples ) || nFramesFed < 2 ) ) +#else if ( nextPacketRcvTime_ms == (uint32_t) ( -1 ) && ( IVAS_DEC_VoIP_IsEmpty( hIvasDec ) || nFramesFed < 2 ) ) +#endif { break; } - nOutSamples = (int16_t) ( arg.output_Fs / 50 ); /* decode and get samples */ - if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, pcmBuf, systemTime_ms + if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, + pcmBuf, systemTime_ms +#if defined( JBM_TSM_ON_TCS ) || defined( VARIABLE_SPEED_DECODING ) + , + &nSamplesAvailableNext +#endif #ifdef SUPPORT_JBM_TRACEFILE , writeJbmTraceFileFrameWrapper, @@ -2188,7 +2347,11 @@ static ivas_error decodeVoIP( goto cleanup; } } +#ifdef DEBUG_JBM_CMD_OPTION + else if ( arg.noBadFrameDelay == false ) +#else else +#endif { ++numInitialBadFrames; } @@ -2211,6 +2374,55 @@ static ivas_error decodeVoIP( { delayNumSamples -= nOutSamples; } + +#ifdef JBM_TSM_ON_TCS + /* Write ISM metadata to external file(s) */ + if ( decodedGoodFrame && arg.outputFormat == IVAS_DEC_OUTPUT_EXT ) + { + int16_t i; + + if ( bsFormat == IVAS_DEC_BS_OBJ ) + { + if ( ( error = IVAS_DEC_GetNumObjects( hIvasDec, &numObj ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetNumObjects: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + for ( i = 0; i < numObj; ++i ) + { + IVAS_ISM_METADATA IsmMetadata; + + if ( ( error = IVAS_DEC_GetObjectMetadata( hIvasDec, &IsmMetadata, 0, i ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetObjectMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + if ( ( IsmFileWriter_writeFrame( IsmMetadata, ismWriters[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing ISM metadata to file %s\n", IsmFileWriter_getFilePath( ismWriters[i] ) ); + goto cleanup; + } + } + } + else if ( bsFormat == IVAS_DEC_BS_MASA ) + { + MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta; + if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &hMasaExtOutMeta ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetMasaMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + if ( ( error = MasaFileWriter_writeFrame( masaWriter, hMasaExtOutMeta ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( masaWriter ) ); + goto cleanup; + } + } + } +#endif } if ( !arg.quietModeEnabled ) @@ -2219,7 +2431,12 @@ static ivas_error decodeVoIP( } frame++; +#ifdef JBM_TSM_ON_TCS + systemTime_ms += systemTimeInc_ms; + nFramesWritten++; +#else systemTime_ms += 20; +#endif #ifdef WMOPS update_mem(); @@ -2277,6 +2494,547 @@ cleanup: } +#ifdef VARIABLE_SPEED_DECODING +/*---------------------------------------------------------------------* + * decodeVariableSpeed() + * + * Read G.192 or decode with variable Speed + *---------------------------------------------------------------------*/ + +static ivas_error decodeVariableSpeed( + DecArguments arg, + BS_READER_HANDLE hBsReader, + HeadRotFileReader *headRotReader, + HeadRotFileReader *refRotReader, + Vector3PairFileReader *referenceVectorReader, + IVAS_DEC_HANDLE hIvasDec ) + +{ + bool decodingFailed = true; /* Assume failure until cleanup is reached without errors */ + uint16_t bit_stream[IVAS_MAX_BITS_PER_FRAME + 4 * 8]; + int16_t i, num_bits; + int16_t bfi = 0; +#ifdef DEBUGGING + int16_t fec_seed = 12558; /* FEC_SEED */ +#endif + AudioFileWriter *afWriter = NULL; + MasaFileWriter *masaWriter = NULL; + bool decodedGoodFrame = false; + int16_t numInitialBadFrames = 0; /* Number of bad frames received until first good frame is decoded */ + int16_t nOutChannels = 0; + int16_t delayNumSamples = -1; + int16_t delayNumSamples_orig[3]; + int16_t nOutSamples = 0; + int32_t delayTimeScale = 0; + ivas_error error = IVAS_ERR_UNKNOWN; + uint16_t numObj = 0; + IVAS_DEC_BS_FORMAT bsFormat = IVAS_DEC_BS_UNKOWN; + uint16_t nSamplesAvailableNext; + int16_t pcmBuf[MAX_OUTPUT_PCM_BUFFER_SIZE]; +#ifdef SUPPORT_JBM_TRACEFILE + JbmTraceFileWriter *jbmTraceWriter = NULL; +#endif + TsmScaleFileReader *tsmScaleFileReader = NULL; + IsmFileWriter *ismWriters[IVAS_MAX_NUM_OBJECTS]; + IVAS_VECTOR3 Pos[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; + int16_t scale; + for ( i = 0; i < IVAS_MAX_NUM_OBJECTS; ++i ) + { + ismWriters[i] = NULL; + } + + /*------------------------------------------------------------------------------------------* + * Open TSM scale file + *------------------------------------------------------------------------------------------*/ + + if ( arg.tsmScaleFileEnabled ) + { + if ( ( tsmScaleFileReader = TsmScaleFileReader_open( arg.tsmScaleFileName ) ) == NULL ) + { + fprintf( stderr, "\nError: Can't open TSM scale file %s \n\n", arg.tsmScaleFileName ); + goto cleanup; + } + } + + if ( !arg.quietModeEnabled ) + { + fprintf( stdout, "\n------ Running the decoder ------\n\n" ); + fprintf( stdout, "Frames processed: " ); + } + else + { + fprintf( stdout, "\n-- Start the decoder (quiet mode) --\n\n" ); + } + + delayNumSamples_orig[0] = -1; + +#ifdef WMOPS + reset_stack(); + reset_wmops(); +#endif + nSamplesAvailableNext = 0; + nOutSamples = (int16_t) ( arg.output_Fs / 1000 * VARIABLE_SPEED_FETCH_FRAMESIZE_MS ); + /*------------------------------------------------------------------------------------------* + * Loop for every packet (frame) of bitstream data + * - Read the bitstream packet + * - Run the decoder + * - Write the synthesized signal into output file + *------------------------------------------------------------------------------------------*/ + + while ( 1 ) + { + /* Read next frame if not enough samples availble */ + + /* reference vector */ + if ( arg.enableReferenceVectorTracking ) + { + IVAS_VECTOR3 listenerPosition, referencePosition; + if ( ( error = Vector3PairFileReader_read( referenceVectorReader, &listenerPosition, &referencePosition ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError %s while reading listener and reference positions from %s\n", IVAS_DEC_GetErrorMessage( error ), Vector3PairFileReader_getFilePath( referenceVectorReader ) ); + goto cleanup; + } + + if ( ( error = IVAS_DEC_FeedRefVectorData( hIvasDec, listenerPosition, referencePosition ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_FeedRefVectorData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + } + /* Reference rotation */ + if ( arg.enableReferenceRotation ) + { + IVAS_QUATERNION quaternion; + if ( ( error = HeadRotationFileReading( refRotReader, &quaternion, NULL ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError %s while reading reference rotation from %s\n", IVAS_DEC_GetErrorMessage( error ), HeadRotationFileReader_getFilePath( refRotReader ) ); + goto cleanup; + } + + if ( ( error = IVAS_DEC_FeedRefRotData( hIvasDec, quaternion ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_FeedRefRotData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + } + /* Head-tracking input simulation */ + if ( arg.enableHeadRotation ) + { + IVAS_QUATERNION Quaternions[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; + + for ( i = 0; i < IVAS_MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + if ( ( error = HeadRotationFileReading( headRotReader, &Quaternions[i], &Pos[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ), HeadRotationFileReader_getFilePath( headRotReader ) ); + goto cleanup; + } + } + + if ( ( error = IVAS_DEC_FeedHeadTrackData( hIvasDec, Quaternions, Pos ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_FeedHeadTrackData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + } + + /* decode and get samples */ + do + { + error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, + pcmBuf, 0, + &nSamplesAvailableNext +#ifdef SUPPORT_JBM_TRACEFILE + , + writeJbmTraceFileFrameWrapper, + jbmTraceWriter +#endif + ); + if ( error != IVAS_ERR_OK && error != IVAS_ERR_VS_FRAME_NEEDED ) + + { + fprintf( stderr, "\nError in IVAS_DEC_VoIP_GetSamples: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + if ( error == IVAS_ERR_VS_FRAME_NEEDED ) + { + if ( arg.tsmScaleFileEnabled ) + { + if ( ( error = TsmScaleFileReader_readScale( tsmScaleFileReader, &scale ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: input bitstream file couldn't be read: %s \n\n", arg.inputBitstreamFilename ); + goto cleanup; + } + IVAS_DEC_VoIP_SetScale( hIvasDec, scale ); + } + + if ( ( error = BS_Reader_ReadFrame_short( hBsReader, bit_stream, &num_bits, &bfi ) ) != IVAS_ERR_OK ) + { + if ( error == IVAS_ERR_END_OF_FILE ) + { + break; + } + fprintf( stderr, "\nError: input bitstream file couldn't be read: %s \n\n", arg.inputBitstreamFilename ); + goto cleanup; + } + +#ifdef DEBUGGING + /* Random FEC simulation */ + if ( arg.FER > 0.0f ) + { + float ftmp = (float) app_own_random( &fec_seed ) + 32768.0f; + if ( ftmp <= arg.FER / 100.0f * 65535.0f ) + { + bfi = 1; + } + else + { + bfi = 0; + } + } +#endif + + /* Feed into decoder */ + if ( ( error = IVAS_DEC_FeedFrame_Serial( hIvasDec, bit_stream, num_bits, bfi ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: could not feed frame to decoder: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + error = IVAS_ERR_VS_FRAME_NEEDED; + } + } while ( error != IVAS_ERR_OK ); + + if ( error == IVAS_ERR_END_OF_FILE ) + { + break; + } + + /* Continue checking for first good frame until it is found */ + if ( !decodedGoodFrame ) + { + if ( ( error = IVAS_DEC_HasDecodedFirstGoodFrame( hIvasDec, &decodedGoodFrame ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_HasDecodedFirstGoodFrame, code: %d\n", error ); + goto cleanup; + } + + /* Once good frame decoded, catch up */ + if ( decodedGoodFrame ) + { + error = initOnFirstGoodFrame( + hIvasDec, + arg, + numInitialBadFrames, + nOutSamples, + delayNumSamples_orig, + &delayNumSamples, + &delayTimeScale, + &bsFormat, + &afWriter, + &masaWriter, + ismWriters, + &nOutChannels, + &numObj ); + if ( error != IVAS_ERR_OK ) + { + goto cleanup; + } + } + else + { + ++numInitialBadFrames; + } + } + + + /* Write current frame */ + if ( decodedGoodFrame ) + { + 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; + } + } + + /* Write ISm metadata to external file(s) */ + if ( decodedGoodFrame && arg.outputFormat == IVAS_DEC_OUTPUT_EXT ) + { + if ( bsFormat == IVAS_DEC_BS_OBJ ) + { + if ( ( error = IVAS_DEC_GetNumObjects( hIvasDec, &numObj ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetNumObjects: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + for ( i = 0; i < numObj; ++i ) + { + IVAS_ISM_METADATA IsmMetadata; + + if ( ( error = IVAS_DEC_GetObjectMetadata( hIvasDec, &IsmMetadata, 0, i ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetObjectMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + if ( ( IsmFileWriter_writeFrame( IsmMetadata, ismWriters[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing ISM metadata to file %s\n", IsmFileWriter_getFilePath( ismWriters[i] ) ); + goto cleanup; + } + } + } + else if ( bsFormat == IVAS_DEC_BS_MASA ) + { + MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta; + if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &hMasaExtOutMeta ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetMasaMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + if ( ( error = MasaFileWriter_writeFrame( masaWriter, hMasaExtOutMeta ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( masaWriter ) ); + goto cleanup; + } + } + } + + frame++; + if ( !arg.quietModeEnabled ) + { + fprintf( stdout, "%-8d\b\b\b\b\b\b\b\b", frame ); +#ifdef DEBUGGING + if ( IVAS_DEC_GetBerDetectFlag( hIvasDec ) ) + { + fprintf( stdout, "\n Decoding error: BER detected in frame %d !!!!!\n", frame - 1 ); + } +#endif + } +#ifdef WMOPS + update_wmops(); +#ifdef MEM_COUNT_DETAILS + export_mem( "mem_analysis.csv" ); +#endif +#endif + } + + + /*------------------------------------------------------------------------------------------* + * Flush what is still left in the VoIP Buffers.... + *------------------------------------------------------------------------------------------*/ + while ( nSamplesAvailableNext > 0 ) + { + int16_t nSamplesFlushed; + + /* Feed into decoder */ + + /* reference vector */ + if ( arg.enableReferenceVectorTracking ) + { + IVAS_VECTOR3 listenerPosition, referencePosition; + if ( ( error = Vector3PairFileReader_read( referenceVectorReader, &listenerPosition, &referencePosition ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError %s while reading listener and reference positions from %s\n", IVAS_DEC_GetErrorMessage( error ), Vector3PairFileReader_getFilePath( referenceVectorReader ) ); + goto cleanup; + } + + if ( ( error = IVAS_DEC_FeedRefVectorData( hIvasDec, listenerPosition, referencePosition ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_FeedRefVectorData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + } + /* Reference rotation */ + if ( arg.enableReferenceRotation ) + { + IVAS_QUATERNION quaternion; + if ( ( error = HeadRotationFileReading( refRotReader, &quaternion, NULL ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError %s while reading reference rotation from %s\n", IVAS_DEC_GetErrorMessage( error ), HeadRotationFileReader_getFilePath( refRotReader ) ); + goto cleanup; + } + + if ( ( error = IVAS_DEC_FeedRefRotData( hIvasDec, quaternion ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_FeedRefRotData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + } + /* Head-tracking input simulation */ + if ( arg.enableHeadRotation ) + { + IVAS_QUATERNION Quaternions[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; + + for ( i = 0; i < IVAS_MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + if ( ( error = HeadRotationFileReading( headRotReader, &Quaternions[i], &Pos[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ), HeadRotationFileReader_getFilePath( headRotReader ) ); + goto cleanup; + } + } + + if ( ( error = IVAS_DEC_FeedHeadTrackData( hIvasDec, Quaternions, Pos ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_FeedHeadTrackData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + } + + /* decode and get samples */ + if ( ( error = IVAS_DEC_VoIP_Flush( hIvasDec, nOutSamples, + pcmBuf, + &nSamplesAvailableNext, + &nSamplesFlushed ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_VoIP_Flush: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + + /* Write current frame */ + + if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, nSamplesFlushed * nOutChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nOutput audio file writer error\n" ); + goto cleanup; + } + + + /* Write ISm metadata to external file(s) */ + if ( decodedGoodFrame && arg.outputFormat == IVAS_DEC_OUTPUT_EXT ) + { + if ( bsFormat == IVAS_DEC_BS_OBJ ) + { + if ( ( error = IVAS_DEC_GetNumObjects( hIvasDec, &numObj ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetNumObjects: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + for ( i = 0; i < numObj; ++i ) + { + IVAS_ISM_METADATA IsmMetadata; + + if ( ( error = IVAS_DEC_GetObjectMetadata( hIvasDec, &IsmMetadata, 0, i ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetObjectMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + if ( ( IsmFileWriter_writeFrame( IsmMetadata, ismWriters[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing ISM metadata to file %s\n", IsmFileWriter_getFilePath( ismWriters[i] ) ); + goto cleanup; + } + } + } + else if ( bsFormat == IVAS_DEC_BS_MASA ) + { + MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta; + if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &hMasaExtOutMeta ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetMasaMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + if ( ( error = MasaFileWriter_writeFrame( masaWriter, hMasaExtOutMeta ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( masaWriter ) ); + goto cleanup; + } + } + } + + frame++; + if ( !arg.quietModeEnabled ) + { + fprintf( stdout, "%-8d\b\b\b\b\b\b\b\b", frame ); +#ifdef DEBUGGING + if ( IVAS_DEC_GetBerDetectFlag( hIvasDec ) ) + { + fprintf( stdout, "\n Decoding error: BER detected in frame %d !!!!!\n", frame - 1 ); + } +#endif + } + } + /*------------------------------------------------------------------------------------------* + * Printouts after decoding has finished + *------------------------------------------------------------------------------------------*/ + + if ( !arg.quietModeEnabled ) + { + printf( "\n\nDecoder+renderer delay: %4.2f ms (%3u samples at timescale %5u)\n", 1000.f * delayNumSamples_orig[1] / (float) delayTimeScale, delayNumSamples_orig[1], delayTimeScale ); + + if ( delayNumSamples_orig[2] > 0 ) + { + printf( "HRIR/BRIR delay: %4.2f ms (%3u samples at timescale %5u)\n", 1000.f * delayNumSamples_orig[2] / (float) delayTimeScale, delayNumSamples_orig[2], delayTimeScale ); + printf( "Total delay: %4.2f ms (%3u samples at timescale %5u)\n", 1000.f * ( delayNumSamples_orig[1] + delayNumSamples_orig[2] ) / (float) delayTimeScale, delayNumSamples_orig[1] + delayNumSamples_orig[2], delayTimeScale ); + } + } + + /* Print output metadata file name(s) */ + if ( arg.outputFormat == IVAS_DEC_OUTPUT_EXT ) + { + if ( bsFormat == IVAS_DEC_BS_OBJ ) + { + for ( i = 0; i < numObj; i++ ) + { + fprintf( stdout, "\nOutput metadata file: %s", IsmFileWriter_getFilePath( ismWriters[i] ) ); + } + fprintf( stdout, "\n" ); + } + else if ( bsFormat == IVAS_DEC_BS_MASA ) + { + fprintf( stdout, "\nOutput metadata file: %s\n", MasaFileWriter_getFilePath( masaWriter ) ); + } + } + + /* add zeros at the end to have equal length of synthesized signals */ + memset( pcmBuf, 0, delayNumSamples_orig[0] * nOutChannels * sizeof( int16_t ) ); + 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; + } + + /*------------------------------------------------------------------------------------------* + * Close files and deallocate resources + *------------------------------------------------------------------------------------------*/ + + decodingFailed = false; /* This will stay set to true if cleanup is reached via a goto due to an error */ + +cleanup: + + AudioFileWriter_close( &afWriter ); + MasaFileWriter_close( &masaWriter ); + TsmScaleFileReader_close( &tsmScaleFileReader ); + for ( i = 0; i < IVAS_MAX_NUM_OBJECTS; i++ ) + { + IsmFileWriter_close( &ismWriters[i] ); + } + + if ( decodingFailed && error == IVAS_ERR_OK ) + { + return IVAS_ERR_UNKNOWN; + } + + return error; +} + +#endif + #ifdef DEBUGGING /*---------------------------------------------------------------------* * parseForcedRendModeDec() diff --git a/ci/smoke_test.sh b/ci/smoke_test.sh index d3206fce1a42943d5e01ff796c66ca02d2a455df..b1b9e024b46711fc7b8ced20dfb3d1f1b19b3144 100755 --- a/ci/smoke_test.sh +++ b/ci/smoke_test.sh @@ -78,28 +78,37 @@ fi # treat ISM modes separately because passing the metadata files to MASA modes causes crashes ism_modes=$(./scripts/runIvasCodec.py -l | grep ISM) non_ism_modes=$(./scripts/runIvasCodec.py -l | grep -v ISM) +echo "\n======================= 1. non-ism modes no FEC =======================\n\n" ./scripts/runIvasCodec.py -m $non_ism_modes -p $cfg -U 1 $WORKERS | tee smoke_test_output.txt +echo "\n======================= 2. ism modes no FEC =======================\n\n" ./scripts/runIvasCodec.py -m $ism_modes -p $cfg -U 1 $WORKERS $ism_md_cmd | tee smoke_test_output.txt # run the decoding again, but with 15% frame loss +echo "\n======================= 3. all modes with FEC =======================\n\n" ./scripts/runIvasCodec.py -p $cfg -U 1 $WORKERS -D="-fec 15" --decoder_only | tee smoke_test_output_plc.txt # run JBM modes - EXT is excluded as not supported yet modes_with_no_ext_out=$(./scripts/runIvasCodec.py -l | grep -v MASA | grep -v ISM) +modes_with_ext_out=$(./scripts/runIvasCodec.py -l | grep 'MASA\|ISM' | grep -v ISM+) +echo "\n======================= 4. JBM, modes with no EXT =======================\n\n" ./scripts/runIvasCodec.py -m $modes_with_no_ext_out -p $cfg -U 1 $WORKERS --decoder_only --jbm_file $dly_profile | tee smoke_test_output_jbm_noEXT.txt -./scripts/runIvasCodec.py -C MASA ISM1 ISM2 ISM3 ISM4 -p $cfg -U 1 $WORKERS --decoder_only --jbm_file $dly_profile --oc BINAURAL BINAURAL_ROOM mono stereo FOA HOA3 5_1 7_1_4 | tee -a smoke_test_output_jbm_noEXT.txt +echo "\n======================= 5. JBM, modes with EXT =======================\n\n" +./scripts/runIvasCodec.py -m $modes_with_ext_out -p $cfg -U 1 $WORKERS --decoder_only --jbm_file $dly_profile --oc BINAURAL BINAURAL_ROOM mono stereo FOA HOA3 5_1 7_1_4 | tee -a smoke_test_output_jbm_noEXT.txt # run all modes with binaural output using external files modes_with_bin_out="SBA PlanarSBA MASA MC ISM1 ISM2 ISM3 ISM4" bin_out_modes="BINAURAL BINAURAL_ROOM" +echo "\n======================= 6. binaural out with HRTF files - WB =======================\n\n" wb_modes=$(./scripts/runIvasCodec.py -l -C $modes_with_bin_out | grep _wb_) hrtf_wb="../scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_16kHz.bin" ./scripts/runIvasCodec.py -p $cfg -m $wb_modes -U 1 $WORKERS -D="-hrtf ${hrtf_wb}" --decoder_only --oc $bin_out_modes | tee -a smoke_test_output_hrtf.txt +echo "\n======================= 7. binaural out with HRTF files - SWB =======================\n\n" swb_modes=$(./scripts/runIvasCodec.py -l -C $modes_with_bin_out | grep _swb_) hrtf_swb="../scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_32kHz.bin" ./scripts/runIvasCodec.py -p $cfg -m $swb_modes -U 1 $WORKERS -D="-hrtf ${hrtf_swb}" --decoder_only --oc $bin_out_modes | tee -a smoke_test_output_hrtf.txt +echo "\n======================= 8. binaural out with HRTF files - FB =======================\n\n" fb_modes=$(./scripts/runIvasCodec.py -l -C $modes_with_bin_out | grep _fb_) hrtf_fb="../scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_48kHz.bin" ./scripts/runIvasCodec.py -p $cfg -m $fb_modes -U 1 $WORKERS -D="-hrtf ${hrtf_fb}" --decoder_only --oc $bin_out_modes | tee -a smoke_test_output_hrtf.txt diff --git a/lib_com/fd_cng_com.c b/lib_com/fd_cng_com.c index f2dbf746b6f18d5e6b9fc07aaa570384733702be..99ae9894f44a26c5b29d70b3cb5e8bc4497f39ce 100644 --- a/lib_com/fd_cng_com.c +++ b/lib_com/fd_cng_com.c @@ -940,6 +940,74 @@ void SynthesisSTFT( return; } +#ifdef JBM_TSM_ON_TCS +/*------------------------------------------------------------------- + * SynthesisSTFT_dirac() + * + * STFT synthesis filterbank + *-------------------------------------------------------------------*/ + +void SynthesisSTFT_dirac( + float *fftBuffer, /* i : FFT bins */ + float *timeDomainOutput, + float *olapBuffer, + const float *olapWin, + const int16_t samples_out, + HANDLE_FD_CNG_COM hFdCngCom /* i/o: FD_CNG structure containing all buffers and variables */ +) +{ + int16_t i; + float buf[M + 1 + 320], tmp; + + /* Perform IFFT */ + RFFTN( fftBuffer, hFdCngCom->fftSineTab, hFdCngCom->fftlen, 1 ); + + /* Handle overlap in P/S domain for stereo */ + mvr2r( olapBuffer + hFdCngCom->frameSize, olapBuffer, hFdCngCom->frameSize ); + set_f( olapBuffer + hFdCngCom->frameSize, 0.0f, hFdCngCom->frameSize ); /*olapBuffer, fftBuffer, olapWin*/ + + + for ( i = hFdCngCom->frameSize / 4; i < 3 * hFdCngCom->frameSize / 4; i++ ) + { + olapBuffer[i] += fftBuffer[i] * olapWin[i - hFdCngCom->frameSize / 4]; + } + for ( ; i < 5 * hFdCngCom->frameSize / 4; i++ ) + { + olapBuffer[i] = fftBuffer[i]; + } + + for ( ; i < 7 * hFdCngCom->frameSize / 4; i++ ) + { + olapBuffer[i] = fftBuffer[i]; + } + + for ( ; i < hFdCngCom->fftlen; i++ ) + { + olapBuffer[i] = 0; + } + + /* Get time-domain signal */ + v_multc( olapBuffer + hFdCngCom->frameSize / 4, (float) ( hFdCngCom->fftlen / 2 ), timeDomainOutput, samples_out ); + + /* Get excitation */ + v_multc( olapBuffer + hFdCngCom->frameSize / 4 - ( M + 1 ), (float) ( hFdCngCom->fftlen / 2 ), buf, M + 1 + hFdCngCom->frameSize ); + tmp = buf[0]; + preemph( buf + 1, PREEMPH_FAC, M + hFdCngCom->frameSize, &tmp ); + residu( hFdCngCom->A_cng, M, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize ); + + /* update and window olapBuf if we have a output frame that is shorter than the default frame size...*/ + if ( samples_out < hFdCngCom->frameSize ) + { + mvr2r( olapBuffer + samples_out, olapBuffer + hFdCngCom->frameSize, 3 * hFdCngCom->frameSize / 4 ); + } + for ( i = 5 * hFdCngCom->frameSize / 4; i < 7 * hFdCngCom->frameSize / 4; i++ ) + { + olapBuffer[i] *= olapWin[i - 3 * hFdCngCom->frameSize / 4]; + } + + return; +} +#endif /*------------------------------------------------------------------- * mhvals() diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 4a260abe2e6fa85ae0db69d4972edfb89cd4f022..91f1127788e07d7575689fdc2c3dd96dfcc48427 100755 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -208,6 +208,25 @@ typedef enum #define IVAS_NUM_SUPPORTED_FS 3 /* number of supported sampling-rates in IVAS */ +#ifdef JBM_TSM_ON_TCS +#define CLDFB_SLOT_NS 1250000L /* 1.25ms: CLDFB slot length */ +#define MAX_JBM_SUBFRAMES_5MS 8 +#define DEFAULT_JBM_SUBFRAMES_5MS 4 +#define JBM_CLDFB_SLOTS_IN_SUBFRAME 4 +#define MAX_JBM_CLDFB_TIMESLOTS 32 +#define DEFAULT_JBM_CLDFB_TIMESLOTS 16 +#define MAX_JBM_L_FRAME48k 1920 +#define MAX_JBM_L_FRAME_NS 40000000L +#define MAX_SPAR_INTERNAL_CHANNELS IVAS_SPAR_MAX_CH +#define MAX_CLDFB_DIGEST_CHANNELS 4 +typedef enum +{ + TC_BUFFER_MODE_NONE = 0, + TC_BUFFER_MODE_RENDERER, + TC_BUFFER_MODE_BUFFER +} TC_BUFFER_MODE; +#endif + /*----------------------------------------------------------------------------------* * IVAS Bitrates *----------------------------------------------------------------------------------*/ @@ -1410,7 +1429,11 @@ typedef enum #define PARAM_MC_REG_GHAT (0.001f) /* Regularization factor for mixing matrix calculation */ #define PARAM_MC_MAX_PARAMETER_BANDS 20 /* Maximum number of parameter bands */ #define PARAM_MC_MAX_PARAMETER_BANDS_RES 14 /* Maximum number of parameter bands with decorrelation */ +#ifdef JBM_TSM_ON_TCS +#define PARAM_MC_MAX_NSLOTS MAX_JBM_CLDFB_TIMESLOTS /* Maximum number of CLDFB slots in a frame */ +#else #define PARAM_MC_MAX_NSLOTS 16 /* Maximum number of CLDFB slots in a frame */ +#endif #define PARAM_MC_MAX_NSLOTS_IN_SUBFRAME 4 /* Maximum number of CLDFB slots in a subframe */ #define PARAM_MC_NSUBFRAMES_DEC 4 /* Number of subframes for the synthesis in the decoder */ #define PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND 30 /* Maximum number of CLDFB frequency bands within a parameter band */ diff --git a/lib_com/ivas_error.h b/lib_com/ivas_error.h index 9438ad44a1d309ca433de3e9a420f441e2245dad..ce5110920740c3238ef0642c0c26275ddbe6d798 100644 --- a/lib_com/ivas_error.h +++ b/lib_com/ivas_error.h @@ -87,6 +87,9 @@ typedef enum IVAS_ERR_ISM_INVALID_METADATA_VALUE, IVAS_ERR_INVALID_MASA_FORMAT_METADATA_FILE, IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED, +#ifdef VARIABLE_SPEED_DECODING + IVAS_ERR_VS_FRAME_NEEDED, +#endif #ifdef DEBUGGING IVAS_ERR_INVALID_FORCE_MODE, #ifdef DEBUG_AGC_ENCODER_CMD_OPTION diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 14a11b105ed8e94cde1a8c5226a57c06dcbeb2e6..dc803e58cb2a5adc6a9f6c77af5496441acbe571 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -251,12 +251,25 @@ ivas_error ivas_compute_core_buffers( /*! r: number of clipped samples */ uint32_t ivas_syn_output( - float synth[][L_FRAME48k], /* i/o: float synthesis signal */ +#ifdef JBM_TSM_ON_TCS + float *synth[], /* i/o: float synthesis signal */ +#else + float synth[][L_FRAME48k], /* i/o: float synthesis signal */ +#endif const int16_t output_frame, /* i : output frame length (one channel) */ const int16_t n_channels, /* i : number of output channels */ int16_t *synth_out /* o : integer 16 bits synthesis signal */ ); +#ifdef JBM_TSM_ON_TCS +void ivas_syn_output_f( + float *synth[], /* i/o: float synthesis signal */ + const int16_t output_frame, /* i : output frame length (one channel) */ + const int16_t n_channels, /* i : number of output channels */ + float *synth_out /* o : integer 16 bits synthesis signal */ + ); +#endif + void ivas_initialize_handles_enc( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ); @@ -299,6 +312,11 @@ ivas_error ivas_dec( ivas_error ivas_dec_setup( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ + #ifdef JBM_TSM_ON_TCS + , + uint16_t *nSamplesRendered, /* o : number of samples flushed from the previous frame (JBM) */ + int16_t *data /* o : flushed PCM samples */ +#endif ); ivas_error create_sce_dec( @@ -637,6 +655,11 @@ ivas_error ivas_mc_enc_config( ivas_error ivas_mc_dec_config( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const int16_t idx /* i : LS config. index */ + #ifdef JBM_TSM_ON_TCS + , + uint16_t *nSamplesRendered, /* o : samples flushed from last frame (JBM) */ + int16_t *data /* o : flushed samples (JBM) */ +#endif ); /*! r: MC format mode (MCT, McMASA, ParamMC) */ @@ -736,6 +759,104 @@ void dtx_read_padding_bits( const int16_t num_bits ); +#ifdef JBM_TSM_ON_TCS +/*----------------------------------------------------------------------------------* + * JBM prototypes + *----------------------------------------------------------------------------------*/ + +ivas_error ivas_jbm_dec_tc( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float *data /* o : output synthesis signal */ +); + +ivas_error ivas_jbm_dec_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const uint16_t nSamplesAsked, /* i : number of samples wanted */ + uint16_t *nSamplesRendered, /* o : number of samples rendered */ + uint16_t *nSamplesAvailableNext, /* o : number of samples still available in the rendering pipeline */ + int16_t *data /* o : output synthesis signal */ +); + +ivas_error ivas_jbm_dec_flush_renderer( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t tc_granularity_new, /* i : new renderer granularity */ + const RENDERER_TYPE renderer_type_old, /* i : old renderer type */ + const AUDIO_CONFIG intern_config_old, /* i : old internal config */ + const IVAS_OUTPUT_SETUP_HANDLE hIntSetupOld, /* i : old internal output setup */ + const MC_MODE mc_mode_old, /* i : old MC mode */ + const ISM_MODE ism_mode_old, /* i : old ISM mode */ + uint16_t *nSamplesRendered, /* o : number of samples flushed */ + int16_t *data /* o : rendered samples */ +); + +ivas_error ivas_jbm_dec_feed_tc_to_renderer( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t nSamplesForRendering, /* i: : number of TC samples available for rendering */ + int16_t *nSamplesResidual, /* o: : number of samples not fitting into the renderer grid and buffer for the next call*/ + float *data /* i/o: transport channels/output synthesis signal */ +); + +ivas_error ivas_jbm_dec_set_discard_samples( + Decoder_Struct *st_ivas /* i/o: main IVAS decoder structre */ +); + +void ivas_jbm_dec_get_adapted_linear_interpolator( + const int16_t default_interp_length, /* i : default length of the (full-frame) interpolator */ + const int16_t interp_length, /* i : length of the interpolator to be created */ + float *interpolator /* o : the interpolator */ +); + +void ivas_jbm_dec_get_adapted_subframes( + const int16_t nCldfbTs, /* i : number of time slots in the current frame */ + int16_t *subframe_nbslots, /* i/o: subframe grid */ + int16_t *nb_subframes /* i/o: number of subframes in the frame */ +); + +void ivas_jbm_dec_get_md_map( + const int16_t default_len, /* i : default frame length in metadata slots */ + const int16_t len, /* i : length of the modfied frames in metadata slots */ + const int16_t subframe_len, /* i : default length of a subframe */ + const int16_t offset, /* i : current read offset into the md buffer */ + const int16_t buf_len, /* i : length of the metadata buffer */ + int16_t *map /* o : metadata index map */ +); + +int16_t ivas_jbm_dec_get_num_tc_channels( Decoder_Struct *st_ivas ); /* i : IVAS decoder handle */ + +TC_BUFFER_MODE ivas_jbm_dec_get_tc_buffer_mode( + Decoder_Struct *st_ivas /* i : IVAS decoder handle */ +); + +int16_t ivas_jbm_dec_get_render_granularity( /* o : render granularity */ + const RENDERER_TYPE rendererType, /* i : renderer type */ + const int32_t output_Fs /* i : sampling rate */ +); + +ivas_error ivas_jbm_dec_tc_buffer_open( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const TC_BUFFER_MODE tc_buffer_mode, /* i : buffer mode */ + const int16_t nchan_transport_jbm, /* i : number of real transport channels */ + const int16_t nchan_transport_internal, /* i : number of totally buffered channels */ + const int16_t nchan_full, /* i : nubmer of channels to fully store */ + const int16_t n_samples_granularity /* i : granularity of the renderer/buffer */ +); + +ivas_error ivas_jbm_dec_tc_buffer_reconfigure( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const TC_BUFFER_MODE tc_buffer_mode, /* i : new buffer mode */ + const int16_t nchan_transport_jbm, /* i : new number of real transport channels */ + const int16_t nchan_transport_internal, /* i : new number of totally buffered channels */ + const int16_t nchan_full, /* i : new number of channels to fully store */ + const int16_t n_samples_granularity /* i : new granularity of the renderer/buffer */ +); + +void ivas_jbm_dec_tc_buffer_close( + DECODER_TC_BUFFER_HANDLE *phTcBuffer /* i/o: TC buffer handle */ +); +void ivas_jbm_dec_td_renderers_adapt_subframes( + Decoder_Struct *st_ivas +); +#endif /*----------------------------------------------------------------------------------* * ISM prototypes @@ -895,6 +1016,11 @@ ivas_error ivas_ism_dec_config( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ , const ISM_MODE last_ism_mode /* i/o: last ISM mode */ +#ifdef JBM_TSM_ON_TCS + , + uint16_t *nSamplesRendered, /* o : number of samples flushed on renderer change */ + int16_t *data /* o : flushed PCM samples */ +#endif ); ivas_error ivas_param_ism_dec_open( @@ -911,6 +1037,26 @@ void ivas_param_ism_dec( float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels/DirAC output */ ); +#ifdef JBM_TSM_ON_TCS +void ivas_ism_dec_digest_tc( + Decoder_Struct *st_ivas +); + +void ivas_param_ism_dec_digest_tc( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const uint16_t nCldfbSlots, /* i : number of CLFBS slots in the transport channels */ + float *transport_channels_f[] /* i : synthesized core-coder transport channels/DirAC output */ +); + +void ivas_param_ism_dec_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ + uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ + uint16_t *nSamplesAvailable, /* o : number of CLDFB slots still to render */ + float *output_f[] /* o : rendered time signal */ +); +#endif + void ivas_param_ism_params_to_masa_param_mapping( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); @@ -2659,7 +2805,11 @@ float sumAbs( void mvc2c( const uint8_t x[], /* i : input vector */ uint8_t y[], /* o : output vector */ +#ifdef FIX_XXX_JBM_FIFO_BUFFER + const int32_t n +#else const int16_t n /* i : vector size */ +#endif ); /*! r: the dot product x'*A*A'*x */ @@ -3290,6 +3440,16 @@ ivas_error ivas_sba_dec_reconfigure( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); +#ifdef JBM_TSM_ON_TCS +ivas_error ivas_sba_digest_tc( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const int16_t nchan_transport, /* i : number of transport channels */ + const int16_t nCldfbSlots, /* i : number of CLDFB slots */ + const int16_t nSamplesForRendering, /* i : number of samples provided */ + float *data[] /* i : transport channel samples */ + ); +#endif + void ivas_init_dec_get_num_cldfb_instances( Decoder_Struct *st_ivas, /* i : IVAS decoder structure */ int16_t *numCldfbAnalyses, /* o : number of CLDFB analysis instances */ @@ -3396,6 +3556,9 @@ void ivas_sba2mc_cldfb( float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: cldfb imag part */ const int16_t nb_channels_out, /* i : nb of output channels */ const int16_t nb_bands, /* i : nb of CLDFB bands to process */ +#ifdef JBM_TSM_ON_TCS + const int16_t nb_timeslots, /* i : number of time slots to process */ +#endif const float *hoa_dec_mtx /* i : HOA decoding mtx */ ); @@ -3481,13 +3644,54 @@ void ivas_dirac_dec_read_BS( int16_t *dirac_to_spar_md_bands /* o : DirAC->SPAR MD bands */ ); +#ifdef JBM_TSM_ON_TCS +void generate_masking_noise_lb_dirac( + HANDLE_FD_CNG_COM hFdCngCom, /* i/o: FD_CNG structure containing all buffers and variables */ + float *tdBuffer, /* i/o: time-domain signal, if NULL no LB-CNA */ + const int16_t nCldfbTs, /* i : number of CLDFB slots that will be rendered */ + const int16_t cna_flag /* i : CNA flag for LB and HB */ +); + +void ivas_dirac_dec_set_md_map( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + int16_t nCldfbTs ); + void ivas_dirac_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ + const int16_t nchan_transport /* i : number of transport channels */ +); +#endif + +#ifdef JBM_TSM_ON_TCS +void ivas_dirac_dec_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const int16_t nchan_transport, /* i : number of transport channels */ + const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ + uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ + uint16_t *nSamplesAvailable, /* o : number of CLDFB slots still to render */ + float *output_f[] /* o : rendered time signal */ +); +#endif + +#ifndef JBM_TSM_ON_TCS +void ivas_dirac_dec( +#else +void ivas_dirac_dec_render_sf( +#endif Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ +#ifdef JBM_TSM_ON_TCS + float *output_f[], /* i/o: synthesized core-coder transport channels/DirAC output */ +#else + float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ +#endif const int16_t nchan_transport, /* i : number of transport channels */ float *pppQMfFrame_ts_re[IVAS_MAX_FB_MIXER_IN_CH][CLDFB_NO_COL_MAX], - float *pppQMfFrame_ts_im[IVAS_MAX_FB_MIXER_IN_CH][CLDFB_NO_COL_MAX], + float *pppQMfFrame_ts_im[IVAS_MAX_FB_MIXER_IN_CH][CLDFB_NO_COL_MAX] +#ifndef JBM_TSM_ON_TCS + , const int16_t i_sf +#endif ); #ifdef FIX_417_TD_DECORR_BRATE_SW @@ -3614,15 +3818,25 @@ void ivas_dirac_dec_output_synthesis_close( void ivas_dirac_dec_output_synthesis_process_slot( const float *reference_power, /* i : Estimated power */ const float *onset, /* i : onset filter */ +#ifdef JBM_TSM_ON_TCS + const int16_t *azimuth, + const int16_t *elevation, + const float *diffuseness, +#endif DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ +#ifdef JBM_TSM_ON_TCS + const int16_t sh_rot_max_order, +#endif const float *p_Rmat, /* i : rotation matrix */ const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ const IVAS_OUTPUT_SETUP hOutSetup, /* i : output setup structure */ - const int16_t nchan_transport, /* i : number of transport channels */ -#ifndef HODIRAC - const int16_t index_slot + const int16_t nchan_transport /* i : number of transport channels */ +#if !defined( HODIRAC ) || defined( JBM_TSM_ON_TCS ) + , + const int16_t index_slot #endif #ifdef HODIRAC + , const int16_t hodirac #endif ); @@ -3632,17 +3846,27 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ const int16_t nchan_transport, /* i : number of transport channels */ +#ifdef JBM_TSM_ON_TCS + const int16_t nbslots, /* i : number of slots to process */ +#endif const float *onset_filter #ifdef HODIRAC , +#ifdef JBM_TSM_ON_TCS + const int16_t md_idx, +#endif const int16_t hodirac /* i: flag for sector-based processing */ #endif ); void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ - DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ + float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ + float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ +#ifdef JBM_TSM_ON_TCS + const int16_t nbslots, /* i : number of slots to process */ + const int16_t diff_md_idx, /* i : md slot idx of diffuseness to use */ +#endif float *reference_power_smooth, float qualityBasedSmFactor ); @@ -3681,9 +3905,14 @@ void ivas_dirac_dec_compute_directional_responses( DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ const MASA_DECODER_HANDLE hMasa, /* i : MASA decoder structure */ +#ifdef JBM_TSM_ON_TCS + const int16_t *azimuth, + const int16_t *elevation, + const int16_t md_idx, +#endif const float *surCohRatio, - const int16_t shd_rot_max_order, /* i : split-order rotation method */ - const float *p_Rmat /* i : rotation matrix */ + const int16_t shd_rot_max_order, /* i : split-order rotation method */ + const float *p_Rmat /* i : rotation matrix */ #ifdef HODIRAC , const int16_t hodirac /* i : flag for sector based dirac processing */ @@ -3814,9 +4043,29 @@ void ivas_param_mc_dec_read_BS( int16_t *nb_bits /* o : number of bits written */ ); +#ifdef JBM_TSM_ON_TCS +void ivas_param_mc_dec_digest_tc( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const uint8_t nCldfbSlots, /* i : number of CLFBS slots in the transport channels */ + float *transport_channels_f[] /* i : synthesized core-coder transport channels/DirAC output */ +); + +void ivas_param_mc_dec_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ + uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ + uint16_t *nSamplesAvailable, /* o : number of CLDFB slots still to render */ + float *output_f[] /* o : rendered time signal */ +); +#endif + void ivas_param_mc_dec( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels/DirAC output */ +#ifdef JBM_TSM_ON_TCS + float *output_f[] /* i/o: synthesized core-coder transport channels/DirAC output */ +#else + float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels/DirAC output */ +#endif ); void ivas_param_mc_default_icc_map( @@ -3947,6 +4196,12 @@ ivas_error ivas_dirac_dec_output_synthesis_cov_open( const float *proto_matrix /* i : the prototype (upmix) matrix (only used if mode == 1) */ ); +#ifdef JBM_TSM_ON_TCS +void ivas_dirac_dec_output_synthesis_get_interpolator( + DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params, /* i/o: handle for the covariance synthesis parameters */ + const uint16_t interp_length ); +#endif + void ivas_dirac_dec_output_synthesis_cov_init( DIRAC_OUTPUT_SYNTHESIS_COV_STATE *h_dirac_output_synthesis_state, /* i/o: pointer to the state of the covariance synthesis */ const int16_t nchan_in, /* i : number of input (tranport) channels */ @@ -3961,27 +4216,45 @@ void ivas_dirac_dec_output_synthesis_cov_close( ); void ivas_dirac_dec_output_synthesis_cov_param_mc_collect_slot( - float RealBuffer[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : input channel filter bank samples (real part) */ - float ImagBuffer[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : input channel filter bank samples (imaginary part */ - float cx[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], /* o : accumulated input covariance (real part) */ - float cx_imag[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], /* o : accumulated input covariance (imaginary part) */ - PARAM_MC_DEC_HANDLE hParamMC, /* i : handle to Parametric MC state */ - const int16_t nchan_in, /* i : number of input channels */ - const int16_t idx_slot /* i : index of the slot to be added to the input covariance */ -); - +#ifdef JBM_TSM_ON_TCS + float *RealBuffer, /* i : input channel filter bank samples (real part) */ + float *ImagBuffer, /* i : input channel filter bank samples (imaginary part */ +#else + float RealBuffer[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : input channel filter bank samples (real part) */ + float ImagBuffer[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : input channel filter bank samples (imaginary part */ +#endif + float cx[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], /* o : accumulated input covariance (real part) */ + float cx_imag[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], /* o : accumulated input covariance (imaginary part) */ + PARAM_MC_DEC_HANDLE hParamMC, /* i : handle to Parametric MC state */ + const int16_t nchan_in /* i : number of input channels */ +#ifndef JBM_TSM_ON_TCS + , + const int16_t idx_slot /* i : index of the slot to be added to the input covariance */ +#endif +); + void ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot( - float Cldfb_RealBuffer_in[][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : input channel filter bank samples (real part) */ - float Cldfb_ImagBuffer_in[][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : input channel filter bank samples (imaginary part) */ - float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : output channel filter bank samples (real part) */ - float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : output channel filter bank samples (imaginary part) */ - float mixing_matrix[PARAM_MC_MAX_PARAMETER_BANDS][MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS], /* i : parameter band wise mixing matrices (direct part) */ - float mixing_matrix_res[PARAM_MC_MAX_PARAMETER_BANDS_RES][MAX_CICP_CHANNELS * MAX_CICP_CHANNELS], /* i : parameter band wise mixing matrices (residual part) */ - const uint16_t slot_idx_sfr, /* i : time slot index for the current slot within the current subframe */ - const uint16_t slot_idx_tot, /* i : time slot index for the current slot within the frame */ - const int16_t nX, /* i : number of input channels */ - const int16_t nY, /* i : number of output channels */ - PARAM_MC_DEC_HANDLE hMetadataPMC /* i : handle to the Parametric MC decoder state */ +#ifdef JBM_TSM_ON_TCS + float *Cldfb_RealBuffer_in, /* i : input channel filter bank samples (real part) */ + float *Cldfb_ImagBuffer_in, /* i : input channel filter bank samples (imaginary part) */ +#else + float Cldfb_RealBuffer_in[PARAM_MC_MAX_TRANSPORT_CHANS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : CLDFB samples of the transport channels (real part) */ + float Cldfb_ImagBuffer_in[PARAM_MC_MAX_TRANSPORT_CHANS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : CLDFB samples of the transport channels (imaginary part) */ +#endif + float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : output channel filter bank samples (real part) */ + float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : output channel filter bank samples (imaginary part) */ +#ifdef JBM_TSM_ON_TCS + float *mixing_matrix[], /* i : parameter band wise mixing matrices (direct part) */ + float *mixing_matrix_res[], /* i : parameter band wise mixing matrices (residual part) */ +#else + float mixing_matrix[PARAM_MC_MAX_PARAMETER_BANDS][MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS], /* i : parameter band wise mixing matrices (direct part) */ + float mixing_matrix_res[PARAM_MC_MAX_PARAMETER_BANDS_RES][MAX_CICP_CHANNELS * MAX_CICP_CHANNELS], /* i : parameter band wise mixing matrices (residual part) */ +#endif + const uint16_t slot_idx_sfr, /* i : time slot index for the current slot within the current subframe */ + const uint16_t slot_idx_tot, /* i : time slot index for the current slot within the frame */ + const int16_t nX, /* i : number of input channels */ + const int16_t nY, /* i : number of output channels */ + PARAM_MC_DEC_HANDLE hParamMC /* i : handle to the Parametric MC decoder state */ ); int16_t computeMixingMatricesISM( @@ -4065,7 +4338,11 @@ void ivas_sba_upmixer_renderer( ); ivas_error ivas_sba_linear_renderer( +#ifdef JBM_TSM_ON_TCS + float *output_f[], /* i/o: synthesized core-coder transport channels/DirAC output */ +#else float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ +#endif const int16_t output_frame, /* i : output frame length per channel */ const int16_t nchan_in, /* i : number of input ambisonics channels */ const AUDIO_CONFIG output_config, /* i : output audio configuration */ @@ -4081,6 +4358,14 @@ void ivas_sba_mix_matrix_determiner( const int16_t output_frame /* i : output frame length */ ); +#ifdef JBM_TSM_ON_TCS +void ivas_sba_prototype_renderer_sf( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ + float inRe[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : Input audio in CLDFB domain, real */ + float inIm[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /* i : Input audio in CLDFB domain, imag */ +); +#endif + /* AGC */ /*! r: AGC enable flag */ int16_t ivas_agc_enc_get_flag( @@ -4237,6 +4522,51 @@ int16_t ivas_is_res_channel( const int16_t nchan_transport /* i : number of transport channels (1-4) */ ); +#ifdef JBM_TSM_ON_TCS +void ivas_spar_dec_agc_pca( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + float output[][L_FRAME48k], /* i/o: input/output audio channels */ + const int16_t output_frame /* i : output frame length */ +); + +void ivas_spar_dec_set_render_map( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + int16_t nCldfbTs +); + +void ivas_spar_dec_set_render_params( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const int16_t n_cldfb_slots /* i : number of cldfb slots in this frame */ +); + +void ivas_spar_dec_digest_tc( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const int16_t nchan_transport, /* i : number of transport channels */ + const int16_t nCldfbSlots, /* i : number of CLDFB slots */ + const int16_t nSamplesForRendering /* i : number of samples provided */ +); + +ivas_error ivas_sba_dec_digest_tc( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const int16_t nCldfbSlots, /* i : number of CLDFB slots */ + const int16_t nSamplesForRendering /* i : number of samples provided */ +); + +void ivas_sba_dec_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ + uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ + uint16_t *nSamplesAvailable, /* o : number of CLDFB slots still to render */ + float *output_f[] /* o : rendered time signal */ +); + +void ivas_spar_dec_upmixer_sf( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + float *output[], /* o : output audio channels */ + const int16_t nchan_internal /* i : number of internal channels */ +); +#endif + void ivas_spar_dec_upmixer( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ float output[][L_FRAME48k], /* i/o: input/output audio channels */ @@ -4508,7 +4838,11 @@ void ivas_td_decorr_dec_close( void ivas_td_decorr_process( ivas_td_decorr_state_t *hTdDecorr, /* i/o: SPAR Covar. decoder handle */ +#ifdef JBM_TSM_ON_TCS + float *pcm_in[], /* i : input audio channels */ +#else float pcm_in[][L_FRAME48k], /* i : input audio channels */ +#endif float **ppOut_pcm, /* o : output audio channels */ const int16_t output_frame /* i : output frame length */ ); @@ -4862,6 +5196,21 @@ void ivas_masa_prerender( const int16_t output_frame /* i : output frame length per channel */ ); +#ifdef JBM_TSM_ON_TCS +#ifndef FIX_355_REFACTOR_PARAMBIN_TO_5MS +void ivas_spar_param_to_masa_param_mapping_sf( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ + int16_t azimuth[CLDFB_NO_CHANNELS_MAX], + int16_t elevation[CLDFB_NO_CHANNELS_MAX], + float energy_ratio1[CLDFB_NO_CHANNELS_MAX], + float spreadCoherence[CLDFB_NO_CHANNELS_MAX], + float surroundingCoherence[CLDFB_NO_CHANNELS_MAX], + float inRe[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : Input audio in CLDFB domain, real */ + float inIm[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /* i : Input audio in CLDFB domain, imag */ +); +#endif +#endif + #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS void ivas_spar_param_to_masa_param_mapping( Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ @@ -4895,12 +5244,28 @@ void ivas_binRenderer_close( #ifdef DEBUGGING void ivas_binaural_cldfb( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ +#ifdef JBM_TSM_ON_TCS + float *output_f[] /* i/o: synthesized core-coder transport channels/DirAC output */ +#else float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels/DirAC output */ +#endif +); + +#ifdef JBM_TSM_ON_TCS +void ivas_binaural_cldfb_sf( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t n_samples_to_render, + float *output_f[] /* i/o: synthesized core-coder transport channels/DirAC output */ ); +#endif + #endif void ivas_binRenderer( BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: fastconv binaural renderer handle */ HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i/o: head track handle */ +#ifdef JBM_TSM_ON_TCS + const int16_t numTimeSlots, /* i: : number of time slots to process */ +#endif float Cldfb_RealBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */ float Cldfb_ImagBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */ float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ @@ -4910,7 +5275,12 @@ void ivas_binRenderer( void ivas_binaural_add_LFE( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ int16_t output_frame, /* i : length of input frame */ +#ifdef JBM_TSM_ON_TCS + float *input_f[], /* i : transport channels */ + float *output_f[] /* o : synthesized core-coder transport channels/DirAC output */ +#else float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels/DirAC output */ +#endif ); @@ -4924,10 +5294,22 @@ ivas_error ivas_ism_renderer_open( void ivas_ism_render( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ +#ifdef JBM_TSM_ON_TCS + float *output_f[], /* i/o: core-coder transport channels/object output */ +#else float output_f[][L_FRAME48k], /* i/o: core-coder transport channels/object output */ +#endif const int16_t output_frame /* i : output frame length per channel */ ); +#ifdef JBM_TSM_ON_TCS +void ivas_ism_render_sf( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float *output_f[], /* i/o: core-coder transport channels/object output */ + const int16_t n_samples_to_render /* i : output frame length per channel */ +); +#endif + void ivas_ism_get_stereo_gains( const float azimuth, /* i : object azimuth */ const float elevation, /* i : object elevation */ @@ -4937,14 +5319,23 @@ void ivas_ism_get_stereo_gains( void ivas_mc2sba( IVAS_OUTPUT_SETUP hIntSetup, /* i : Format of decoder output */ - float buffer_td[][L_FRAME48k], /* i/o: MC signals (on input) and the HOA3 (on output) */ +#ifdef JBM_TSM_ON_TCS + float *in_buffer_td[], /* i : MC signals (on input) and the HOA3 (on output) */ + float *buffer_td[], /* o : MC signals (on input) and the HOA3 (on output) */ +#else + float buffer_td[][L_FRAME48k], /* i/o: MC signals (on input) and the HOA3 (on output) */ +#endif const int16_t output_frame, /* i : output frame length per channel */ const int16_t sba_order, /* i : SBA order */ const float gain_lfe /* i : gain for LFE, 0=ignore LFE */ ); void ivas_ism2sba( - float buffer_td[][L_FRAME48k], /* i/o: TD signal buffers */ +#ifdef JBM_TSM_ON_TCS + float *buffer_td[], /* i/o: TD signal buffers */ +#else + float buffer_td[][L_FRAME48k], /* i/o: TD signal buffers */ +#endif ISM_RENDERER_HANDLE hIsmRendererData, /* i/o: renderer data */ const ISM_METADATA_HANDLE hIsmMetaData[], /* i : object metadata */ const int16_t nchan_ism, /* i : number of objects */ @@ -4952,7 +5343,17 @@ void ivas_ism2sba( const int16_t sba_order /* i : SBA order */ ); - +#ifdef JBM_TSM_ON_TCS +void ivas_ism2sba_sf( + float *buffer_in[], /* i : TC buffer */ + float *buffer_out[], /* o : TD signal buffers */ + ISM_RENDERER_HANDLE hIsmRendererData, /* i/o: renderer data */ + const int16_t num_objects, /* i : number of objects */ + const int16_t n_samples_to_render, /* i : output frame length per channel */ + const int16_t offset, /* i : offset for the interpolatr */ + const int16_t sba_order /* i : Ambisonic (SBA) order */ +); +#endif /*----------------------------------------------------------------------------------* * Amplitude Panning VBAP prototypes *----------------------------------------------------------------------------------*/ @@ -5000,20 +5401,20 @@ void ivas_ls_setup_conversion_close( LSSETUP_CONVERSION_HANDLE *hLsSetUpConversion /* i/o: LS converter handle */ ); -#ifdef MC_PARAMUPMIX_MODE + void ivas_ls_setup_conversion( Decoder_Struct *st_ivas, /* i : IVAS decoder structure */ +#ifdef MC_PARAMUPMIX_MODE const int16_t input_chans, /* i : number of input channels to the renderer */ +#endif const int16_t output_frame, /* i : frame length */ - float output[][L_FRAME48k] /* i/o: LS input/output synthesis signal */ -); +#ifdef JBM_TSM_ON_TCS + float *input[], /* i : LS input/output synthesis signal */ + float *output[] /* i/o: LS input/output synthesis signal */ #else -void ivas_ls_setup_conversion( - Decoder_Struct *st_ivas, /* i : IVAS decoder structure */ - const int16_t output_frame, /* i : frame length */ - float output[][L_FRAME48k] /* i/o: LS input/output synthesis signal */ -); + float output[][L_FRAME48k] /* i/o: LS input/output synthesis signal */ #endif +); void ivas_ls_setup_conversion_process_mdct( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ @@ -5027,6 +5428,9 @@ void ivas_ls_setup_conversion_process_mdct_param_mc( void ivas_lssetupconversion_process_param_mc( Decoder_Struct *st_ivas, /* i/o: LS setup conversion renderer handle */ +#ifdef JBM_TSM_ON_TCS + int16_t num_timeslots, /* i : number of time slots to process */ +#endif float Cldfb_RealBuffer_InOut[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals */ float Cldfb_ImagBuffer_InOut[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals */ int16_t channel_active[MAX_CICP_CHANNELS] /* i : bitmap indicating which output channels are active */ @@ -5257,10 +5661,21 @@ ivas_error ivas_td_binaural_open( ivas_error ivas_td_binaural_renderer( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ +#ifdef JBM_TSM_ON_TCS + float *output[], /* i/o: SCE channels / Binaural synthesis */ +#else + float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ +#endif const int16_t output_frame /* i : output frame length */ ); +#ifdef JBM_TSM_ON_TCS +void ObjRenderIVASSubframe( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float *output[], /* i/o: SCE channels / Binaural synthesis */ + const int16_t output_frame /* i : output frame length */ +); +#endif /*----------------------------------------------------------------------------------* * Filter-bank (FB) Mixer diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index a63b2ebd6b2501886df6557d481190083c845f71..e2f2e0f1f28605512ca05562788e267b0ca68b08 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -354,7 +354,7 @@ typedef struct ivas_agc_chan_data_t typedef struct ivas_agc_com_state_t { float *winFunc; - int16_t in_delay; + int16_t in_delay; /* TODO: JBM check if this needs to be adjusted in the dec */ uint16_t absEmin; uint16_t betaE; uint16_t maxAttExp; @@ -711,6 +711,10 @@ typedef struct ivas_td_decorr_state_t int16_t num_apd_sections; int16_t ducking_flag; +#ifdef JBM_TSM_ON_TCS + int16_t offset; +#endif + } ivas_td_decorr_state_t; diff --git a/lib_com/ivas_td_decorr.c b/lib_com/ivas_td_decorr.c index b1947cdd253d21f3ad9354b36372407331d7beda..9a08c06f6a3fd08d11edc45bdc83253e07324bef 100644 --- a/lib_com/ivas_td_decorr.c +++ b/lib_com/ivas_td_decorr.c @@ -226,7 +226,9 @@ ivas_error ivas_td_decorr_dec_open( return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR COV decoder" ); } set_f( hTdDecorr_loc->look_ahead_buf, 0, (int16_t) ( output_Fs * IVAS_DECORR_PARM_LOOKAHEAD_TAU ) ); - +#ifdef JBM_TSM_ON_TCS + hTdDecorr_loc->offset = (int16_t) ( output_Fs * IVAS_DECORR_PARM_LOOKAHEAD_TAU ); +#endif hTdDecorr_loc->num_apd_sections = ivas_get_APD_filt_orders( num_out_chans, output_Fs, hTdDecorr_loc->APD_filt_state[0].order ); for ( j = 0; j < num_out_chans; j++ ) @@ -477,20 +479,32 @@ static void ivas_td_decorr_APD_sections( void ivas_td_decorr_process( ivas_td_decorr_state_t *hTdDecorr, /* i/o: SPAR Covar. decoder handle */ - float pcm_in[][L_FRAME48k], /* i : input audio channels */ - float **ppOut_pcm, /* o : output audio channels */ - const int16_t output_frame /* i : output frame length */ +#ifdef JBM_TSM_ON_TCS + float *pcm_in[], +#else + float pcm_in[][L_FRAME48k], /* i : input audio channels */ +#endif + float **ppOut_pcm, /* o : output audio channels */ + const int16_t output_frame /* i : output frame length */ ) { int16_t i, j; +#ifndef JBM_TSM_ON_TCS int16_t offset; +#endif float in_duck_gain[L_FRAME48k], out_duck_gain[L_FRAME48k]; +#ifndef JBM_TSM_ON_TCS offset = (int16_t) ( output_frame * FRAMES_PER_SEC * IVAS_DECORR_PARM_LOOKAHEAD_TAU ); +#endif /* Look-ahead delay */ mvr2r( pcm_in[0], ppOut_pcm[0], output_frame ); +#ifdef JBM_TSM_ON_TCS + delay_signal( ppOut_pcm[0], output_frame, hTdDecorr->look_ahead_buf, hTdDecorr->offset ); +#else delay_signal( ppOut_pcm[0], output_frame, hTdDecorr->look_ahead_buf, offset ); +#endif /* In ducking gains */ if ( hTdDecorr->ducking_flag ) diff --git a/lib_com/ivas_tools.c b/lib_com/ivas_tools.c index b75c08379121fbeab38909b5b787ca0fec8a31e2..ce4abafeb5d8cda10fa6ff720e89e7a1322c2e32 100644 --- a/lib_com/ivas_tools.c +++ b/lib_com/ivas_tools.c @@ -75,10 +75,18 @@ float sumAbs( void mvc2c( const uint8_t x[], /* i : input vector */ uint8_t y[], /* o : output vector */ - const int16_t n /* i : vector size */ +#ifdef FIX_XXX_JBM_FIFO_BUFFER + const int32_t n +#else + const int16_t n /* i : vector size */ +#endif ) { +#ifdef FIX_XXX_JBM_FIFO_BUFFER + int32_t i; +#else int16_t i; +#endif if ( n <= 0 ) { @@ -114,14 +122,22 @@ void mvc2c( /*! r: number of clipped samples */ uint32_t ivas_syn_output( - float synth[][L_FRAME48k], /* i/o: float synthesis signal */ +#ifdef JBM_TSM_ON_TCS + float *synth[], /* i/o: float synthesis signal */ +#else + float synth[][L_FRAME48k], /* i/o: float synthesis signal */ +#endif const int16_t output_frame, /* i : output frame length (one channel) */ const int16_t n_channels, /* i : number of output channels */ int16_t *synth_out /* o : integer 16 bits synthesis signal */ ) { int16_t i, n; +#ifdef JBM_TSM_ON_TCS + int16_t synth_loc[MAX_JBM_L_FRAME48k]; +#else int16_t synth_loc[L_FRAME48k]; +#endif uint32_t noClipping = 0; /*-----------------------------------------------------------------* @@ -147,6 +163,40 @@ uint32_t ivas_syn_output( return noClipping; } +#ifdef JBM_TSM_ON_TCS +/*-------------------------------------------------------------------* + * ivas_syn_output_f() + * + * Output ivas synthesis signal with compensation for saturation + * returns number of clipped samples + *-------------------------------------------------------------------*/ + +/*! r: number of clipped samples */ +void ivas_syn_output_f( + float *synth[], /* i/o: float synthesis signal */ + const int16_t output_frame, /* i : output frame length (one channel) */ + const int16_t n_channels, /* i : number of output channels */ + float *synth_out /* o : integer 16 bits synthesis signal */ +) +{ + int16_t i, n; + + /*-----------------------------------------------------------------* + * float to integer conversion with saturation control + *-----------------------------------------------------------------*/ + + for ( n = 0; n < n_channels; n++ ) + { + for ( i = 0; i < output_frame; i++ ) + { + synth_out[i * n_channels + n] = synth[n][i]; + } + } + + return; +} +#endif + /*-------------------------------------------------------------------* * mvr2r_inc() * diff --git a/lib_com/options.h b/lib_com/options.h old mode 100755 new mode 100644 index 655c16b308835db9191cd050cc5014975cce6d5b..b5cefac8e60187ee55802e5d583ae8392cb20401 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -126,6 +126,7 @@ /*#define SPAR_HOA_DBG*/ /* SPAR HOA debug statements */ /*#define DEBUG_BINAURAL_FILTER_DESIGN*/ /* debugging of Crend binaural filter design */ #define DEBUG_AGC_ENCODER_CMD_OPTION /* Ability to force enable or disable AGC behaviour in DIRAC/SPAR via command line option */ +#define DEBUG_JBM_CMD_OPTION /* ability for telling the decoder the frontend fetch size and to not delay compensate for bad frames at the beginning */ #endif /* #################### End DEBUGGING switches ############################ */ @@ -152,6 +153,7 @@ #define SNS_MSVQ /* FhG: contribution 33 - MSVQ for SNS parameters at stereo mid bitrates */ +/*#define FIX_XXX_JBM_FIFO_BUFFER */ /* FhG: prevent wraparound of a length identifier in cause of large frames and many channels*/ #define FIX_379_GAININTP /* Eri: Adds a gain interpolation for directional/distance gain to handle abrupt changes in metadata (Non BE) */ #define FIX_387_ISM_MD_FEC /* VA: Issue 387: fix MD discontinuity in ISM FEC */ @@ -218,6 +220,8 @@ #define COMPLEXITY_LEVEL_INDICATION +#define VARIABLE_SPEED_DECODING /* FhG: variable speed decoding employing the JBM functioniality */ +#define JBM_TSM_ON_TCS /* FhG: run the TSM part of JBM on the TCs instead of the final output pcm waveforms */ /* ################## End DEVELOPMENT switches ######################### */ /* clang-format on */ diff --git a/lib_com/prot.h b/lib_com/prot.h index 69bcaa6647e5993a78d229b349a279ab79e90b4d..8c6fdd674f7cc674b1059abde2f0205c9f949bce 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -177,7 +177,11 @@ float sum2_f( void set_c( int8_t y[], /* i/o: Vector to set */ const int8_t a, /* i : Value to set the vector to */ - const int16_t N /* i : Lenght of the vector */ +#ifdef JBM_TSM_ON_TCS + const int32_t N /* i : Length of the vector */ +#else + const int16_t N /* i : Length of the vector */ +#endif ); void set_s( @@ -8614,6 +8618,17 @@ void generate_masking_noise_mdct( HANDLE_FD_CNG_COM hFdCngCom /* i/o: FD_CNG structure containing all buffers and variables */ ); +#ifdef JBM_TSM_ON_TCS +void SynthesisSTFT_dirac( + float *fftBuffer, /* i : FFT bins */ + float *timeDomainOutput, + float *olapBuffer, + const float *olapWin, + const int16_t samples_out, + HANDLE_FD_CNG_COM hFdCngCom /* i/o: FD_CNG structure containing all buffers and variables */ +); +#endif + void generate_masking_noise_dirac( HANDLE_FD_CNG_COM hFdCngCom, /* i/o: FD_CNG structure containing all buffers and variables */ HANDLE_CLDFB_FILTER_BANK h_cldfb, /* i : filterbank state */ diff --git a/lib_com/tools.c b/lib_com/tools.c index 46803c8b1ed2f7539bcc20035350f884581734cb..b730564580e892b85eee18f9a391e4540e3ac555 100644 --- a/lib_com/tools.c +++ b/lib_com/tools.c @@ -210,7 +210,11 @@ float sum2_f( void set_c( int8_t y[], /* i/o: Vector to set */ const int8_t a, /* i : Value to set the vector to */ +#ifdef JBM_TSM_ON_TCS + const int32_t N /* i : Length of the vector */ +#else const int16_t N /* i : Length of the vector */ +#endif ) { int16_t i; @@ -387,7 +391,11 @@ uint32_t mvr2s( return 0; } +#ifdef JBM_TSM_ON_TCS + if ( (void *) y <= (const void *) x ) +#else if ( (void *) y < (const void *) x ) +#endif { for ( i = 0; i < n; i++ ) { diff --git a/lib_debug/debug.c b/lib_debug/debug.c index 85e48e8bae0b71aaa6c4dfc4484b6ddbd53dd285..ce10231876d27e76b141333f2fa70423abb4430e 100644 --- a/lib_debug/debug.c +++ b/lib_debug/debug.c @@ -201,6 +201,7 @@ int16_t dbgwrite( return 0; } + /*-------------------------------------------------------------------* * dbgwrite_mat_repeat() * diff --git a/lib_debug/sba_debug.c b/lib_debug/sba_debug.c index 040cadf88774b68fad67286377ef5ad721c15ee5..73bb630b5fe54dee3600127f19cf5882c425bdbc 100644 --- a/lib_debug/sba_debug.c +++ b/lib_debug/sba_debug.c @@ -51,11 +51,11 @@ #define MAX_IN_FILE_LEN ( 1000 ) #define MAX_PLUG_IN_FILE_LEN ( MAX_IN_FILE_LEN ) #define MAX_DEBUG_TAG_LEN ( 50 ) -#define NUM_DEBUG_FILES ( 4 ) +#define NUM_DEBUG_FILES ( 5 ) #define MAX_TAG_LEN ( 200 ) WAVEFILEOUT *spar_foa_enc_wav[3]; -WAVEFILEOUT *spar_foa_dec_wav[4]; +WAVEFILEOUT *spar_foa_dec_wav[NUM_DEBUG_FILES]; float max_diff = 0; int32_t dbg_frm_num; int32_t dbg_band; @@ -202,6 +202,7 @@ void ivas_spar_dump_signal_wav( { for ( i = 0; i < no_channel; i++, k++ ) { +#if 0 if ( ppPcm ) { tmp_value = roundf( ppPcm[i][j] * PCM16_TO_FLT_FAC ); @@ -210,6 +211,16 @@ void ivas_spar_dump_signal_wav( { tmp_value = roundf( pcm_array[i][j] * PCM16_TO_FLT_FAC ); } +#else + if ( ppPcm ) + { + tmp_value = roundf( ppPcm[i][j] ); + } + else + { + tmp_value = roundf( pcm_array[i][j] ); + } +#endif if ( tmp_value > MAX16B_FLT ) { largest_value = (float) fabs( tmp_value ) > largest_value ? (float) fabs( tmp_value ) : largest_value; @@ -272,6 +283,12 @@ void ivas_close_sba_decoder_debug_files( CloseWav( spar_foa_dec_wav[3] ); } + if ( spar_foa_dec_wav[4] != NULL ) + { + UpdateWave( fs, n_ch, 16, spar_foa_dec_wav[4] ); + CloseWav( spar_foa_dec_wav[4] ); + } + return; } @@ -315,7 +332,7 @@ void ivas_open_sba_decoder_debug_files( const int16_t n_ch, const int16_t n_transport ) { - int8_t fb_wav_dump_path[4][MAX_PLUG_IN_FILE_LEN] = { "", "", "", "" }; + int8_t fb_wav_dump_path[NUM_DEBUG_FILES][MAX_PLUG_IN_FILE_LEN] = { "", "", "", "", "" }; cstrcat( (char *) fb_wav_dump_path[0], sizeof( fb_wav_dump_path[0] ), "dec_out.wav" ); spar_foa_dec_wav[0] = CreateWav( (const char *) fb_wav_dump_path[0], fs, n_ch, 32 /* const uint32_t writeWaveExt */ ); @@ -329,6 +346,9 @@ void ivas_open_sba_decoder_debug_files( cstrcat( (char *) fb_wav_dump_path[3], sizeof( fb_wav_dump_path[3] ), "cldfbSynthesis.wav" ); spar_foa_dec_wav[3] = CreateWav( (const char *) fb_wav_dump_path[3], fs, n_transport, 16 /* const uint32_t writeWaveExt */ ); + cstrcat( (char *) fb_wav_dump_path[4], sizeof( fb_wav_dump_path[4] ), "cldfbAnalysis.wav" ); + spar_foa_dec_wav[4] = CreateWav( (const char *) fb_wav_dump_path[4], fs, n_transport, 16 /* const uint32_t writeWaveExt */ ); + return; } diff --git a/lib_debug/sba_debug.h b/lib_debug/sba_debug.h index cd4fd58c11a22f39e99b8d73a6c6dd12ce7212d1..a314d1568cc2df74be82d26610a30b00e78b6866 100644 --- a/lib_debug/sba_debug.h +++ b/lib_debug/sba_debug.h @@ -41,9 +41,10 @@ #include "ivas_cnst.h" #include "tinywaveout_c.h" + #ifdef DEBUG_SBA_AUDIO_DUMP extern WAVEFILEOUT *spar_foa_enc_wav[3]; -extern WAVEFILEOUT *spar_foa_dec_wav[4]; +extern WAVEFILEOUT *spar_foa_dec_wav[5]; #endif #ifdef DEBUG_AGC diff --git a/lib_dec/fd_cng_dec.c b/lib_dec/fd_cng_dec.c index 38495a681acd2ffbcc3d2893fc42c45aab9b3a46..7f8eba27c0e5a7f9dd7ff5f953e1818e7e3b5de0 100644 --- a/lib_dec/fd_cng_dec.c +++ b/lib_dec/fd_cng_dec.c @@ -1798,6 +1798,162 @@ void generate_stereo_masking_noise( return; } +#ifdef JBM_TSM_ON_TCS +/*------------------------------------------------------------------- + * generate_masking_noise_hf_cldfb() + * + * Generate additional comfort noise (kind of noise filling) + *-------------------------------------------------------------------*/ + +void generate_masking_noise_lb_dirac( + HANDLE_FD_CNG_COM hFdCngCom, /* i/o: FD_CNG structure containing all buffers and variables */ + float *tdBuffer, /* i/o: time-domain signal, if NULL no LB-CNA */ + const int16_t nCldfbTs, /* i : number of CLDFB slots that will be rendered */ + const int16_t cna_flag /* i : CNA flag for LB and HB */ +) +{ + int16_t i; + float *cngNoiseLevel = hFdCngCom->cngNoiseLevel; + float *fftBuffer = hFdCngCom->fftBuffer; + float *ptr_r; + float *ptr_i; + float *ptr_level; + int16_t *seed = &( hFdCngCom->seed ); + float scale; + int16_t n_samples_out, n_samples_start, n_samples_out_loop; + + push_wmops( "fd_cng_dirac" ); + + /* Init */ + scale = 0.f; + n_samples_out = hFdCngCom->frameSize / DEFAULT_JBM_CLDFB_TIMESLOTS * nCldfbTs; + n_samples_start = 0; + + + /*LB CLDFB - CNA from STFT*/ +#ifdef DEBUG_MODE_DIRAC + { + int16_t tmp_s; + tmp_s = (int16_t) ( 32768.f * 0.5f * hFdCngCom->likelihood_noisy_speech * cna_flag + 0.5f ); + dbgwrite( &tmp_s, sizeof( int16_t ), 1, hFdCngCom->frameSize / 16, "./res/ivas_dirac_likelihood_noisy.pcm" ); + } +#endif + if ( cna_flag ) + { + /* skip noise generating if level is very low, to avoid problems with possibly running into denormals */ + if ( hFdCngCom->likelihood_noisy_speech > DELTA_MASKING_NOISE ) + { + /* Compute additional CN level */ + for ( i = 0; i < 15; i++ ) + { + if ( ( hFdCngCom->CngBandwidth == scaleTable_cn_dirac[i].bwmode ) && + ( hFdCngCom->CngBitrate >= scaleTable_cn_dirac[i].bitrateFrom ) && + ( hFdCngCom->CngBitrate < scaleTable_cn_dirac[i].bitrateTo ) ) + { + break; + } + } + + scale = (float) pow( 10.f, -scaleTable_cn_dirac[i].scale / 10.f ) - 1.f; + scale *= hFdCngCom->likelihood_noisy_speech; + } + } + + /* LB CLDFB - CNA from STFT: CNA applied only in channel 0*/ + if ( cna_flag && tdBuffer != NULL ) + { + while ( n_samples_out > 0 ) + { + n_samples_out_loop = min( hFdCngCom->frameSize, n_samples_out ); + if ( scale != 0 ) + { + /*Generate LF comfort noise only at first slot, for the whole frame*/ + ptr_level = cngNoiseLevel; + + /* Generate Gaussian random noise in real and imaginary parts of the FFT bins + Amplitudes are adjusted to the estimated noise level cngNoiseLevel in each bin */ + if ( hFdCngCom->startBand == 0 ) + { + rand_gauss( &fftBuffer[0], seed ); + ptr_r = fftBuffer + 2; + fftBuffer[0] *= (float) sqrt( scale * *ptr_level ); /* DC component in FFT */ + ptr_level++; + } + else + { + fftBuffer[0] = 0.f; + set_f( fftBuffer + 2, 0.0f, 2 * ( hFdCngCom->startBand - 1 ) ); + ptr_r = fftBuffer + 2 * hFdCngCom->startBand; + } + ptr_i = ptr_r + 1; + + for ( ; ptr_level < cngNoiseLevel + hFdCngCom->stopFFTbin - hFdCngCom->startBand; ptr_level++ ) + { + /* Real part in FFT bins */ + rand_gauss( ptr_r, seed ); + ( *ptr_r ) *= (float) sqrt( ( scale * *ptr_level ) * 0.5f ); + ptr_r += 2; + /* Imaginary part in FFT bins */ + rand_gauss( ptr_i, seed ); + ( *ptr_i ) *= (float) sqrt( ( scale * *ptr_level ) * 0.5f ); + ptr_i += 2; + } + + /* Remaining FFT bins are set to zero */ + set_f( fftBuffer + 2 * hFdCngCom->stopFFTbin, 0.0f, hFdCngCom->fftlen - 2 * hFdCngCom->stopFFTbin ); + /* Nyquist frequency is discarded */ + fftBuffer[1] = 0.f; + + /* Perform STFT synthesis */ + SynthesisSTFT_dirac( fftBuffer, tdBuffer + n_samples_start, hFdCngCom->olapBufferSynth2, hFdCngCom->olapWinSyn, n_samples_out_loop, hFdCngCom ); + +#ifdef DEBUG_MODE_DIRAC + { + int16_t tmp[1000]; + + for ( i = 0; i < hFdCngCom->frameSize; i++ ) + { + tmp[i] = (int16_t) ( tdBuffer[i] + 0.5f ); + } + dbgwrite( tmp, sizeof( int16_t ), hFdCngCom->frameSize, 1, "./res/ivas_dirac_cna_fft.pcm" ); + } +#endif + } + + else + { + /* very low level case - update random seeds */ + generate_masking_noise_update_seed( hFdCngCom ); + + set_f( fftBuffer, 0.f, hFdCngCom->fftlen ); + + /* Perform STFT synthesis */ + SynthesisSTFT_dirac( fftBuffer, tdBuffer + n_samples_start, hFdCngCom->olapBufferSynth2, hFdCngCom->olapWinSyn, n_samples_out_loop, hFdCngCom ); + +#ifdef DEBUG_MODE_DIRAC + { + int16_t tmp[1000]; + + for ( i = 0; i < hFdCngCom->frameSize; i++ ) + { + tmp[i] = (int16_t) ( tdBuffer[i] + 0.5f ); + } + dbgwrite( tmp, sizeof( int16_t ), hFdCngCom->frameSize, 1, "./res/ivas_dirac_cna_fft.pcm" ); + } +#endif + } + n_samples_out -= hFdCngCom->frameSize; + n_samples_start += hFdCngCom->frameSize; + } + } + + pop_wmops(); + + return; +} + +#endif + /*------------------------------------------------------------------- * generate_masking_noise_hf_cldfb() @@ -1817,10 +1973,12 @@ void generate_masking_noise_dirac( ) { int16_t i; +#ifndef JBM_TSM_ON_TCS float *cngNoiseLevel = hFdCngCom->cngNoiseLevel; float *fftBuffer = hFdCngCom->fftBuffer; float *ptr_r; float *ptr_i; +#endif float *ptr_level; int16_t *seed = &( hFdCngCom->seed ); float scale; @@ -1867,12 +2025,12 @@ void generate_masking_noise_dirac( scale *= hFdCngCom->likelihood_noisy_speech; } } - /* LB CLDFB - CNA from STFT: CNA applied only in channel 0*/ if ( cna_flag && tdBuffer != NULL ) { if ( scale != 0 ) { +#ifndef JBM_TSM_ON_TCS /*Generate LF comfort noise only at first slot, for the whole frame*/ if ( slot_index == 0 ) { @@ -1927,12 +2085,13 @@ void generate_masking_noise_dirac( } #endif } - +#endif /* LF CLDFB*/ cldfbAnalysis_ts( &( tdBuffer[hFdCngCom->numCoreBands * slot_index] ), Cldfb_RealBuffer, Cldfb_ImagBuffer, hFdCngCom->numCoreBands, h_cldfb ); } else { +#ifndef JBM_TSM_ON_TCS if ( slot_index == 0 ) { /* very low level case - update random seeds */ @@ -1955,7 +2114,7 @@ void generate_masking_noise_dirac( } #endif } - +#endif /* LB ana CLDFB*/ cldfbAnalysis_ts( &( tdBuffer[hFdCngCom->numCoreBands * slot_index] ), Cldfb_RealBuffer, Cldfb_ImagBuffer, hFdCngCom->numCoreBands, h_cldfb ); } diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 63372cd5ba498174fdd9b69d1e841bbb3afbeaa2..bfe0a4bb533681ebb76b93d73f03380014b20f97 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -59,7 +59,10 @@ static void ivas_binRenderer_filterModule( float out_Conv_CLDFB_imag[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : imag part of Binaural signals */ float CLDFB_real[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : real part of LS signals */ float CLDFB_imag[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : imag part of LS signals */ - BINAURAL_RENDERER_HANDLE hBinRenderer /* i/o: fastconv binaural renderer handle */ +#ifdef JBM_TSM_ON_TCS + const int16_t numTimeSlots, /* i : number of time slots to process */ +#endif + BINAURAL_RENDERER_HANDLE hBinRenderer /* i/o: fastconv binaural renderer handle */ ) { int16_t bandIdx, k, chIdx, tapIdx; @@ -78,7 +81,11 @@ static void ivas_binRenderer_filterModule( filterTapsRightRealPtr = hBinRenderer->hBinRenConvModule->filterTapsRightReal[bandIdx][chIdx]; filterTapsRightImagPtr = hBinRenderer->hBinRenConvModule->filterTapsRightImag[bandIdx][chIdx]; +#ifdef JBM_TSM_ON_TCS + for ( k = 0; k < numTimeSlots; k++ ) +#else for ( k = 0; k < MAX_PARAM_SPATIAL_SUBFRAMES; k++ ) +#endif { float outRealLeft = 0.0f, outRealRight = 0.0f, outImagLeft = 0.0f, outImagRight = 0.0f; @@ -857,9 +864,14 @@ void ivas_binRenderer_close( *-------------------------------------------------------------------------*/ void ivas_binaural_add_LFE( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - int16_t output_frame, /* i : length of input frame */ + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + int16_t output_frame, /* i : length of input frame */ +#ifdef JBM_TSM_ON_TCS + float *input_f[], /* i : transport channels */ + float *output_f[] /* o : synthesized core-coder transport channels/DirAC output */ +#else float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels/DirAC output */ +#endif ) { int16_t render_lfe, idx_lfe; @@ -886,10 +898,17 @@ void ivas_binaural_add_LFE( } for ( idx_lfe = 0; idx_lfe < st_ivas->hIntSetup.num_lfe; idx_lfe++ ) { +#ifdef JBM_TSM_ON_TCS + v_multc( input_f[st_ivas->hIntSetup.index_lfe[idx_lfe]], gain, input_f[st_ivas->hIntSetup.index_lfe[idx_lfe]], output_frame ); + /* copy LFE to left and right channels */ + v_add( output_f[0], input_f[st_ivas->hIntSetup.index_lfe[idx_lfe]], output_f[0], output_frame ); + v_add( output_f[1], input_f[st_ivas->hIntSetup.index_lfe[idx_lfe]], output_f[1], output_frame ); +#else v_multc( output_f[st_ivas->hIntSetup.index_lfe[idx_lfe]], gain, output_f[st_ivas->hIntSetup.index_lfe[idx_lfe]], output_frame ); /* copy LFE to left and right channels */ v_add( output_f[0], output_f[st_ivas->hIntSetup.index_lfe[idx_lfe]], output_f[0], output_frame ); v_add( output_f[1], output_f[st_ivas->hIntSetup.index_lfe[idx_lfe]], output_f[1], output_frame ); +#endif } } @@ -905,8 +924,12 @@ void ivas_binaural_add_LFE( *-------------------------------------------------------------------------*/ void ivas_binaural_cldfb( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ +#ifdef JBM_TSM_ON_TCS + float *output_f[] /* i/o: synthesized core-coder transport channels/DirAC output */ +#else float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels/DirAC output */ +#endif ) { float Cldfb_RealBuffer[MAX_INTERN_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; @@ -949,8 +972,11 @@ void ivas_binaural_cldfb( } /* Implement binaural rendering */ +#ifdef JBM_TSM_ON_TCS + ivas_binRenderer( st_ivas->hBinRenderer, st_ivas->hHeadTrackData, JBM_CLDFB_SLOTS_IN_SUBFRAME, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer ); +#else ivas_binRenderer( st_ivas->hBinRenderer, st_ivas->hHeadTrackData, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer ); - +#endif /* Implement CLDFB synthesis */ for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { @@ -971,6 +997,99 @@ void ivas_binaural_cldfb( return; } +#ifdef JBM_TSM_ON_TCS +/*-------------------------------------------------------------------------* + * ivas_binaural_cldfb() + * + * Perform CLDFB analysis, fastconv binaural rendering and CLDFB synthesis + *-------------------------------------------------------------------------*/ + +void ivas_binaural_cldfb_sf( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t n_samples_to_render, + float *output_f[] /* i/o: synthesized core-coder transport channels/DirAC output */ +) +{ + float Cldfb_RealBuffer[MAX_INTERN_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer[MAX_INTERN_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + int16_t slot_idx, subframeIdx, index_slot, idx_in, idx_lfe, maxBand, ch; + int16_t slot_size, slots_to_render, first_sf, last_sf; + int16_t slot_index_start, slot_index_start_cldfb; + + /* Implement a 5 msec loops */ + maxBand = (int16_t) ( ( CLDFB_NO_CHANNELS_MAX * st_ivas->hDecoderConfig->output_Fs ) / 48000 ); + slot_size = st_ivas->hTcBuffer->nb_subframes; + /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ + slots_to_render = min( st_ivas->hTcBuffer->num_slots - st_ivas->hTcBuffer->slots_rendered, n_samples_to_render / slot_size ); + first_sf = st_ivas->hTcBuffer->subframes_rendered; + last_sf = first_sf; + slot_index_start = st_ivas->hTcBuffer->slots_rendered; + slot_index_start_cldfb = 0; + st_ivas->hTcBuffer->slots_rendered += slots_to_render; + while ( slots_to_render > 0 ) + { + slots_to_render -= st_ivas->hTcBuffer->subframe_nbslots[last_sf]; + last_sf++; + } + for ( subframeIdx = first_sf; subframeIdx < last_sf; subframeIdx++ ) + { + for ( slot_idx = 0; slot_idx < st_ivas->hTcBuffer->subframe_nbslots[subframeIdx]; slot_idx++ ) + { + index_slot = slot_index_start + slot_idx; + + /* Implement CLDFB analysis */ + idx_in = 0; + idx_lfe = 0; + + for ( ch = 0; ch < ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ); ch++ ) + { + if ( ( st_ivas->hIntSetup.num_lfe > 0 ) && ( st_ivas->hIntSetup.index_lfe[idx_lfe] == ch ) ) + { + if ( idx_lfe < ( st_ivas->hIntSetup.num_lfe - 1 ) ) + { + idx_lfe++; + } + } + else + { + cldfbAnalysis_ts( &( st_ivas->hTcBuffer->tc[ch][maxBand * index_slot] ), + Cldfb_RealBuffer[idx_in][slot_idx], + Cldfb_ImagBuffer[idx_in][slot_idx], + maxBand, st_ivas->cldfbAnaDec[idx_in] ); + idx_in++; + } + } + } + + /* Implement binaural rendering */ +#ifdef JBM_TSM_ON_TCS + ivas_binRenderer( st_ivas->hBinRenderer, st_ivas->hHeadTrackData, st_ivas->hTcBuffer->subframe_nbslots[subframeIdx], Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer ); +#else + ivas_binRenderer( st_ivas->hBinRenderer, st_ivas->hHeadTrackData, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer ); +#endif + /* Implement CLDFB synthesis */ + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + float *RealBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; + float *ImagBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; + + for ( slot_idx = 0; slot_idx < st_ivas->hTcBuffer->subframe_nbslots[subframeIdx]; slot_idx++ ) + { + RealBuffer[slot_idx] = Cldfb_RealBuffer_Binaural[ch][slot_idx]; + ImagBuffer[slot_idx] = Cldfb_ImagBuffer_Binaural[ch][slot_idx]; + } + + cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][slot_index_start_cldfb * maxBand] ), maxBand * st_ivas->hTcBuffer->subframe_nbslots[subframeIdx], st_ivas->cldfbSynDec[ch] ); + } + slot_index_start += st_ivas->hTcBuffer->subframe_nbslots[subframeIdx]; + slot_index_start_cldfb += st_ivas->hTcBuffer->subframe_nbslots[subframeIdx]; + } + st_ivas->hTcBuffer->subframes_rendered = last_sf; + return; +} +#endif #endif @@ -981,8 +1100,11 @@ void ivas_binaural_cldfb( *-------------------------------------------------------------------------*/ void ivas_binRenderer( - BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: binaural renderer handle */ - HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i/o: head track handle */ + BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: binaural renderer handle */ + HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i/o: head track handle */ +#ifdef JBM_TSM_ON_TCS + const int16_t numTimeSlots, /* i : number of time slots to render*/ +#endif float Cldfb_RealBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */ float Cldfb_ImagBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */ float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ @@ -990,7 +1112,9 @@ void ivas_binRenderer( ) { int16_t chIdx, k; +#ifndef JBM_TSM_ON_TCS int16_t numTimeSlots = MAX_PARAM_SPATIAL_SUBFRAMES; +#endif push_wmops( "fastconv_binaural_rendering" ); @@ -1014,27 +1138,47 @@ void ivas_binRenderer( if ( hHeadTrackData->shd_rot_max_order == -1 ) { QuatToRotMat( hHeadTrackData->Quaternions[hHeadTrackData->num_quaternions++], hHeadTrackData->Rmat ); +#ifdef JBM_TSM_ON_TCS + rotateFrame_shd_cldfb( RealBuffer, ImagBuffer, hHeadTrackData->Rmat, hBinRenderer->hInputSetup->nchan_out_woLFE, numTimeSlots, 3 ); +#else rotateFrame_shd_cldfb( RealBuffer, ImagBuffer, hHeadTrackData->Rmat, hBinRenderer->hInputSetup->nchan_out_woLFE, 3 ); +#endif } else if ( hHeadTrackData->shd_rot_max_order > 0 ) { +#ifdef JBM_TSM_ON_TCS + rotateFrame_shd_cldfb( RealBuffer, ImagBuffer, hHeadTrackData->Rmat, hBinRenderer->hInputSetup->nchan_out_woLFE, numTimeSlots, hHeadTrackData->shd_rot_max_order ); +#else rotateFrame_shd_cldfb( RealBuffer, ImagBuffer, hHeadTrackData->Rmat, hBinRenderer->hInputSetup->nchan_out_woLFE, hHeadTrackData->shd_rot_max_order ); +#endif } } else { /* Rotation in SD (CICPx) */ +#ifdef JBM_TSM_ON_TCS + rotateFrame_sd_cldfb( hHeadTrackData, RealBuffer, ImagBuffer, hBinRenderer->hInputSetup, hBinRenderer->hEFAPdata, numTimeSlots, hBinRenderer->conv_band ); +#else rotateFrame_sd_cldfb( hHeadTrackData, RealBuffer, ImagBuffer, hBinRenderer->hInputSetup, hBinRenderer->hEFAPdata, hBinRenderer->conv_band ); +#endif } } /* HOA decoding to CICP19 if needed*/ if ( hBinRenderer->hInputSetup->is_loudspeaker_setup == 0 && hBinRenderer->nInChannels != 16 ) { +#ifdef JBM_TSM_ON_TCS + ivas_sba2mc_cldfb( *( hBinRenderer->hInputSetup ), RealBuffer, ImagBuffer, hBinRenderer->nInChannels, hBinRenderer->conv_band, numTimeSlots, hBinRenderer->hoa_dec_mtx ); +#else ivas_sba2mc_cldfb( *( hBinRenderer->hInputSetup ), RealBuffer, ImagBuffer, hBinRenderer->nInChannels, hBinRenderer->conv_band, hBinRenderer->hoa_dec_mtx ); +#endif } +#ifdef JBM_TSM_ON_TCS + ivas_binRenderer_filterModule( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, RealBuffer, ImagBuffer, numTimeSlots, hBinRenderer ); +#else ivas_binRenderer_filterModule( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, RealBuffer, ImagBuffer, hBinRenderer ); +#endif /* Obtain the binaural dmx and compute the reverb */ if ( hBinRenderer->hReverb != NULL ) @@ -1062,7 +1206,11 @@ void ivas_binRenderer( } #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS +#ifdef JBM_TSM_ON_TCS + ivas_binaural_reverb_processSubframe( hBinRenderer->hReverb, BINAURAL_CHANNELS, numTimeSlots, inRe, inIm, reverbRe, reverbIm ); +#else ivas_binaural_reverb_processSubframe( hBinRenderer->hReverb, BINAURAL_CHANNELS, inRe, inIm, reverbRe, reverbIm ); +#endif #else ivas_binaural_reverb_processFrame( hBinRenderer->hReverb, BINAURAL_CHANNELS, inRe, inIm, reverbRe, reverbIm, 0u ); #endif diff --git a/lib_dec/ivas_dec.c b/lib_dec/ivas_dec.c index b60be084f9797bb74b6e1f9124c1d126c1609cd0..62dab78ef5d7977c0a86c8a06c3c83c2730bf0aa 100644 --- a/lib_dec/ivas_dec.c +++ b/lib_dec/ivas_dec.c @@ -68,6 +68,9 @@ ivas_error ivas_dec( float pan_left, pan_right; #endif ivas_error error; +#ifdef JBM_TSM_ON_TCS + float *p_output[MAX_OUTPUT_CHANNELS]; +#endif error = IVAS_ERR_OK; @@ -83,7 +86,11 @@ ivas_error ivas_dec( if ( st_ivas->bfi == 0 ) { +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_dec_setup( st_ivas, NULL, NULL ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_dec_setup( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -100,6 +107,13 @@ ivas_error ivas_dec( output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); +#ifdef JBM_TSM_ON_TCS + for ( n = 0; n < MAX_OUTPUT_CHANNELS; n++ ) + { + p_output[n] = &output[n][0]; + } +#endif + /*----------------------------------------------------------------* * Decoding + Rendering *----------------------------------------------------------------*/ @@ -137,10 +151,18 @@ ivas_error ivas_dec( /* Rendering */ if ( st_ivas->renderer_type == RENDERER_MC ) { +#ifdef JBM_TSM_ON_TCS +#ifdef MC_PARAMUPMIX_MODE + ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, p_output, p_output ); +#else + ivas_ls_setup_conversion( st_ivas, output_frame, p_output, p_output ); +#endif +#else #ifdef MC_PARAMUPMIX_MODE ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, output ); #else ivas_ls_setup_conversion( st_ivas, output_frame, output ); +#endif #endif } } @@ -210,7 +232,11 @@ ivas_error ivas_dec( if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) { /* Convert CICP19 -> Ambisonics */ +#ifdef JBM_TSM_ON_TCS + ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, output_frame, st_ivas->hOutSetup.ambisonics_order, 0.f ); +#else ivas_mc2sba( st_ivas->hIntSetup, output, output_frame, st_ivas->hOutSetup.ambisonics_order, 0.f ); +#endif } } } @@ -233,7 +259,11 @@ ivas_error ivas_dec( else if ( st_ivas->renderer_type == RENDERER_TD_PANNING || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) { /* Convert to CICPxx; used also for ISM->CICP19->binaural_room rendering */ +#ifdef JBM_TSM_ON_TCS + ivas_ism_render( st_ivas, p_output, output_frame ); +#else ivas_ism_render( st_ivas, output, output_frame ); +#endif } #ifdef REND_DEBUGGING_REVISION #ifdef DEBUGGING @@ -246,29 +276,57 @@ ivas_error ivas_dec( #endif { /* Convert to Ambisonics; used also for ISM->HOA3->binaural rendering */ +#ifdef JBM_TSM_ON_TCS + ivas_ism2sba( p_output, st_ivas->hIsmRendererData, st_ivas->hIsmMetaData, st_ivas->nchan_ism, output_frame, st_ivas->hIntSetup.ambisonics_order ); +#else ivas_ism2sba( output, st_ivas->hIsmRendererData, st_ivas->hIsmMetaData, st_ivas->nchan_ism, output_frame, st_ivas->hIntSetup.ambisonics_order ); +#endif } /* Binaural rendering */ if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) { +#ifdef JBM_TSM_ON_TCS + if ( ( ivas_td_binaural_renderer( st_ivas, p_output, output_frame ) ) != IVAS_ERR_OK ) +#else if ( ( ivas_td_binaural_renderer( st_ivas, output, output_frame ) ) != IVAS_ERR_OK ) +#endif { return error; } } else if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) { - if ( ( error = ivas_rend_crendProcess( st_ivas->hCrendWrapper, AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_BINAURAL_ROOM, NULL, NULL, NULL, NULL, output, output_Fs ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_rend_crendProcess( st_ivas->hCrendWrapper, + AUDIO_CONFIG_7_1_4, + AUDIO_CONFIG_BINAURAL_ROOM, + NULL, + NULL, + NULL, + NULL, +#ifdef JBM_TSM_ON_TCS + p_output, +#else + output, +#endif + output_Fs ) ) != IVAS_ERR_OK ) { return error; } +#ifdef JBM_TSM_ON_TCS + ivas_binaural_add_LFE( st_ivas, output_frame, p_output, p_output ); +#else ivas_binaural_add_LFE( st_ivas, output_frame, output ); +#endif } #ifdef DEBUGGING else if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) { +#ifdef JBM_TSM_ON_TCS + ivas_binaural_cldfb( st_ivas, p_output ); +#else ivas_binaural_cldfb( st_ivas, output ); +#endif } #endif } @@ -364,6 +422,7 @@ ivas_error ivas_dec( /* Dump audio signal after core-decoding */ ivas_spar_dump_signal_wav( output_frame, NULL, output, st_ivas->nchan_transport, spar_foa_dec_wav[0], "core-decoding" ); #endif + /* TCs remapping */ nchan_remapped = st_ivas->nchan_transport; if ( st_ivas->sba_dirac_stereo_flag ) @@ -409,6 +468,12 @@ ivas_error ivas_dec( { ivas_sba_mix_matrix_determiner( st_ivas->hSpar, output, st_ivas->bfi, nchan_remapped, output_frame ); } +#ifdef JBM_TSM_ON_TCS + else if ( st_ivas->sba_mode == SBA_MODE_SPAR && st_ivas->renderer_type != RENDERER_DISABLE ) + { + ivas_spar_dec_agc_pca( st_ivas, output, output_frame ); + } +#endif } if ( st_ivas->ivas_format == MASA_FORMAT ) @@ -447,14 +512,22 @@ ivas_error ivas_dec( { if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC ) { +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_sba_linear_renderer( p_output, output_frame, nchan_remapped, output_config, st_ivas->hOutSetup, st_ivas->hoa_dec_mtx ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_sba_linear_renderer( output, output_frame, nchan_remapped, output_config, st_ivas->hOutSetup, st_ivas->hoa_dec_mtx ) ) != IVAS_ERR_OK ) +#endif { return error; } } else if ( st_ivas->renderer_type == RENDERER_DIRAC ) { +#ifdef JBM_TSM_ON_TCS + ivas_dirac_dec( st_ivas, output, nchan_remapped ); +#else ivas_dirac_dec( st_ivas, output, nchan_remapped, NULL, NULL, -1 ); +#endif } } else if ( !st_ivas->sba_dirac_stereo_flag && nchan_out != 1 ) @@ -492,39 +565,78 @@ ivas_error ivas_dec( if ( st_ivas->transport_config != st_ivas->intern_config && ( st_ivas->intern_config == AUDIO_CONFIG_FOA || st_ivas->intern_config == AUDIO_CONFIG_HOA2 || st_ivas->intern_config == AUDIO_CONFIG_HOA3 ) ) { +#ifdef JBM_TSM_ON_TCS + ivas_mc2sba( st_ivas->hTransSetup, p_output, p_output, output_frame, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE ); +#else ivas_mc2sba( st_ivas->hTransSetup, output, output_frame, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE ); +#endif } /* Rendering */ if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) { - if ( ( error = ivas_rend_crendProcess( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hHeadTrackData, &st_ivas->hIntSetup, st_ivas->hEFAPdata, output, output_Fs ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_rend_crendProcess( st_ivas->hCrendWrapper, + st_ivas->intern_config, + st_ivas->hOutSetup.output_config, + st_ivas->hDecoderConfig, + st_ivas->hHeadTrackData, + &st_ivas->hIntSetup, + st_ivas->hEFAPdata, +#ifdef JBM_TSM_ON_TCS + p_output, +#else + output, +#endif + output_Fs ) ) != IVAS_ERR_OK ) { return error; } +#ifdef JBM_TSM_ON_TCS + ivas_binaural_add_LFE( st_ivas, output_frame, p_output, p_output ); +#else ivas_binaural_add_LFE( st_ivas, output_frame, output ); +#endif } else if ( st_ivas->renderer_type == RENDERER_MC ) { +#ifdef JBM_TSM_ON_TCS +#ifdef MC_PARAMUPMIX_MODE + ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, p_output, p_output ); +#else + ivas_ls_setup_conversion( st_ivas, output_frame, p_output, p_output ); +#endif +#else #ifdef MC_PARAMUPMIX_MODE ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, output ); #else ivas_ls_setup_conversion( st_ivas, output_frame, output ); +#endif #endif } else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) { +#ifdef JBM_TSM_ON_TCS + ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, output_frame, st_ivas->hOutSetup.ambisonics_order, 0.f ); +#else ivas_mc2sba( st_ivas->hIntSetup, output, output_frame, st_ivas->hOutSetup.ambisonics_order, 0.f ); +#endif } else if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) { +#ifdef JBM_TSM_ON_TCS + if ( ( ivas_td_binaural_renderer( st_ivas, p_output, output_frame ) ) != IVAS_ERR_OK ) + { + return error; + } + ivas_binaural_add_LFE( st_ivas, output_frame, p_output, p_output ); +#else if ( ( ivas_td_binaural_renderer( st_ivas, output, output_frame ) ) != IVAS_ERR_OK ) { return error; } - ivas_binaural_add_LFE( st_ivas, output_frame, output ); +#endif } } #ifdef MC_PARAMUPMIX_MODE @@ -554,42 +666,72 @@ ivas_error ivas_dec( if ( st_ivas->transport_config != st_ivas->intern_config && ( st_ivas->intern_config == AUDIO_CONFIG_FOA || st_ivas->intern_config == AUDIO_CONFIG_HOA2 || st_ivas->intern_config == AUDIO_CONFIG_HOA3 ) ) { +#ifdef JBM_TSM_ON_TCS + ivas_mc2sba( st_ivas->hTransSetup, p_output, p_output, output_frame, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE ); +#else ivas_mc2sba( st_ivas->hTransSetup, output, output_frame, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE ); +#endif } /* Rendering */ if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) { +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_rend_crendProcess( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hHeadTrackData, &st_ivas->hIntSetup, st_ivas->hEFAPdata, p_output, output_Fs ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_rend_crendProcess( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hHeadTrackData, &st_ivas->hIntSetup, st_ivas->hEFAPdata, output, output_Fs ) ) != IVAS_ERR_OK ) +#endif { return error; } - +#ifdef JBM_TSM_ON_TCS + ivas_binaural_add_LFE( st_ivas, output_frame, p_output, p_output ); +#else ivas_binaural_add_LFE( st_ivas, output_frame, output ); +#endif } else if ( st_ivas->renderer_type == RENDERER_MC ) { if ( ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_MONO ) || ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO ) ) { +#ifdef JBM_TSM_ON_TCS + ivas_ls_setup_conversion( st_ivas, audioCfg2channels( AUDIO_CONFIG_5_1_2 ), output_frame, p_output, p_output ); +#else ivas_ls_setup_conversion( st_ivas, audioCfg2channels( AUDIO_CONFIG_5_1_2 ), output_frame, output ); +#endif } else { +#ifdef JBM_TSM_ON_TCS + ivas_ls_setup_conversion( st_ivas, MC_PARAMUPMIX_MAX_INPUT_CHANS, output_frame, p_output, p_output ); +#else ivas_ls_setup_conversion( st_ivas, MC_PARAMUPMIX_MAX_INPUT_CHANS, output_frame, output ); +#endif } } else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) { +#ifdef JBM_TSM_ON_TCS + ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, output_frame, st_ivas->hOutSetup.ambisonics_order, 0.f ); +#else ivas_mc2sba( st_ivas->hIntSetup, output, output_frame, st_ivas->hOutSetup.ambisonics_order, 0.f ); +#endif } else if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) { +#ifdef JBM_TSM_ON_TCS + if ( ( ivas_td_binaural_renderer( st_ivas, p_output, output_frame ) ) != IVAS_ERR_OK ) +#else if ( ( ivas_td_binaural_renderer( st_ivas, output, output_frame ) ) != IVAS_ERR_OK ) +#endif { return error; } - +#ifdef JBM_TSM_ON_TCS + ivas_binaural_add_LFE( st_ivas, output_frame, p_output, p_output ); +#else ivas_binaural_add_LFE( st_ivas, output_frame, output ); +#endif } } #endif @@ -622,15 +764,28 @@ ivas_error ivas_dec( /* Rendering */ if ( output_config == AUDIO_CONFIG_MONO || output_config == AUDIO_CONFIG_STEREO ) { +#ifdef JBM_TSM_ON_TCS +#ifdef MC_PARAMUPMIX_MODE + ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, p_output, p_output ); +#else + ivas_ls_setup_conversion( st_ivas, output_frame, p_output, p_output ); +#endif +#else #ifdef MC_PARAMUPMIX_MODE ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, output ); #else + ivas_ls_setup_conversion( st_ivas, output_frame, output ); +#endif #endif } else { +#ifdef JBM_TSM_ON_TCS + ivas_param_mc_dec( st_ivas, p_output ); +#else ivas_param_mc_dec( st_ivas, output ); +#endif } } else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) @@ -712,11 +867,19 @@ ivas_error ivas_dec( } else if ( st_ivas->renderer_type == RENDERER_DIRAC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) /* rendering to CICPxx and Ambisonics */ { +#ifdef JBM_TSM_ON_TCS + ivas_dirac_dec( st_ivas, output, st_ivas->nchan_transport ); +#else ivas_dirac_dec( st_ivas, output, st_ivas->nchan_transport, NULL, NULL, -1 ); +#endif if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) { +#ifdef JBM_TSM_ON_TCS + ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, output_frame, st_ivas->hOutSetup.ambisonics_order, 0.f ); +#else ivas_mc2sba( st_ivas->hIntSetup, output, output_frame, st_ivas->hOutSetup.ambisonics_order, 0.f ); +#endif } else if ( st_ivas->intern_config == AUDIO_CONFIG_5_1 && ( output_config == AUDIO_CONFIG_5_1_2 || output_config == AUDIO_CONFIG_5_1_4 || output_config == AUDIO_CONFIG_7_1 ) ) { @@ -739,14 +902,21 @@ ivas_error ivas_dec( * - compensation for saturation * - float to integer conversion *----------------------------------------------------------------*/ +#ifdef JBM_TSM_ON_TCS + ivas_limiter_dec( st_ivas->hLimiter, p_output, nchan_out, output_frame, st_ivas->BER_detect ); +#ifdef DEBUGGING + st_ivas->noClipping += +#endif + ivas_syn_output( p_output, output_frame, nchan_out, data ); +#else ivas_limiter_dec( st_ivas->hLimiter, output, nchan_out, output_frame, st_ivas->BER_detect ); #ifdef DEBUGGING st_ivas->noClipping += #endif ivas_syn_output( output, output_frame, nchan_out, data ); - +#endif /*----------------------------------------------------------------* * Common updates *----------------------------------------------------------------*/ diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c index 73c8dcf12e8fe3ebe947ee07845fcd8e8ab9db53..861b7da54545d30ba6ca1f56cc9fd47e39d4a9df 100644 --- a/lib_dec/ivas_dirac_dec.c +++ b/lib_dec/ivas_dirac_dec.c @@ -149,6 +149,7 @@ ivas_error ivas_dirac_dec_config( output_Fs = st_ivas->hDecoderConfig->output_Fs; ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + if ( flag_config == DIRAC_RECONFIGURE ) { hDirAC = st_ivas->hDirAC; @@ -169,7 +170,10 @@ ivas_error ivas_dirac_dec_config( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC Config\n" ) ); } nchan_transport_old = 0; - +#ifdef JBM_TSM_ON_TCS + hDirAC->hParamIsm = NULL; + hDirAC->hParamIsmRendering = NULL; +#endif st_ivas->hDirAC = hDirAC; } @@ -265,9 +269,18 @@ ivas_error ivas_dirac_dec_config( if ( flag_config == DIRAC_OPEN ) { hDirAC->slot_size = (int16_t) ( ( output_Fs / FRAMES_PER_SEC ) / CLDFB_NO_COL_MAX ); +#ifdef JBM_TSM_ON_TCS + set_s( hDirAC->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set_s( hDirAC->subframe_nbslots, JBM_CLDFB_SLOTS_IN_SUBFRAME, DEFAULT_JBM_SUBFRAMES_5MS ); + hDirAC->nb_subframes = DEFAULT_JBM_SUBFRAMES_5MS; + hDirAC->subframes_rendered = 0; + hDirAC->slots_rendered = 0; + hDirAC->num_slots = DEFAULT_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME; +#else hDirAC->subframe_nbslots = (int16_t) ( CLDFB_NO_COL_MAX * 5.f / 20.f + 0.5f ); hDirAC->nb_subframes = CLDFB_NO_COL_MAX / hDirAC->subframe_nbslots; assert( hDirAC->nb_subframes <= MAX_PARAM_SPATIAL_SUBFRAMES ); +#endif } #ifdef HODIRAC @@ -929,11 +942,31 @@ ivas_error ivas_dirac_dec_config( if ( st_ivas->mc_mode == MC_MODE_MCMASA ) { hDirAC->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES; +#ifdef JBM_TSM_ON_TCS + { + int16_t map_idx; + set_s( hDirAC->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); + for ( map_idx = 0; map_idx < DEFAULT_JBM_SUBFRAMES_5MS; map_idx++ ) + { + hDirAC->render_to_md_map[map_idx] = map_idx; + } + } +#endif } else if ( st_ivas->ivas_format == MASA_FORMAT ) { hDirAC->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR; hDirAC->dirac_bs_md_write_idx = DELAY_MASA_PARAM_DEC_SFR; +#ifdef JBM_TSM_ON_TCS + { + int16_t map_idx; + set_s( hDirAC->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); + for ( map_idx = 0; map_idx < DEFAULT_JBM_SUBFRAMES_5MS; map_idx++ ) + { + hDirAC->render_to_md_map[map_idx] = map_idx; + } + } +#endif } else { @@ -956,6 +989,16 @@ ivas_error ivas_dirac_dec_config( hDirAC->dirac_read_idx = 0; hDirAC->dirac_estimator_idx = 0; } +#ifdef JBM_TSM_ON_TCS + { + int16_t map_idx; + set_s( hDirAC->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); + for ( map_idx = 0; map_idx < DEFAULT_JBM_CLDFB_TIMESLOTS; map_idx++ ) + { + hDirAC->render_to_md_map[map_idx] = hDirAC->dirac_read_idx + map_idx * num_slots_in_subfr / JBM_CLDFB_SLOTS_IN_SUBFRAME; + } + } +#endif } if ( ( hDirAC->azimuth = (int16_t **) malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) @@ -1242,6 +1285,35 @@ ivas_error ivas_dirac_dec_config( } } #endif +#ifdef JBM_TSM_ON_TCS + /* allocate transport channels*/ + if ( flag_config == DIRAC_OPEN ) + { + if ( st_ivas->hDecoderConfig->voip_active == 1 && st_ivas->hTcBuffer == NULL ) + { + if ( st_ivas->sba_mode == SBA_MODE_DIRAC ) + { + int16_t nchan_to_allocate; + + nchan_to_allocate = nchan_transport; + if ( st_ivas->nchan_transport == 1 && ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) || ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) ) + { + nchan_to_allocate++; /* we need a channel for the CNG in this case*/ + } + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + nchan_to_allocate = 2 * BINAURAL_CHANNELS; + } + if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, TC_BUFFER_MODE_RENDERER, nchan_transport, nchan_to_allocate, nchan_to_allocate, hDirAC->slot_size ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + } + +#endif /* JBM_TMS_ON_TCS*/ + return error; } @@ -1810,7 +1882,6 @@ void ivas_dirac_dec_read_BS( { int16_t i, j, b, dir, orig_dirac_bands; int16_t next_bit_pos_orig; - *nb_bits = 0; if ( !st->bfi && ivas_total_brate > IVAS_SID_5k2 ) { @@ -2122,6 +2193,7 @@ void ivas_qmetadata_to_dirac( #endif num_slots_in_subfr = hDirAC->hConfig->dec_param_estim ? CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES : 1; + /* ungroup */ seed_ptr = &hDirAC->dithering_seed; nblocks = q_direction->cfg.nblocks; @@ -2200,12 +2272,52 @@ void ivas_qmetadata_to_dirac( { band_start = band_grouping[band]; band_end = band_grouping[band + 1]; +#ifdef JBM_TSM_ON_TCS + tmp_write_idx_param_band = hDirAC->dirac_bs_md_write_idx; + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) +#else for ( block = 0; block < hDirAC->nb_subframes; block++ ) +#endif { +#ifdef JBM_TSM_ON_TCS + ts_start = hDirAC->block_grouping[block]; + ts_end = hDirAC->block_grouping[block + 1]; +#endif for ( b = band_start; b < band_end; b++ ) { +#ifdef JBM_TSM_ON_TCS + tmp_write_idx_band = tmp_write_idx_param_band; +#endif hDirAC->spreadCoherence[block][b] = 0.0f; hDirAC->surroundingCoherence[block][b] = 0.0f; +#ifdef JBM_TSM_ON_TCS + if ( hDirAC->hConfig->dec_param_estim == FALSE ) + { + hDirAC->elevation[tmp_write_idx_band][b] = 0; + hDirAC->azimuth[tmp_write_idx_band][b] = 0; + hDirAC->diffuseness_vector[tmp_write_idx_band][b] = 0.f; + + hDirAC->spreadCoherence[tmp_write_idx_band][b] = 0.0f; + hDirAC->surroundingCoherence[tmp_write_idx_band][b] = 0.0f; + hDirAC->energy_ratio1[tmp_write_idx_band][b] = 0; + tmp_write_idx_band = ( tmp_write_idx_band + 1 ) % hDirAC->dirac_md_buffer_length; + } + else + { + for ( ts = ts_start; ts < ts_end; ts++ ) + { + hDirAC->elevation[tmp_write_idx_band][b] = 0; + hDirAC->azimuth[tmp_write_idx_band][b] = 0; +#if 0 + hDirAC->diffuseness_vector[tmp_write_idx_band][b] = 0.f; +#endif + hDirAC->spreadCoherence[tmp_write_idx_band][b] = 0.0f; + hDirAC->surroundingCoherence[tmp_write_idx_band][b] = 0.0f; + hDirAC->energy_ratio1[tmp_write_idx_band][b] = 0; + tmp_write_idx_band = ( tmp_write_idx_band + 1 ) % hDirAC->dirac_md_buffer_length; + } + } +#endif } } } @@ -2239,7 +2351,11 @@ void ivas_qmetadata_to_dirac( #endif diff_idx = q_direction->band_data[qBand_idx].energy_ratio_index[0]; +#ifdef JBM_TSM_ON_TCS + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) +#else for ( block = 0; block < hDirAC->nb_subframes; block++ ) +#endif { int16_t block_qmetadata; @@ -2386,7 +2502,11 @@ void ivas_qmetadata_to_dirac( for ( b = band_grouping[band]; b < hDirAC->num_freq_bands; b++ ) { tmp_write_idx_band = hDirAC->dirac_bs_md_write_idx; +#ifdef JBM_TSM_ON_TCS + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) +#else for ( block = 0; block < hDirAC->nb_subframes; block++ ) +#endif { ts_start = hDirAC->block_grouping[block]; ts_end = hDirAC->block_grouping[block + 1]; @@ -2400,6 +2520,11 @@ void ivas_qmetadata_to_dirac( hDirAC->elevation[tmp_write_idx_band][b] = 0; hDirAC->azimuth[tmp_write_idx_band][b] = 0; hDirAC->diffuseness_vector[tmp_write_idx_band][b] = 0.f; +#ifdef JBM_TSM_ON_TCS + hDirAC->spreadCoherence[tmp_write_idx_band][b] = 0.0f; + hDirAC->surroundingCoherence[tmp_write_idx_band][b] = 0.0f; + hDirAC->energy_ratio1[tmp_write_idx_band][b] = 0; +#endif tmp_write_idx_band = ( tmp_write_idx_band + 1 ) % hDirAC->dirac_md_buffer_length; } else @@ -2409,6 +2534,11 @@ void ivas_qmetadata_to_dirac( hDirAC->elevation[tmp_write_idx_band][b] = 0; hDirAC->azimuth[tmp_write_idx_band][b] = 0; hDirAC->diffuseness_vector[tmp_write_idx_band][b] = 0.f; +#ifdef JBM_TSM_ON_TCS + hDirAC->spreadCoherence[tmp_write_idx_band][b] = 0.0f; + hDirAC->surroundingCoherence[tmp_write_idx_band][b] = 0.0f; + hDirAC->energy_ratio1[tmp_write_idx_band][b] = 0; +#endif tmp_write_idx_band = ( tmp_write_idx_band + 1 ) % hDirAC->dirac_md_buffer_length; } } @@ -2462,19 +2592,222 @@ void ivas_qmetadata_to_dirac( } +#ifdef JBM_TSM_ON_TCS +/*------------------------------------------------------------------------- + * ivas_dirac_dec_set_md_map() + * + * Set metadata index mapping for DirAC + *------------------------------------------------------------------------*/ +void ivas_dirac_dec_set_md_map( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + int16_t nCldfbTs ) +{ + int16_t num_slots_in_subfr; + DIRAC_DEC_HANDLE hDirAC; + + hDirAC = st_ivas->hDirAC; +#ifdef DEBUGGING + assert( hDirAC ); +#endif + + /* adapt subframes */ + hDirAC->num_slots = nCldfbTs; + hDirAC->slots_rendered = 0; + if ( hDirAC->hParamIsm != NULL || hDirAC->hConfig->dec_param_estim == 0 ) + { + num_slots_in_subfr = CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; + } + else + { + num_slots_in_subfr = 1; + } + hDirAC->subframes_rendered = 0; + + ivas_jbm_dec_get_adapted_subframes( nCldfbTs, hDirAC->subframe_nbslots, &hDirAC->nb_subframes ); + + /* set mapping according to dirac_read_idx */ + + set_s( hDirAC->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); + + if ( hDirAC->hConfig == NULL || hDirAC->hConfig->dec_param_estim == 0 ) + { + ivas_jbm_dec_get_md_map( DEFAULT_JBM_CLDFB_TIMESLOTS, nCldfbTs, num_slots_in_subfr, 0, hDirAC->dirac_md_buffer_length, hDirAC->render_to_md_map ); + } + else + { + ivas_jbm_dec_get_md_map( DEFAULT_JBM_CLDFB_TIMESLOTS, nCldfbTs, num_slots_in_subfr, hDirAC->dirac_read_idx, hDirAC->dirac_md_buffer_length, hDirAC->render_to_md_map ); + } + + if ( hDirAC->hConfig == NULL || hDirAC->hConfig->dec_param_estim == 0 ) + { + float tmp; + int16_t sf_idx, slot_idx, slot_idx_abs; + slot_idx_abs = 0; + for ( sf_idx = 0; sf_idx < hDirAC->nb_subframes; sf_idx++ ) + { + tmp = 0.0f; + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[sf_idx]; slot_idx++ ) + { + tmp += (float) hDirAC->render_to_md_map[slot_idx_abs]; + slot_idx_abs++; + } + hDirAC->render_to_md_map[sf_idx] = ( (int16_t) roundf( tmp / (float) hDirAC->subframe_nbslots[sf_idx] ) + hDirAC->dirac_read_idx ) % hDirAC->dirac_md_buffer_length; + } + set_s( &hDirAC->render_to_md_map[hDirAC->nb_subframes], 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME - hDirAC->nb_subframes ); + } + + return; +} + /*------------------------------------------------------------------------- * ivas_dirac_dec() * * DirAC decoding process *------------------------------------------------------------------------*/ +void ivas_dirac_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ + const int16_t nchan_transport /* i : number of transport channels */ +) +{ + int16_t subframe_idx; + float *output_f_local[MAX_OUTPUT_CHANNELS]; + float cng_td_buffer[L_FRAME16k]; + int16_t nchan_out, n, n_samples_sf; + nchan_out = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; + + n_samples_sf = JBM_CLDFB_SLOTS_IN_SUBFRAME * st_ivas->hDirAC->slot_size; + + for ( n = 0; n < nchan_out; n++ ) + { + output_f_local[n] = &output_f[n][0]; + } + for ( n = 0; n < nchan_transport; n++ ) + { + st_ivas->hTcBuffer->tc[n] = output_f[n]; + } + if ( st_ivas->nchan_transport == 1 && st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->sba_mode != SBA_MODE_SPAR ) + { + Decoder_State *st = st_ivas->hSCE[0]->hCoreCoder[0]; + st_ivas->hTcBuffer->tc[nchan_transport] = &cng_td_buffer[0]; + generate_masking_noise_lb_dirac( st->hFdCngDec->hFdCngCom, st_ivas->hTcBuffer->tc[1], DEFAULT_JBM_CLDFB_TIMESLOTS, st->cna_dirac_flag && st->flag_cna ); + } + ivas_dirac_dec_set_md_map( st_ivas, DEFAULT_JBM_CLDFB_TIMESLOTS ); + for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ ) + { + ivas_dirac_dec_render_sf( st_ivas, output_f_local, nchan_transport, NULL, NULL ); + for ( n = 0; n < nchan_out; n++ ) + { + output_f_local[n] += n_samples_sf; + } + } + if ( st_ivas->hDirAC->hConfig->dec_param_estim == 1 ) + { + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_CLDFB_TIMESLOTS ) % st_ivas->hDirAC->dirac_md_buffer_length; + } + else + { + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % st_ivas->hDirAC->dirac_md_buffer_length; + } + for ( n = 0; n < nchan_transport; n++ ) + { + st_ivas->hTcBuffer->tc[n] = NULL; + } + if ( st_ivas->nchan_transport == 1 && st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->sba_mode != SBA_MODE_SPAR ) + { + st_ivas->hTcBuffer->tc[nchan_transport] = NULL; + } + + return; +} + +void ivas_dirac_dec_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const int16_t nchan_transport, /* i : number of transport channels */ + const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ + uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ + uint16_t *nSamplesAvailable, /* o : number of CLDFB slots still to render */ + float *output_f[] /* o : rendered time signal */ +) +{ + int16_t slots_to_render, first_sf, last_sf, subframe_idx; + uint16_t slot_size, n_samples_sf, ch, nchan_intern; + DIRAC_DEC_HANDLE hDirAC; + float *output_f_local[MAX_OUTPUT_CHANNELS]; + + hDirAC = st_ivas->hDirAC; + + nchan_intern = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; +#ifdef DEBUGGING + assert( hDirAC ); +#endif + for ( ch = 0; ch < nchan_intern; ch++ ) + { + output_f_local[ch] = output_f[ch]; + } + slot_size = NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); + /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ + slots_to_render = min( hDirAC->num_slots - hDirAC->slots_rendered, nSamplesAsked / slot_size ); + *nSamplesRendered = slots_to_render * slot_size; + first_sf = hDirAC->subframes_rendered; + last_sf = first_sf; + while ( slots_to_render > 0 ) + { + slots_to_render -= hDirAC->subframe_nbslots[last_sf]; + last_sf++; + } +#ifdef DEBUGGING + assert( slots_to_render == 0 ); +#endif + for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + { + ivas_dirac_dec_render_sf( st_ivas, output_f_local, nchan_transport, NULL, NULL ); + n_samples_sf = hDirAC->subframe_nbslots[subframe_idx] * st_ivas->hDirAC->slot_size; + for ( ch = 0; ch < nchan_intern; ch++ ) + { + output_f_local[ch] += n_samples_sf; + } + } + if ( hDirAC->slots_rendered == hDirAC->num_slots ) + { + if ( st_ivas->hDirAC->hConfig->dec_param_estim == 1 ) + { + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_CLDFB_TIMESLOTS ) % st_ivas->hDirAC->dirac_md_buffer_length; + } + else + { + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % st_ivas->hDirAC->dirac_md_buffer_length; + } + } + *nSamplesAvailable = ( hDirAC->num_slots - hDirAC->slots_rendered ) * slot_size; + return; +} +#endif +/*------------------------------------------------------------------------- + * ivas_dirac_dec() + * + * DirAC decoding process + *------------------------------------------------------------------------*/ +#ifndef JBM_TSM_ON_TCS void ivas_dirac_dec( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ +#else +void ivas_dirac_dec_render_sf( +#endif + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ +#ifdef JBM_TSM_ON_TCS + float *output_f[], /* i/o: synthesized core-coder transport channels/DirAC output */ +#else + float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ +#endif const int16_t nchan_transport, /* i : number of transport channels */ float *pppQMfFrame_ts_re[IVAS_MAX_FB_MIXER_IN_CH][CLDFB_NO_COL_MAX], - float *pppQMfFrame_ts_im[IVAS_MAX_FB_MIXER_IN_CH][CLDFB_NO_COL_MAX], - const int16_t i_sf ) + float *pppQMfFrame_ts_im[IVAS_MAX_FB_MIXER_IN_CH][CLDFB_NO_COL_MAX] +#ifndef JBM_TSM_ON_TCS + , + const int16_t i_sf +#endif +) { int16_t i, ch, idx_in, idx_lfe; DIRAC_DEC_HANDLE hDirAC; @@ -2482,9 +2815,14 @@ void ivas_dirac_dec( float surCohEner; float surCohRatio[CLDFB_NO_CHANNELS_MAX]; int16_t subframe_idx; +#ifndef JBM_TSM_ON_TCS int16_t sf1, sf2; +#endif int16_t slot_idx, index_slot; float *p_Rmat; +#ifdef JBM_TSM_ON_TCS + int16_t slot_idx_start, slot_idx_start_cldfb_synth, md_idx; +#endif /*CLDFB: last output channels reserved to LFT for CICPx*/ float Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; @@ -2493,12 +2831,23 @@ void ivas_dirac_dec( float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; int16_t index, num_freq_bands; +#ifdef JBM_TSM_ON_TCS + /* local copies of azi, ele, diffuseness */ + int16_t azimuth[JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + int16_t elevation[JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float diffuseness_vector[JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; +#endif + DIRAC_DEC_STACK_MEM DirAC_mem; float *reference_power, *reference_power_smooth; float *onset_filter, *onset_filter_subframe, *p_onset_filter = NULL; uint16_t coherence_flag; +#ifndef JBM_TSM_ON_TCS push_wmops( "ivas_dirac_dec" ); +#else + push_wmops( "ivas_dirac_dec_render" ); +#endif /* Initialize aux buffers */ hDirAC = st_ivas->hDirAC; @@ -2538,7 +2887,7 @@ void ivas_dirac_dec( #endif /* Subframe loop */ - +#ifndef JBM_TSM_ON_TCS if ( i_sf == -1 ) { sf1 = 0; @@ -2549,136 +2898,279 @@ void ivas_dirac_dec( sf1 = i_sf; sf2 = i_sf + 1; } +#endif +#ifdef JBM_TSM_ON_TCS + slot_idx_start = hDirAC->slots_rendered; + slot_idx_start_cldfb_synth = 0; +#endif +#ifdef JBM_TSM_ON_TCS + subframe_idx = hDirAC->subframes_rendered; +#else for ( subframe_idx = sf1; subframe_idx < sf2; subframe_idx++ ) { - if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) +#endif +#ifdef JBM_TSM_ON_TCS + if ( hDirAC->hConfig->dec_param_estim == FALSE ) + { + md_idx = hDirAC->render_to_md_map[subframe_idx]; + } + else + { + md_idx = hDirAC->render_to_md_map[slot_idx_start]; + } +#endif +#ifdef JBM_TSM_ON_TCS + /* Another workaround for self test BE */ + if ( st_ivas->hHeadTrackData && st_ivas->hDecoderConfig->voip_active == 0 ) + { + QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[st_ivas->hHeadTrackData->num_quaternions++], st_ivas->hHeadTrackData->Rmat ); + + p_Rmat = &st_ivas->hHeadTrackData->Rmat[0][0]; + + if ( st_ivas->hHeadTrackData->shd_rot_max_order == 0 ) { - set_zero( reference_power_smooth, hDirAC->num_freq_bands ); + num_freq_bands = hDirAC->band_grouping[hDirAC->hConfig->enc_param_start_band]; + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + index_slot = slot_idx_start + slot_idx; + rotateAziEle_DirAC( hDirAC->azimuth[index_slot], hDirAC->elevation[index_slot], num_freq_bands, hDirAC->num_freq_bands, p_Rmat ); + } } - else + } + else + { + p_Rmat = 0; + } + + /* copy parameters into local buffers*/ + + if ( hDirAC->hConfig->dec_param_estim == TRUE ) + { + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + mvs2s( hDirAC->azimuth[hDirAC->render_to_md_map[slot_idx + slot_idx_start]], azimuth[slot_idx], hDirAC->num_freq_bands ); + mvs2s( hDirAC->elevation[hDirAC->render_to_md_map[slot_idx + slot_idx_start]], elevation[slot_idx], hDirAC->num_freq_bands ); + mvr2r( hDirAC->diffuseness_vector[hDirAC->render_to_md_map[slot_idx + slot_idx_start]], diffuseness_vector[slot_idx], hDirAC->num_freq_bands ); + } + } + else + { + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) { - set_zero( onset_filter_subframe, hDirAC->num_freq_bands ); + mvs2s( hDirAC->azimuth[hDirAC->render_to_md_map[subframe_idx]], azimuth[slot_idx], hDirAC->num_freq_bands ); + mvs2s( hDirAC->elevation[hDirAC->render_to_md_map[subframe_idx]], elevation[slot_idx], hDirAC->num_freq_bands ); + mvr2r( hDirAC->diffuseness_vector[hDirAC->render_to_md_map[subframe_idx]], diffuseness_vector[slot_idx], hDirAC->num_freq_bands ); } + } + +#endif + + if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + { + set_zero( reference_power_smooth, hDirAC->num_freq_bands ); + } + else + { + set_zero( onset_filter_subframe, hDirAC->num_freq_bands ); + } +#ifdef JBM_TSM_ON_TCS + if ( st_ivas->hHeadTrackData && st_ivas->hDecoderConfig->voip_active == 1 ) +#else if ( st_ivas->hHeadTrackData ) - { - QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[st_ivas->hHeadTrackData->num_quaternions++], st_ivas->hHeadTrackData->Rmat ); +#endif + { + QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[st_ivas->hHeadTrackData->num_quaternions++], st_ivas->hHeadTrackData->Rmat ); - p_Rmat = &st_ivas->hHeadTrackData->Rmat[0][0]; + p_Rmat = &st_ivas->hHeadTrackData->Rmat[0][0]; - if ( st_ivas->hHeadTrackData->shd_rot_max_order == 0 ) - { - num_freq_bands = hDirAC->band_grouping[hDirAC->hConfig->enc_param_start_band]; + if ( st_ivas->hHeadTrackData->shd_rot_max_order == 0 ) + { + num_freq_bands = hDirAC->band_grouping[hDirAC->hConfig->enc_param_start_band]; +#ifdef JBM_TSM_ON_TCS + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) +#else for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots; slot_idx++ ) - { +#endif + { +#ifdef JBM_TSM_ON_TCS + rotateAziEle_DirAC( azimuth[slot_idx], elevation[slot_idx], num_freq_bands, hDirAC->num_freq_bands, p_Rmat ); + +#else + /* note, this seems wrong since it does not take the dirac read ptr into account */ index_slot = subframe_idx * hDirAC->subframe_nbslots + slot_idx; /* Todo: This access to azimuth & elevation may use wrong indices as access should probably be based on hDirAC->dirac_read_idx */ rotateAziEle_DirAC( hDirAC->azimuth[index_slot], hDirAC->elevation[index_slot], num_freq_bands, hDirAC->num_freq_bands, p_Rmat ); - } +#endif } } + } +#ifdef JBM_TSM_ON_TCS + else if ( !st_ivas->hHeadTrackData ) +#else else - { - p_Rmat = 0; - } +#endif + { + p_Rmat = 0; + } + + if ( hDirAC->hConfig->dec_param_estim == FALSE ) + { - if ( hDirAC->hConfig->dec_param_estim == FALSE ) + /* compute response */ + if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) { - /* compute response */ - if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) - { - ivas_dirac_dec_compute_power_factors( hDirAC->num_freq_bands, + ivas_dirac_dec_compute_power_factors( hDirAC->num_freq_bands, +#ifdef JBM_TSM_ON_TCS + diffuseness_vector[0], +#else hDirAC->diffuseness_vector[hDirAC->dirac_read_idx], - hDirAC->h_output_synthesis_psd_params.max_band_decorr, - hDirAC->h_output_synthesis_psd_state.direct_power_factor, - hDirAC->h_output_synthesis_psd_state.diffuse_power_factor ); +#endif + hDirAC->h_output_synthesis_psd_params.max_band_decorr, + hDirAC->h_output_synthesis_psd_state.direct_power_factor, + hDirAC->h_output_synthesis_psd_state.diffuse_power_factor ); - if ( coherence_flag ) + if ( coherence_flag ) + { + for ( i = 0; i < hDirAC->num_freq_bands; i++ ) { - for ( i = 0; i < hDirAC->num_freq_bands; i++ ) - { - dirEne = hDirAC->h_output_synthesis_psd_state.direct_power_factor[i]; + dirEne = hDirAC->h_output_synthesis_psd_state.direct_power_factor[i]; +#ifdef JBM_TSM_ON_TCS + surCohEner = hDirAC->h_output_synthesis_psd_state.diffuse_power_factor[i] * hDirAC->surroundingCoherence[md_idx][i]; +#else surCohEner = hDirAC->h_output_synthesis_psd_state.diffuse_power_factor[i] * hDirAC->surroundingCoherence[hDirAC->dirac_read_idx][i]; - hDirAC->h_output_synthesis_psd_state.diffuse_power_factor[i] -= surCohEner; - hDirAC->h_output_synthesis_psd_state.direct_power_factor[i] += surCohEner; +#endif + hDirAC->h_output_synthesis_psd_state.diffuse_power_factor[i] -= surCohEner; + hDirAC->h_output_synthesis_psd_state.direct_power_factor[i] += surCohEner; - surCohRatio[i] = surCohEner / ( 1e-12f + dirEne + surCohEner ); - } - } - else - { - set_zero( surCohRatio, hDirAC->num_freq_bands ); + surCohRatio[i] = surCohEner / ( 1e-12f + dirEne + surCohEner ); } } else { - ivas_dirac_dec_compute_gain_factors( hDirAC->num_freq_bands, + set_zero( surCohRatio, hDirAC->num_freq_bands ); + } + } + else + { + ivas_dirac_dec_compute_gain_factors( hDirAC->num_freq_bands, +#ifdef JBM_TSM_ON_TCS + hDirAC->diffuseness_vector[md_idx], +#else hDirAC->diffuseness_vector[hDirAC->dirac_read_idx], - hDirAC->h_output_synthesis_psd_params.max_band_decorr, - hDirAC->h_output_synthesis_psd_state.direct_power_factor, - hDirAC->h_output_synthesis_psd_state.diffuse_power_factor ); +#endif + hDirAC->h_output_synthesis_psd_params.max_band_decorr, + hDirAC->h_output_synthesis_psd_state.direct_power_factor, + hDirAC->h_output_synthesis_psd_state.diffuse_power_factor ); - if ( coherence_flag ) + if ( coherence_flag ) + { + for ( i = 0; i < hDirAC->num_freq_bands; i++ ) { - for ( i = 0; i < hDirAC->num_freq_bands; i++ ) - { +#ifdef JBM_TSM_ON_TCS + surCohRatio[i] = hDirAC->surroundingCoherence[md_idx][i]; +#else surCohRatio[i] = hDirAC->surroundingCoherence[hDirAC->dirac_read_idx][i]; - } - } - else - { - set_zero( surCohRatio, hDirAC->num_freq_bands ); +#endif } } - - if ( st_ivas->hDecoderConfig->Opt_Headrotation && st_ivas->hHeadTrackData->shd_rot_max_order == 1 ) + else { - ivas_dirac_dec_compute_directional_responses( hDirAC, - st_ivas->hVBAPdata, - st_ivas->hMasa, - surCohRatio, - st_ivas->hHeadTrackData->shd_rot_max_order, - p_Rmat + set_zero( surCohRatio, hDirAC->num_freq_bands ); + } + } + + + if ( st_ivas->hDecoderConfig->Opt_Headrotation && st_ivas->hHeadTrackData->shd_rot_max_order == 1 ) + { + ivas_dirac_dec_compute_directional_responses( hDirAC, + st_ivas->hVBAPdata, + st_ivas->hMasa, +#ifdef JBM_TSM_ON_TCS + hDirAC->azimuth[md_idx], + hDirAC->elevation[md_idx], + md_idx, +#endif + surCohRatio, + st_ivas->hHeadTrackData->shd_rot_max_order, + p_Rmat #ifdef HODIRAC - , - st_ivas->sba_analysis_order > 1 && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_256k + , + st_ivas->sba_analysis_order > 1 && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_256k #endif - ); - } - else - { - ivas_dirac_dec_compute_directional_responses( hDirAC, - st_ivas->hVBAPdata, - st_ivas->hMasa, - surCohRatio, - 0, - 0 + ); + } + else + { + ivas_dirac_dec_compute_directional_responses( hDirAC, + st_ivas->hVBAPdata, + st_ivas->hMasa, +#ifdef JBM_TSM_ON_TCS + hDirAC->azimuth[md_idx], + hDirAC->elevation[md_idx], + md_idx, +#endif + surCohRatio, + 0, + NULL #ifdef HODIRAC - , - st_ivas->sba_analysis_order > 1 && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_256k + , + st_ivas->sba_analysis_order > 1 && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_256k #endif - ); - } + ); } + } + +#ifdef JBM_TSM_ON_TCS + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) +#else for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots; slot_idx++ ) +#endif + { +#ifdef JBM_TSM_ON_TCS + index_slot = slot_idx_start + slot_idx; + if ( hDirAC->hConfig->dec_param_estim == TRUE ) { + md_idx = hDirAC->render_to_md_map[index_slot]; + } + else + { + md_idx = hDirAC->render_to_md_map[subframe_idx]; + } +#else index_slot = subframe_idx * hDirAC->subframe_nbslots + slot_idx; +#endif - if ( st_ivas->sba_mode == SBA_MODE_SPAR ) + if ( st_ivas->sba_mode == SBA_MODE_SPAR ) + { + for ( ch = 0; ch < nchan_transport; ch++ ) { - for ( ch = 0; ch < nchan_transport; ch++ ) - { - mvr2r( pppQMfFrame_ts_re[ch][slot_idx], Cldfb_RealBuffer[ch][0], hDirAC->num_freq_bands ); - mvr2r( pppQMfFrame_ts_im[ch][slot_idx], Cldfb_ImagBuffer[ch][0], hDirAC->num_freq_bands ); - } + mvr2r( pppQMfFrame_ts_re[ch][slot_idx], Cldfb_RealBuffer[ch][0], hDirAC->num_freq_bands ); + mvr2r( pppQMfFrame_ts_im[ch][slot_idx], Cldfb_ImagBuffer[ch][0], hDirAC->num_freq_bands ); } - else + } + else + { + /* CLDFB Analysis*/ + for ( ch = 0; ch < nchan_transport; ch++ ) { - /* CLDFB Analysis*/ - for ( ch = 0; ch < nchan_transport; ch++ ) - { +#ifdef JBM_TSM_ON_TCS +#ifdef SPAR_TUNING + cldfbAnalysis_ts( &( st_ivas->hTcBuffer->tc[hDirAC->sba_map_tc[ch]][hDirAC->num_freq_bands * index_slot] ), + Cldfb_RealBuffer[ch][0], + Cldfb_ImagBuffer[ch][0], + hDirAC->num_freq_bands, + st_ivas->cldfbAnaDec[ch] ); +#else + cldfbAnalysis_ts( &( st_ivas->hTcBuffer->tc[sba_map_tc[ch]][hDirAC->num_freq_bands * index_slot] ), + Cldfb_RealBuffer[ch][0], + Cldfb_ImagBuffer[ch][0], + hDirAC->num_freq_bands, + st_ivas->cldfbAnaDec[ch] ); +#endif +#else #ifdef SPAR_TUNING cldfbAnalysis_ts( &( output_f[hDirAC->sba_map_tc[ch]][hDirAC->num_freq_bands * index_slot] ), Cldfb_RealBuffer[ch][0], @@ -2691,290 +3183,358 @@ void ivas_dirac_dec( Cldfb_ImagBuffer[ch][0], hDirAC->num_freq_bands, st_ivas->cldfbAnaDec[ch] ); + +#endif #endif - } } + } - /* CNG in DirAC, extra CLDFB ana for CNA*/ - if ( st_ivas->nchan_transport == 1 && st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->sba_mode != SBA_MODE_SPAR ) - { - Decoder_State *st = st_ivas->hSCE[0]->hCoreCoder[0]; + /* CNG in DirAC, extra CLDFB ana for CNA*/ + if ( st_ivas->nchan_transport == 1 && st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->sba_mode != SBA_MODE_SPAR ) + { + Decoder_State *st = st_ivas->hSCE[0]->hCoreCoder[0]; - generate_masking_noise_dirac( st->hFdCngDec->hFdCngCom, - st_ivas->cldfbAnaDec[1], + generate_masking_noise_dirac( st->hFdCngDec->hFdCngCom, + st_ivas->cldfbAnaDec[1], +#ifdef JBM_TSM_ON_TCS + st_ivas->hTcBuffer->tc[1], +#else &( output_f[1][L_FRAME48k - L_FRAME16k] ), - Cldfb_RealBuffer[1][0], - Cldfb_ImagBuffer[1][0], - index_slot, - st->cna_dirac_flag && st->flag_cna, - ( st->core_brate == FRAME_NO_DATA || st->core_brate == SID_2k40 ) && st->cng_type == FD_CNG && st->cng_sba_flag ); - } - - /* LFE synthesis */ - if ( st_ivas->mc_mode == MC_MODE_MCMASA && !hDirAC->hOutSetup.separateChannelEnabled && !( hDirAC->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM && hDirAC->hOutSetup.num_lfe == 0 ) ) - { - ivas_lfe_synth_with_cldfb( st_ivas->hMasa->hMasaLfeSynth, - Cldfb_RealBuffer, Cldfb_ImagBuffer, - Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS - 1], Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS - 1], - slot_idx, +#endif + Cldfb_RealBuffer[1][0], + Cldfb_ImagBuffer[1][0], + index_slot, + st->cna_dirac_flag && st->flag_cna, + ( st->core_brate == FRAME_NO_DATA || st->core_brate == SID_2k40 ) && st->cng_type == FD_CNG && st->cng_sba_flag ); + } + + /* LFE synthesis */ + if ( st_ivas->mc_mode == MC_MODE_MCMASA && !hDirAC->hOutSetup.separateChannelEnabled && !( hDirAC->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM && hDirAC->hOutSetup.num_lfe == 0 ) ) + { + ivas_lfe_synth_with_cldfb( st_ivas->hMasa->hMasaLfeSynth, + Cldfb_RealBuffer, Cldfb_ImagBuffer, + Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS - 1], Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS - 1], + slot_idx, +#ifdef JBM_TSM_ON_TCS + md_idx, +#else subframe_idx, - nchan_transport ); - } +#endif + nchan_transport ); + } - /*-----------------------------------------------------------------* - * protoype signal computation - *-----------------------------------------------------------------*/ + /*-----------------------------------------------------------------* + * protoype signal computation + *-----------------------------------------------------------------*/ - if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + if ( st_ivas->hDecoderConfig->Opt_Headrotation && st_ivas->hHeadTrackData->shd_rot_max_order == 0 ) { - if ( st_ivas->hDecoderConfig->Opt_Headrotation && st_ivas->hHeadTrackData->shd_rot_max_order == 0 ) - { - protoSignalComputation_shd( Cldfb_RealBuffer, Cldfb_ImagBuffer, - hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, - hDirAC->h_output_synthesis_psd_state.proto_diffuse_buffer_f, - reference_power, slot_idx, nchan_transport, - hDirAC->num_outputs_diff, - hDirAC->num_freq_bands, - p_Rmat ); - } - else - { - protoSignalComputation_shd( Cldfb_RealBuffer, Cldfb_ImagBuffer, - hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, - hDirAC->h_output_synthesis_psd_state.proto_diffuse_buffer_f, - reference_power, slot_idx, nchan_transport, - hDirAC->num_outputs_diff, - hDirAC->num_freq_bands, - 0 ); - } + protoSignalComputation_shd( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, + hDirAC->h_output_synthesis_psd_state.proto_diffuse_buffer_f, + reference_power, slot_idx, nchan_transport, + hDirAC->num_outputs_diff, + hDirAC->num_freq_bands, + p_Rmat ); } - else if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) + else { - protoSignalComputation2( Cldfb_RealBuffer, Cldfb_ImagBuffer, hDirAC->proto_frame_f, - hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, - reference_power, hDirAC->h_output_synthesis_psd_state.proto_power_smooth, - 0, slot_idx, hDirAC->num_freq_bands, hDirAC->masa_stereo_type_detect ); + protoSignalComputation_shd( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, + hDirAC->h_output_synthesis_psd_state.proto_diffuse_buffer_f, + reference_power, slot_idx, nchan_transport, + hDirAC->num_outputs_diff, + hDirAC->num_freq_bands, + 0 ); } - else + } + else if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) + { + protoSignalComputation2( Cldfb_RealBuffer, Cldfb_ImagBuffer, hDirAC->proto_frame_f, + hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, + reference_power, hDirAC->h_output_synthesis_psd_state.proto_power_smooth, + 0, slot_idx, hDirAC->num_freq_bands, hDirAC->masa_stereo_type_detect ); + } + else + { + switch ( nchan_transport ) { - switch ( nchan_transport ) - { #ifdef HODIRAC - case 11: + case 11: #endif - case 8: - case 6: - case 4: - protoSignalComputation4( Cldfb_RealBuffer, Cldfb_ImagBuffer, - hDirAC->proto_frame_f, - hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, - reference_power, - hDirAC->h_output_synthesis_psd_state.proto_power_smooth, - slot_idx, hDirAC->num_outputs_diff, - hDirAC->num_freq_bands, - hDirAC->hoa_decoder, - nchan_transport + case 8: + case 6: + case 4: + protoSignalComputation4( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirAC->proto_frame_f, + hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, + reference_power, + hDirAC->h_output_synthesis_psd_state.proto_power_smooth, + slot_idx, hDirAC->num_outputs_diff, + hDirAC->num_freq_bands, + hDirAC->hoa_decoder, + nchan_transport #ifdef SPAR_TUNING - , - hDirAC->sba_map_tc + , + hDirAC->sba_map_tc #endif - ); - break; - case 2: - protoSignalComputation2( Cldfb_RealBuffer, Cldfb_ImagBuffer, - hDirAC->proto_frame_f, - hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, - reference_power, - hDirAC->h_output_synthesis_psd_state.proto_power_smooth, - hDirAC->hOutSetup.is_loudspeaker_setup, - slot_idx, - hDirAC->num_freq_bands, - hDirAC->masa_stereo_type_detect ); - break; - case 1: - protoSignalComputation1( Cldfb_RealBuffer, Cldfb_ImagBuffer, - hDirAC->proto_frame_f, - hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, - reference_power, - hDirAC->h_output_synthesis_psd_state.proto_power_smooth, - slot_idx, - hDirAC->num_protos_diff, - hDirAC->num_freq_bands ); - break; - default: - return; - } + ); + break; + case 2: + protoSignalComputation2( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirAC->proto_frame_f, + hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, + reference_power, + hDirAC->h_output_synthesis_psd_state.proto_power_smooth, + hDirAC->hOutSetup.is_loudspeaker_setup, + slot_idx, + hDirAC->num_freq_bands, + hDirAC->masa_stereo_type_detect ); + break; + case 1: + protoSignalComputation1( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirAC->proto_frame_f, + hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f, + reference_power, + hDirAC->h_output_synthesis_psd_state.proto_power_smooth, + slot_idx, + hDirAC->num_protos_diff, + hDirAC->num_freq_bands ); + break; + default: + return; } + } - /*-----------------------------------------------------------------* - * Compute DirAC parameters at decoder side - *-----------------------------------------------------------------*/ - if ( hDirAC->hConfig->dec_param_estim == TRUE ) - { - hDirAC->index_buffer_intensity = ( hDirAC->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */ + /*-----------------------------------------------------------------* + * Compute DirAC parameters at decoder side + *-----------------------------------------------------------------*/ - index = hDirAC->index_buffer_intensity; + if ( hDirAC->hConfig->dec_param_estim == TRUE ) + { + hDirAC->index_buffer_intensity = ( hDirAC->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */ - num_freq_bands = hDirAC->band_grouping[hDirAC->hConfig->enc_param_start_band]; + index = hDirAC->index_buffer_intensity; - computeIntensityVector_dec( Cldfb_RealBuffer, - Cldfb_ImagBuffer, - num_freq_bands, - hDirAC->buffer_intensity_real[0][index - 1], - hDirAC->buffer_intensity_real[1][index - 1], - hDirAC->buffer_intensity_real[2][index - 1] ); + num_freq_bands = hDirAC->band_grouping[hDirAC->hConfig->enc_param_start_band]; - computeDirectionAngles( hDirAC->buffer_intensity_real[0][index - 1], - hDirAC->buffer_intensity_real[1][index - 1], - hDirAC->buffer_intensity_real[2][index - 1], + computeIntensityVector_dec( Cldfb_RealBuffer, + Cldfb_ImagBuffer, num_freq_bands, + hDirAC->buffer_intensity_real[0][index - 1], + hDirAC->buffer_intensity_real[1][index - 1], + hDirAC->buffer_intensity_real[2][index - 1] ); + computeDirectionAngles( hDirAC->buffer_intensity_real[0][index - 1], + hDirAC->buffer_intensity_real[1][index - 1], + hDirAC->buffer_intensity_real[2][index - 1], + num_freq_bands, +#ifdef JBM_TSM_ON_TCS + azimuth[slot_idx], + elevation[slot_idx] +#else hDirAC->azimuth[hDirAC->dirac_estimator_idx], - hDirAC->elevation[hDirAC->dirac_estimator_idx] ); + hDirAC->elevation[hDirAC->dirac_estimator_idx] +#endif + ); - mvr2r( reference_power, &( hDirAC->buffer_energy[( index - 1 ) * num_freq_bands] ), num_freq_bands ); + mvr2r( reference_power, &( hDirAC->buffer_energy[( index - 1 ) * num_freq_bands] ), num_freq_bands ); - computeDiffuseness( hDirAC->buffer_intensity_real, - hDirAC->buffer_energy, - num_freq_bands, - hDirAC->diffuseness_vector[hDirAC->dirac_estimator_idx] ); + computeDiffuseness( hDirAC->buffer_intensity_real, + hDirAC->buffer_energy, + num_freq_bands, +#ifdef JBM_TSM_ON_TCS + diffuseness_vector[slot_idx] +#else + hDirAC->diffuseness_vector[hDirAC->dirac_estimator_idx] +#endif + ); - hDirAC->dirac_estimator_idx = ( hDirAC->dirac_estimator_idx + 1 ) % hDirAC->dirac_md_buffer_length; - } +#ifndef JBM_TSM_ON_TCS + hDirAC->dirac_estimator_idx = ( hDirAC->dirac_estimator_idx + 1 ) % hDirAC->dirac_md_buffer_length; +#endif + } #ifdef DEBUG_MODE_DIRAC - { - static FILE *fp_direction_vector = NULL, *fp_diffuseness = NULL, *fp_referencePower = NULL; + { + static FILE *fp_direction_vector = NULL, *fp_diffuseness = NULL, *fp_referencePower = NULL; - if ( fp_direction_vector == NULL ) - fp_direction_vector = fopen( "./res/dbg_direction_vector_C_dec.bin", "wb" ); - if ( fp_diffuseness == NULL ) - fp_diffuseness = fopen( "./res/dbg_diffuseness_C_dec.bin", "wb" ); - if ( fp_referencePower == NULL ) - fp_referencePower = fopen( "./res/dbg_reference_power_C_dec.bin", "wb" ); + if ( fp_direction_vector == NULL ) + fp_direction_vector = fopen( "./res/dbg_direction_vector_C_dec.bin", "wb" ); + if ( fp_diffuseness == NULL ) + fp_diffuseness = fopen( "./res/dbg_diffuseness_C_dec.bin", "wb" ); + if ( fp_referencePower == NULL ) + fp_referencePower = fopen( "./res/dbg_reference_power_C_dec.bin", "wb" ); - for ( i = 0; i < hDirAC->num_freq_bands; i++ ) - { - float radius_length; - float dv[3]; + for ( i = 0; i < hDirAC->num_freq_bands; i++ ) + { + float radius_length; + float dv[3]; - if ( hDirAC->hConfig->dec_param_estim == FALSE ) - { - radius_length = cos( hDirAC->elevation[subframe_idx][i] * PI_OVER_180 ); - dv[0] = radius_length * cos( hDirAC->azimuth[subframe_idx][i] * PI_OVER_180 ); - dv[1] = radius_length * sin( hDirAC->azimuth[subframe_idx][i] * PI_OVER_180 ); - dv[2] = sin( hDirAC->elevation[subframe_idx][i] * PI_OVER_180 ); - - fwrite( dv, sizeof( float ), 3, fp_direction_vector ); - fwrite( &( hDirAC->diffuseness_vector[0][i] ), sizeof( float ), 1, fp_diffuseness ); - if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) - { - reference_power[i] = Cldfb_RealBuffer[0][0][i] * Cldfb_RealBuffer[0][0][i] + Cldfb_ImagBuffer[0][0][i] * Cldfb_ImagBuffer[0][0][i]; - } - fwrite( &( reference_power[i] ), sizeof( float ), 1, fp_referencePower ); - } - else + if ( hDirAC->hConfig->dec_param_estim == FALSE ) + { + radius_length = cos( hDirAC->elevation[subframe_idx][i] * PI_OVER_180 ); + dv[0] = radius_length * cos( hDirAC->azimuth[subframe_idx][i] * PI_OVER_180 ); + dv[1] = radius_length * sin( hDirAC->azimuth[subframe_idx][i] * PI_OVER_180 ); + dv[2] = sin( hDirAC->elevation[subframe_idx][i] * PI_OVER_180 ); + + fwrite( dv, sizeof( float ), 3, fp_direction_vector ); + fwrite( &( hDirAC->diffuseness_vector[0][i] ), sizeof( float ), 1, fp_diffuseness ); + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { - radius_length = cos( hDirAC->elevation[index_slot][i] * PI_OVER_180 ); - dv[0] = radius_length * cos( hDirAC->azimuth[index_slot][i] * PI_OVER_180 ); - dv[1] = radius_length * sin( hDirAC->azimuth[index_slot][i] * PI_OVER_180 ); - dv[2] = sin( hDirAC->elevation[index_slot][i] * PI_OVER_180 ); - - fwrite( dv, sizeof( float ), 3, fp_direction_vector ); - fwrite( &( hDirAC->diffuseness_vector[index_slot][i] ), sizeof( float ), 1, fp_diffuseness ); - fwrite( &( reference_power[i] ), sizeof( float ), 1, fp_referencePower ); + reference_power[i] = Cldfb_RealBuffer[0][0][i] * Cldfb_RealBuffer[0][0][i] + Cldfb_ImagBuffer[0][0][i] * Cldfb_ImagBuffer[0][0][i]; } + fwrite( &( reference_power[i] ), sizeof( float ), 1, fp_referencePower ); + } + else + { + radius_length = cos( hDirAC->elevation[index_slot][i] * PI_OVER_180 ); + dv[0] = radius_length * cos( hDirAC->azimuth[index_slot][i] * PI_OVER_180 ); + dv[1] = radius_length * sin( hDirAC->azimuth[index_slot][i] * PI_OVER_180 ); + dv[2] = sin( hDirAC->elevation[index_slot][i] * PI_OVER_180 ); + + fwrite( dv, sizeof( float ), 3, fp_direction_vector ); + fwrite( &( hDirAC->diffuseness_vector[index_slot][i] ), sizeof( float ), 1, fp_diffuseness ); + fwrite( &( reference_power[i] ), sizeof( float ), 1, fp_referencePower ); } } + } #endif - /*-----------------------------------------------------------------* - * frequency domain decorrelation - *-----------------------------------------------------------------*/ + /*-----------------------------------------------------------------* + * frequency domain decorrelation + *-----------------------------------------------------------------*/ - if ( hDirAC->proto_signal_decorr_on == 1 ) + if ( hDirAC->proto_signal_decorr_on == 1 ) + { + /* decorrelate prototype frame */ + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { - /* decorrelate prototype frame */ - if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) - { - ivas_dirac_dec_decorr_process( hDirAC->num_freq_bands, - hDirAC->num_outputs_diff, - hDirAC->num_protos_diff, - hDirAC->synthesisConf, - nchan_transport, - hDirAC->h_output_synthesis_psd_state.proto_diffuse_buffer_f + slot_idx * 2 * hDirAC->num_freq_bands * hDirAC->num_outputs_diff, - hDirAC->num_protos_diff, - hDirAC->proto_index_diff, - hDirAC->h_output_synthesis_psd_state.proto_diffuse_buffer_f + slot_idx * 2 * hDirAC->num_freq_bands * hDirAC->num_outputs_diff + 2 * hDirAC->num_freq_bands * min( 4, nchan_transport ), - onset_filter, - hDirAC->h_freq_domain_decorr_ap_params, - hDirAC->h_freq_domain_decorr_ap_state ); - - v_multc( onset_filter, 0.25f, onset_filter, hDirAC->num_freq_bands ); - v_add( onset_filter, onset_filter_subframe, onset_filter_subframe, hDirAC->num_freq_bands ); - p_onset_filter = onset_filter_subframe; - } - else - { - ivas_dirac_dec_decorr_process( hDirAC->num_freq_bands, - hDirAC->num_outputs_diff, - hDirAC->num_protos_diff, - hDirAC->synthesisConf, - nchan_transport, - hDirAC->proto_frame_f, - hDirAC->num_protos_diff, - hDirAC->proto_index_diff, - DirAC_mem.frame_dec_f, - onset_filter, - hDirAC->h_freq_domain_decorr_ap_params, - hDirAC->h_freq_domain_decorr_ap_state ); - - hDirAC->proto_frame_dec_f = DirAC_mem.frame_dec_f; - p_onset_filter = onset_filter; - } + ivas_dirac_dec_decorr_process( hDirAC->num_freq_bands, + hDirAC->num_outputs_diff, + hDirAC->num_protos_diff, + hDirAC->synthesisConf, + nchan_transport, + hDirAC->h_output_synthesis_psd_state.proto_diffuse_buffer_f + slot_idx * 2 * hDirAC->num_freq_bands * hDirAC->num_outputs_diff, + hDirAC->num_protos_diff, + hDirAC->proto_index_diff, + hDirAC->h_output_synthesis_psd_state.proto_diffuse_buffer_f + slot_idx * 2 * hDirAC->num_freq_bands * hDirAC->num_outputs_diff + 2 * hDirAC->num_freq_bands * min( 4, nchan_transport ), + onset_filter, + hDirAC->h_freq_domain_decorr_ap_params, + hDirAC->h_freq_domain_decorr_ap_state ); + + v_multc( onset_filter, 0.25f, onset_filter, hDirAC->num_freq_bands ); + v_add( onset_filter, onset_filter_subframe, onset_filter_subframe, hDirAC->num_freq_bands ); + p_onset_filter = onset_filter_subframe; } else { - if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) - { - set_f( onset_filter_subframe, 1.f, hDirAC->num_freq_bands ); - p_onset_filter = onset_filter_subframe; - } - else - { - /* no frequency domain decorrelation: use prototype frame */ - hDirAC->proto_frame_dec_f = hDirAC->proto_frame_f; - p_onset_filter = NULL; - } + ivas_dirac_dec_decorr_process( hDirAC->num_freq_bands, + hDirAC->num_outputs_diff, + hDirAC->num_protos_diff, + hDirAC->synthesisConf, + nchan_transport, + hDirAC->proto_frame_f, + hDirAC->num_protos_diff, + hDirAC->proto_index_diff, + DirAC_mem.frame_dec_f, + onset_filter, + hDirAC->h_freq_domain_decorr_ap_params, + hDirAC->h_freq_domain_decorr_ap_state ); + + hDirAC->proto_frame_dec_f = DirAC_mem.frame_dec_f; + p_onset_filter = onset_filter; } - - /*-----------------------------------------------------------------* - * output synthesis - *-----------------------------------------------------------------*/ - - if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_LS || hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) + } + else + { + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + set_f( onset_filter_subframe, 1.f, hDirAC->num_freq_bands ); + p_onset_filter = onset_filter_subframe; + } + else { - /*Compute diffuse prototypes*/ - ivas_dirac_dec_compute_diffuse_proto( hDirAC, slot_idx ); + /* no frequency domain decorrelation: use prototype frame */ + hDirAC->proto_frame_dec_f = hDirAC->proto_frame_f; + p_onset_filter = NULL; } + } + + /*-----------------------------------------------------------------* + * output synthesis + *-----------------------------------------------------------------*/ + + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_LS || hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) + { + /*Compute diffuse prototypes*/ + ivas_dirac_dec_compute_diffuse_proto( hDirAC, slot_idx ); + } - /*Compute PSDs*/ - if ( st_ivas->hDecoderConfig->Opt_Headrotation && st_ivas->hHeadTrackData->shd_rot_max_order == 2 ) + /*Compute PSDs*/ +#ifndef JBM_TSM_ON_TCS + if ( st_ivas->hDecoderConfig->Opt_Headrotation && st_ivas->hHeadTrackData->shd_rot_max_order == 2 ) + { + ivas_dirac_dec_output_synthesis_process_slot( reference_power, + p_onset_filter, + hDirAC, + p_Rmat, + st_ivas->hVBAPdata, + hDirAC->hOutSetup, + nchan_transport +#ifndef HODIRAC + , + index_slot +#endif +#ifdef HODIRAC + , + st_ivas->sba_analysis_order > 1 && + st_ivas->hDecoderConfig->ivas_total_brate > IVAS_256k +#endif + ); + } + else + { + ivas_dirac_dec_output_synthesis_process_slot( reference_power, + p_onset_filter, + hDirAC, + 0, + st_ivas->hVBAPdata, + hDirAC->hOutSetup, + nchan_transport +#ifndef HODIRAC + , + index_slot +#endif +#ifdef HODIRAC + , + st_ivas->sba_analysis_order > 1 && + st_ivas->hDecoderConfig->ivas_total_brate > IVAS_256k +#endif + + ); + } +#else + if ( st_ivas->hDecoderConfig->Opt_Headrotation && st_ivas->hHeadTrackData->shd_rot_max_order > 0 ) { ivas_dirac_dec_output_synthesis_process_slot( reference_power, p_onset_filter, + azimuth[slot_idx], + elevation[slot_idx], + diffuseness_vector[slot_idx], hDirAC, + st_ivas->hHeadTrackData->shd_rot_max_order, p_Rmat, st_ivas->hVBAPdata, hDirAC->hOutSetup, nchan_transport, -#ifndef HODIRAC - index_slot -#endif + md_idx, #ifdef HODIRAC - st_ivas->sba_analysis_order > 1 && + st_ivas->sba_analysis_order > 1 && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_256k #endif @@ -2984,237 +3544,364 @@ void ivas_dirac_dec( { ivas_dirac_dec_output_synthesis_process_slot( reference_power, p_onset_filter, + azimuth[slot_idx], + elevation[slot_idx], + diffuseness_vector[slot_idx], hDirAC, 0, + 0, st_ivas->hVBAPdata, hDirAC->hOutSetup, nchan_transport, -#ifndef HODIRAC - index_slot -#endif + md_idx, #ifdef HODIRAC - st_ivas->sba_analysis_order > 1 && + st_ivas->sba_analysis_order > 1 && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_256k #endif ); } +#endif - if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) - { - v_add( reference_power, reference_power_smooth, reference_power_smooth, hDirAC->num_freq_bands ); - } - - if ( hDirAC->hConfig->dec_param_estim ) - { - hDirAC->dirac_read_idx = ( hDirAC->dirac_read_idx + 1 ) % hDirAC->dirac_md_buffer_length; - } + if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + { + v_add( reference_power, reference_power_smooth, reference_power_smooth, hDirAC->num_freq_bands ); } - if ( hDirAC->hConfig->dec_param_estim == 0 ) +#ifndef JBM_TSM_ON_TCS + if ( hDirAC->hConfig->dec_param_estim ) { hDirAC->dirac_read_idx = ( hDirAC->dirac_read_idx + 1 ) % hDirAC->dirac_md_buffer_length; } +#endif + } +#ifndef JBM_TSM_ON_TCS + if ( hDirAC->hConfig->dec_param_estim == 0 ) + { + hDirAC->dirac_read_idx = ( hDirAC->dirac_read_idx + 1 ) % hDirAC->dirac_md_buffer_length; + } +#endif +#ifdef JBM_TSM_ON_TCS + ivas_dirac_dec_output_synthesis_get_interpolator( &hDirAC->h_output_synthesis_psd_params, hDirAC->subframe_nbslots[subframe_idx] ); - if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + if ( hDirAC->hConfig->dec_param_estim == FALSE ) + { + md_idx = hDirAC->render_to_md_map[subframe_idx]; + } + else + { + md_idx = hDirAC->render_to_md_map[slot_idx_start]; + } + + /* Workaround for BE (should be gone when #393 is adressed and diffuseness index in the gain SHD renderer with HO-DirAC is fixed) */ + /* :TODO: remove */ + /* get the correct md index for the diffuseness in direction smoothing and HO-DirAC, it is always the first slot of the next subframe*/ + if ( slot_idx_start + hDirAC->subframe_nbslots[subframe_idx] == hDirAC->num_slots ) + { + /* we are at the end, get the next one using the normal dirac read idx...*/ + if ( st_ivas->hDirAC->hConfig->dec_param_estim == 1 ) { - ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( Cldfb_RealBuffer, - Cldfb_ImagBuffer, - hDirAC, - nchan_transport, - p_onset_filter + md_idx = ( hDirAC->dirac_read_idx + DEFAULT_JBM_CLDFB_TIMESLOTS ) % hDirAC->dirac_md_buffer_length; + } + else + { + md_idx = ( hDirAC->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % hDirAC->dirac_md_buffer_length; + } + } + else + { + if ( st_ivas->hDirAC->hConfig->dec_param_estim == 1 ) + { + md_idx = hDirAC->render_to_md_map[slot_idx_start + hDirAC->subframe_nbslots[subframe_idx]]; + } + else + { + md_idx = hDirAC->render_to_md_map[subframe_idx + 1]; + } + } + +#endif + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( Cldfb_RealBuffer, + Cldfb_ImagBuffer, + hDirAC, + nchan_transport, +#ifdef JBM_TSM_ON_TCS + hDirAC->subframe_nbslots[subframe_idx], +#endif + p_onset_filter #ifdef HODIRAC - , - st_ivas->sba_analysis_order > 1 && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_256k + , +#ifdef JBM_TSM_ON_TCS + md_idx, #endif - ); + st_ivas->sba_analysis_order > 1 && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_256k +#endif + ); + } + else + { + /* Determine encoding quality based additional smoothing factor */ + float qualityBasedSmFactor = 1.0f; + + if ( st_ivas->hMasa != NULL ) + { + qualityBasedSmFactor = st_ivas->hMasa->data.dir_decode_quality; + qualityBasedSmFactor *= qualityBasedSmFactor; } - else +#ifdef JBM_TSM_ON_TCS + /* Workaround for BE (should be gone when #393 is adressed) */ + if ( hDirAC->hConfig->dec_param_estim == 1 ) { - /* Determine encoding quality based additional smoothing factor */ - float qualityBasedSmFactor = 1.0f; - if ( st_ivas->hMasa != NULL ) + num_freq_bands = hDirAC->band_grouping[hDirAC->hConfig->enc_param_start_band]; + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) { - qualityBasedSmFactor = st_ivas->hMasa->data.dir_decode_quality; - qualityBasedSmFactor *= qualityBasedSmFactor; + mvs2s( azimuth[slot_idx], hDirAC->azimuth[hDirAC->render_to_md_map[slot_idx + slot_idx_start]], num_freq_bands ); + mvs2s( elevation[slot_idx], hDirAC->elevation[hDirAC->render_to_md_map[slot_idx + slot_idx_start]], num_freq_bands ); + mvr2r( diffuseness_vector[slot_idx], hDirAC->diffuseness_vector[hDirAC->render_to_md_map[slot_idx + slot_idx_start]], num_freq_bands ); } - - ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( Cldfb_RealBuffer, - Cldfb_ImagBuffer, - hDirAC, - reference_power_smooth, - qualityBasedSmFactor ); } - /*-----------------------------------------------------------------* - * CLDFB synthesis (and binaural rendering) - *-----------------------------------------------------------------*/ +#endif + ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( Cldfb_RealBuffer, + Cldfb_ImagBuffer, + hDirAC, +#ifdef JBM_TSM_ON_TCS + hDirAC->subframe_nbslots[subframe_idx], + md_idx, +#endif + reference_power_smooth, + qualityBasedSmFactor ); + } + + /*-----------------------------------------------------------------* + * CLDFB synthesis (and binaural rendering) + *-----------------------------------------------------------------*/ + +#ifdef JBM_TSM_ON_TCS + index_slot = slot_idx_start_cldfb_synth; +#else index_slot = subframe_idx * hDirAC->subframe_nbslots; +#endif - if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) - { - /* Perform binaural rendering */ - ivas_binRenderer( st_ivas->hBinRenderer, - st_ivas->hHeadTrackData, - Cldfb_RealBuffer_Binaural, - Cldfb_ImagBuffer_Binaural, - Cldfb_RealBuffer, - Cldfb_ImagBuffer ); + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + /* Perform binaural rendering */ + ivas_binRenderer( st_ivas->hBinRenderer, + st_ivas->hHeadTrackData, +#ifdef JBM_TSM_ON_TCS + hDirAC->subframe_nbslots[subframe_idx], +#endif + Cldfb_RealBuffer_Binaural, + Cldfb_ImagBuffer_Binaural, + Cldfb_RealBuffer, + Cldfb_ImagBuffer ); - /* Inverse CLDFB*/ - for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) - { - /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ - float *RealBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; - float *ImagBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; + /* Inverse CLDFB*/ + for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) + { + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ + float *RealBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; + float *ImagBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; +#ifdef JBM_TSM_ON_TCS + for ( i = 0; i < hDirAC->subframe_nbslots[subframe_idx]; i++ ) +#else for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) - { - RealBuffer[i] = Cldfb_RealBuffer_Binaural[ch][i]; - ImagBuffer[i] = Cldfb_ImagBuffer_Binaural[ch][i]; - } +#endif + { + RealBuffer[i] = Cldfb_RealBuffer_Binaural[ch][i]; + ImagBuffer[i] = Cldfb_ImagBuffer_Binaural[ch][i]; + } +#ifdef JBM_TSM_ON_TCS + cldfbSynthesis( RealBuffer, + ImagBuffer, + &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), + hDirAC->num_freq_bands * hDirAC->subframe_nbslots[subframe_idx], + st_ivas->cldfbSynDec[ch] ); +#else cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), hDirAC->num_freq_bands * hDirAC->subframe_nbslots, st_ivas->cldfbSynDec[ch] ); - } +#endif } - else if ( st_ivas->sba_mode == SBA_MODE_SPAR ) + } + else if ( st_ivas->sba_mode == SBA_MODE_SPAR ) + { + for ( ch = 0; ch < hDirAC->hOutSetup.nchan_out_woLFE; ch++ ) { - for ( ch = 0; ch < hDirAC->hOutSetup.nchan_out_woLFE; ch++ ) - { +#ifdef JBM_TSM_ON_TCS + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) +#else for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots; slot_idx++ ) - { - mvr2r( Cldfb_RealBuffer[ch][slot_idx], pppQMfFrame_ts_re[ch][slot_idx], hDirAC->num_freq_bands ); - mvr2r( Cldfb_ImagBuffer[ch][slot_idx], pppQMfFrame_ts_im[ch][slot_idx], hDirAC->num_freq_bands ); - } +#endif + { + mvr2r( Cldfb_RealBuffer[ch][slot_idx], pppQMfFrame_ts_re[ch][slot_idx], hDirAC->num_freq_bands ); + mvr2r( Cldfb_ImagBuffer[ch][slot_idx], pppQMfFrame_ts_im[ch][slot_idx], hDirAC->num_freq_bands ); } } - else + } + else + { + float *RealBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; + float *ImagBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; + int16_t outchannels; + + idx_in = 0; + idx_lfe = 0; + + outchannels = hDirAC->hOutSetup.nchan_out_woLFE + hDirAC->hOutSetup.num_lfe; + if ( hDirAC->hOutSetup.separateChannelEnabled && ( hDirAC->hOutSetup.output_config == AUDIO_CONFIG_5_1 || + hDirAC->hOutSetup.output_config == AUDIO_CONFIG_7_1 || + hDirAC->hOutSetup.output_config == AUDIO_CONFIG_5_1_2 || + hDirAC->hOutSetup.output_config == AUDIO_CONFIG_5_1_4 || + hDirAC->hOutSetup.output_config == AUDIO_CONFIG_7_1_4 || + ( hDirAC->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM && st_ivas->hLsSetupCustom->separate_ch_found ) ) ) { - float *RealBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; - float *ImagBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; - int16_t outchannels; - - idx_in = 0; - idx_lfe = 0; - - outchannels = hDirAC->hOutSetup.nchan_out_woLFE + hDirAC->hOutSetup.num_lfe; - if ( hDirAC->hOutSetup.separateChannelEnabled && ( hDirAC->hOutSetup.output_config == AUDIO_CONFIG_5_1 || - hDirAC->hOutSetup.output_config == AUDIO_CONFIG_7_1 || - hDirAC->hOutSetup.output_config == AUDIO_CONFIG_5_1_2 || - hDirAC->hOutSetup.output_config == AUDIO_CONFIG_5_1_4 || - hDirAC->hOutSetup.output_config == AUDIO_CONFIG_7_1_4 || - ( hDirAC->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM && st_ivas->hLsSetupCustom->separate_ch_found ) ) ) - { - outchannels++; - } + outchannels++; + } - if ( hDirAC->hOutSetup.separateChannelEnabled && hDirAC->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM ) - { - float tmp_separated[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; - float tmp_lfe[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; - const int16_t subframe_start_sample = index_slot * hDirAC->num_freq_bands; + if ( hDirAC->hOutSetup.separateChannelEnabled && hDirAC->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM ) + { + float tmp_separated[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; + float tmp_lfe[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; + const int16_t subframe_start_sample = index_slot * hDirAC->num_freq_bands; +#ifdef JBM_TSM_ON_TCS + const int16_t num_samples_subframe = hDirAC->num_freq_bands * hDirAC->subframe_nbslots[subframe_idx]; +#else const int16_t num_samples_subframe = hDirAC->num_freq_bands * hDirAC->subframe_nbslots; +#endif - /* Move the separated and the LFE channels to temporary variables as spatial synthesis may overwrite current channels */ - mvr2r( &( output_f[st_ivas->hOutSetup.separateChannelIndex][subframe_start_sample] ), tmp_separated, num_samples_subframe ); - mvr2r( &( output_f[LFE_CHANNEL][subframe_start_sample] ), tmp_lfe, num_samples_subframe ); + /* Move the separated and the LFE channels to temporary variables as spatial synthesis may overwrite current channels */ + mvr2r( &( output_f[st_ivas->hOutSetup.separateChannelIndex][subframe_start_sample] ), tmp_separated, num_samples_subframe ); + mvr2r( &( output_f[LFE_CHANNEL][subframe_start_sample] ), tmp_lfe, num_samples_subframe ); - for ( ch = 0; ch < outchannels; ch++ ) + for ( ch = 0; ch < outchannels; ch++ ) + { + if ( ( hDirAC->hOutSetup.num_lfe > 0 ) && ( hDirAC->hOutSetup.index_lfe[idx_lfe] == ch ) ) { - if ( ( hDirAC->hOutSetup.num_lfe > 0 ) && ( hDirAC->hOutSetup.index_lfe[idx_lfe] == ch ) ) - { - /* Move the LFE channel to the correct place */ - mvr2r( tmp_lfe, &( output_f[ch][subframe_start_sample] ), num_samples_subframe ); + /* Move the LFE channel to the correct place */ + mvr2r( tmp_lfe, &( output_f[ch][subframe_start_sample] ), num_samples_subframe ); - if ( idx_lfe < ( hDirAC->hOutSetup.num_lfe - 1 ) ) - { - idx_lfe++; - } - } - else if ( ( st_ivas->hLsSetupCustom->separate_ch_found ) && ( hDirAC->hOutSetup.separateChannelIndex == ch ) ) + if ( idx_lfe < ( hDirAC->hOutSetup.num_lfe - 1 ) ) { - /* Move the separated channel to the correct place. Thus, the separated channel is - * combined with the synthesized channels here when there is a matching channel. */ - mvr2r( tmp_separated, &( output_f[ch][subframe_start_sample] ), num_samples_subframe ); + idx_lfe++; } - else - { - /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ + } + else if ( ( st_ivas->hLsSetupCustom->separate_ch_found ) && ( hDirAC->hOutSetup.separateChannelIndex == ch ) ) + { + /* Move the separated channel to the correct place. Thus, the separated channel is + * combined with the synthesized channels here when there is a matching channel. */ + mvr2r( tmp_separated, &( output_f[ch][subframe_start_sample] ), num_samples_subframe ); + } + else + { + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ +#ifdef JBM_TSM_ON_TCS + for ( i = 0; i < hDirAC->subframe_nbslots[subframe_idx]; i++ ) +#else for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) - { - RealBuffer[i] = Cldfb_RealBuffer[idx_in][i]; - ImagBuffer[i] = Cldfb_ImagBuffer[idx_in][i]; - } - cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][subframe_start_sample] ), num_samples_subframe, st_ivas->cldfbSynDec[idx_in] ); - - if ( !st_ivas->hLsSetupCustom->separate_ch_found ) - { - /* Pan the separated channel and mix with the synthesized channels. Thus, the separated channel - * is combined with the synthesized channels here when there is no matching channel. */ - v_multc_acc( tmp_separated, st_ivas->hLsSetupCustom->separate_ch_gains[idx_in], &( output_f[ch][subframe_start_sample] ), num_samples_subframe ); - } +#endif + { + RealBuffer[i] = Cldfb_RealBuffer[idx_in][i]; + ImagBuffer[i] = Cldfb_ImagBuffer[idx_in][i]; + } + cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][subframe_start_sample] ), num_samples_subframe, st_ivas->cldfbSynDec[idx_in] ); - idx_in++; + if ( !st_ivas->hLsSetupCustom->separate_ch_found ) + { + /* Pan the separated channel and mix with the synthesized channels. Thus, the separated channel + * is combined with the synthesized channels here when there is no matching channel. */ + v_multc_acc( tmp_separated, st_ivas->hLsSetupCustom->separate_ch_gains[idx_in], &( output_f[ch][subframe_start_sample] ), num_samples_subframe ); } + + idx_in++; } } - else + } + else + { + for ( ch = 0; ch < outchannels; ch++ ) { - for ( ch = 0; ch < outchannels; ch++ ) + if ( ( hDirAC->hOutSetup.num_lfe > 0 ) && ( hDirAC->hOutSetup.index_lfe[idx_lfe] == ch ) ) { - if ( ( hDirAC->hOutSetup.num_lfe > 0 ) && ( hDirAC->hOutSetup.index_lfe[idx_lfe] == ch ) ) + if ( st_ivas->mc_mode == MC_MODE_MCMASA && !hDirAC->hOutSetup.separateChannelEnabled ) { - if ( st_ivas->mc_mode == MC_MODE_MCMASA && !hDirAC->hOutSetup.separateChannelEnabled ) - { +#ifdef JBM_TSM_ON_TCS + for ( i = 0; i < hDirAC->subframe_nbslots[subframe_idx]; i++ ) +#else for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) - { - RealBuffer[i] = Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS - 1][i]; - ImagBuffer[i] = Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS - 1][i]; - } - cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), hDirAC->num_freq_bands * hDirAC->subframe_nbslots, st_ivas->cldfbSynDec[hDirAC->hOutSetup.nchan_out_woLFE + idx_lfe] ); - } - else if ( st_ivas->mc_mode == MC_MODE_MCMASA && hDirAC->hOutSetup.separateChannelEnabled ) - { - /* LFE has been synthesized in the time domain, do nothing. */ - } - else - { - set_zero( &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), hDirAC->subframe_nbslots * hDirAC->num_freq_bands ); - } - - if ( idx_lfe < ( hDirAC->hOutSetup.num_lfe - 1 ) ) +#endif { - idx_lfe++; + RealBuffer[i] = Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS - 1][i]; + ImagBuffer[i] = Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS - 1][i]; } +#ifdef JBM_TSM_ON_TCS + cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), hDirAC->num_freq_bands * hDirAC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[hDirAC->hOutSetup.nchan_out_woLFE + idx_lfe] ); +#else + cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), hDirAC->num_freq_bands * hDirAC->subframe_nbslots, st_ivas->cldfbSynDec[hDirAC->hOutSetup.nchan_out_woLFE + idx_lfe] ); +#endif } - else if ( ( hDirAC->hOutSetup.separateChannelEnabled ) && ( hDirAC->hOutSetup.separateChannelIndex == ch ) ) + else if ( st_ivas->mc_mode == MC_MODE_MCMASA && hDirAC->hOutSetup.separateChannelEnabled ) { - /* The separated channel is already set to output_f[hOutSetup.separateChannelIndex]. Thus, the separated - * channel is combined with the synthesized channels here. */ + /* LFE has been synthesized in the time domain, do nothing. */ } else { - /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ +#ifdef JBM_TSM_ON_TCS + set_zero( &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), hDirAC->subframe_nbslots[subframe_idx] * hDirAC->num_freq_bands ); +#else + set_zero( &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), hDirAC->subframe_nbslots * hDirAC->num_freq_bands ); +#endif + } + + if ( idx_lfe < ( hDirAC->hOutSetup.num_lfe - 1 ) ) + { + idx_lfe++; + } + } + else if ( ( hDirAC->hOutSetup.separateChannelEnabled ) && ( hDirAC->hOutSetup.separateChannelIndex == ch ) ) + { + /* The separated channel is already set to output_f[hOutSetup.separateChannelIndex]. Thus, the separated + * channel is combined with the synthesized channels here. */ + } + else + { + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ +#ifdef JBM_TSM_ON_TCS + for ( i = 0; i < hDirAC->subframe_nbslots[subframe_idx]; i++ ) +#else for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) - { - RealBuffer[i] = Cldfb_RealBuffer[idx_in][i]; - ImagBuffer[i] = Cldfb_ImagBuffer[idx_in][i]; - } - cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), hDirAC->num_freq_bands * hDirAC->subframe_nbslots, st_ivas->cldfbSynDec[idx_in] ); - idx_in++; +#endif + { + RealBuffer[i] = Cldfb_RealBuffer[idx_in][i]; + ImagBuffer[i] = Cldfb_ImagBuffer[idx_in][i]; } +#ifdef JBM_TSM_ON_TCS + cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), hDirAC->num_freq_bands * hDirAC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[idx_in] ); +#else + cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][index_slot * hDirAC->num_freq_bands] ), hDirAC->num_freq_bands * hDirAC->subframe_nbslots, st_ivas->cldfbSynDec[idx_in] ); +#endif + idx_in++; } } } } +#ifdef JBM_TSM_ON_TCS + hDirAC->slots_rendered += hDirAC->subframe_nbslots[subframe_idx]; + hDirAC->subframes_rendered++; +#endif +#ifndef JBM_TSM_ON_TCS +} +#endif - pop_wmops(); +pop_wmops(); - return; +return; } @@ -3937,8 +4624,8 @@ static void protoSignalComputation4( proto_frame_f[2 * l * num_freq_bands + 2 * k] += RealBuffer[n][0][k] * mtx_hoa_decoder[l * 16 + sba_map_tc_ind[n]]; proto_frame_f[2 * l * num_freq_bands + 2 * k + 1] += ImagBuffer[n][0][k] * mtx_hoa_decoder[l * 16 + sba_map_tc_ind[n]]; #else - proto_frame_f[2 * l * num_freq_bands + 2 * k] += RealBuffer[n][0][k] * mtx_hoa_decoder[l * 16 + sba_map_tc[n]]; - proto_frame_f[2 * l * num_freq_bands + 2 * k + 1] += ImagBuffer[n][0][k] * mtx_hoa_decoder[l * 16 + sba_map_tc[n]]; + proto_frame_f[2 * l * num_freq_bands + 2 * k] += RealBuffer[n][0][k] * mtx_hoa_decoder[l * 16 + sba_map_tc[n]]; + proto_frame_f[2 * l * num_freq_bands + 2 * k + 1] += ImagBuffer[n][0][k] * mtx_hoa_decoder[l * 16 + sba_map_tc[n]]; #endif } } diff --git a/lib_dec/ivas_dirac_output_synthesis_cov.c b/lib_dec/ivas_dirac_output_synthesis_cov.c index a2fc9ee8210be12378d3175c808075fd88ebcd8d..892cfe4acbd1120a7f3d2f4b90eae08a2fa2ad76 100644 --- a/lib_dec/ivas_dirac_output_synthesis_cov.c +++ b/lib_dec/ivas_dirac_output_synthesis_cov.c @@ -104,12 +104,19 @@ ivas_error ivas_dirac_dec_output_synthesis_cov_open( set_zero( h_dirac_output_synthesis_state->cx_old[idx], nchan_in * nchan_in ); set_zero( h_dirac_output_synthesis_state->cy_old[idx], nchan_out * nchan_out ); set_zero( h_dirac_output_synthesis_state->mixing_matrix_old[idx], nchan_out * nchan_in ); +#ifdef JBM_TSM_ON_TCS + h_dirac_output_synthesis_state->mixing_matrix[idx] = (float *) malloc( nchan_out * nchan_in * sizeof( float ) ); + set_zero( h_dirac_output_synthesis_state->mixing_matrix[idx], nchan_out * nchan_in ); +#endif } for ( ; idx < CLDFB_NO_CHANNELS_MAX; idx++ ) { h_dirac_output_synthesis_state->cx_old[idx] = NULL; h_dirac_output_synthesis_state->cy_old[idx] = NULL; h_dirac_output_synthesis_state->mixing_matrix_old[idx] = NULL; +#ifdef JBM_TSM_ON_TCS + h_dirac_output_synthesis_state->mixing_matrix[idx] = NULL; +#endif } for ( idx = 0; idx < num_param_bands_residual; idx++ ) { @@ -118,10 +125,17 @@ ivas_error ivas_dirac_dec_output_synthesis_cov_open( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) ); } set_zero( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx], nchan_out * nchan_out ); +#ifdef JBM_TSM_ON_TCS + h_dirac_output_synthesis_state->mixing_matrix_res[idx] = (float *) malloc( nchan_out * nchan_out * sizeof( float ) ); + set_zero( h_dirac_output_synthesis_state->mixing_matrix_res[idx], nchan_out * nchan_out ); +#endif } for ( ; idx < CLDFB_NO_CHANNELS_MAX; idx++ ) { h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] = NULL; +#ifdef JBM_TSM_ON_TCS + h_dirac_output_synthesis_state->mixing_matrix_res[idx] = NULL; +#endif } /*-----------------------------------------------------------------* @@ -144,6 +158,28 @@ ivas_error ivas_dirac_dec_output_synthesis_cov_open( return IVAS_ERR_OK; } +#ifdef JBM_TSM_ON_TCS +/*-------------------------------------------------------------------* + * ivas_dirac_dec_output_synthesis_cov_open() + * + * Sets up the state and parameters for the Covariance Synthesis + *-------------------------------------------------------------------*/ + +void ivas_dirac_dec_output_synthesis_get_interpolator( + DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params, /* i/o: handle for the covariance synthesis parameters */ + const uint16_t interp_length ) +{ + int16_t idx; + + for ( idx = 1; idx <= interp_length; ++idx ) + { + h_dirac_output_synthesis_params->interpolator[idx - 1] = (float) idx / (float) interp_length; + } + + return; +} +#endif + /*-------------------------------------------------------------------* * ivas_dirac_dec_output_synthesis_cov_init() @@ -168,11 +204,17 @@ void ivas_dirac_dec_output_synthesis_cov_init( set_zero( h_dirac_output_synthesis_state->cx_old[idx], nchan_in * nchan_in ); set_zero( h_dirac_output_synthesis_state->cy_old[idx], nchan_out * nchan_out ); set_zero( h_dirac_output_synthesis_state->mixing_matrix_old[idx], nchan_out * nchan_in ); +#ifdef JBM_TSM_ON_TCS + set_zero( h_dirac_output_synthesis_state->mixing_matrix[idx], nchan_out * nchan_in ); +#endif } for ( idx = 0; idx < n_param_bands_res; idx++ ) { set_zero( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx], nchan_out * nchan_out ); +#ifdef JBM_TSM_ON_TCS + set_zero( h_dirac_output_synthesis_state->mixing_matrix_res[idx], nchan_out * nchan_out ); +#endif } return; @@ -243,6 +285,19 @@ void ivas_dirac_dec_output_synthesis_cov_close( free( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] ); h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] = NULL; } +#ifdef JBM_TSM_ON_TCS + if ( h_dirac_output_synthesis_state->mixing_matrix[idx] != NULL ) + { + free( h_dirac_output_synthesis_state->mixing_matrix[idx] ); + h_dirac_output_synthesis_state->mixing_matrix[idx] = NULL; + } + + if ( h_dirac_output_synthesis_state->mixing_matrix_res[idx] != NULL ) + { + free( h_dirac_output_synthesis_state->mixing_matrix_res[idx] ); + h_dirac_output_synthesis_state->mixing_matrix_res[idx] = NULL; + } +#endif } return; @@ -256,13 +311,21 @@ void ivas_dirac_dec_output_synthesis_cov_close( *-------------------------------------------------------------------*/ void ivas_dirac_dec_output_synthesis_cov_param_mc_collect_slot( - float RealBuffer[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : input channel filter bank samples (real part) */ - float ImagBuffer[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : input channel filter bank samples (imaginary part */ +#ifdef JBM_TSM_ON_TCS + float *RealBuffer, /* i : input channel filter bank samples (real part) */ + float *ImagBuffer, /* i : input channel filter bank samples (imaginary part */ +#else + float RealBuffer[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : input channel filter bank samples (real part) */ + float ImagBuffer[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : input channel filter bank samples (imaginary part */ +#endif float cx[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], /* o : accumulated input covariance (real part) */ float cx_imag[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], /* o : accumulated input covariance (imaginary part) */ PARAM_MC_DEC_HANDLE hParamMC, /* i : handle to Parametric MC state */ - const int16_t nchan_in, /* i : number of input channels */ - const int16_t idx_slot /* i : index of the slot to be added to the input covariance */ + const int16_t nchan_in /* i : number of input channels */ +#ifndef JBM_TSM_ON_TCS + , + const int16_t idx_slot /* i : index of the slot to be added to the input covariance */ +#endif ) { int16_t param_band, band_idx, ch_idx; @@ -288,8 +351,13 @@ void ivas_dirac_dec_output_synthesis_cov_param_mc_collect_slot( int16_t band = brange[0] + band_idx; for ( ch_idx = 0; ch_idx < nchan_in; ch_idx++ ) { +#ifdef JBM_TSM_ON_TCS + real_in_buffer[band_idx + num_bands * ch_idx] = RealBuffer[ch_idx * hParamMC->num_freq_bands + band]; + imag_in_buffer[band_idx + num_bands * ch_idx] = ImagBuffer[ch_idx * hParamMC->num_freq_bands + band]; +#else real_in_buffer[band_idx + num_bands * ch_idx] = RealBuffer[ch_idx][idx_slot][band]; imag_in_buffer[band_idx + num_bands * ch_idx] = ImagBuffer[ch_idx][idx_slot][band]; +#endif } } @@ -312,17 +380,27 @@ void ivas_dirac_dec_output_synthesis_cov_param_mc_collect_slot( *-------------------------------------------------------------------*/ void ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot( - float Cldfb_RealBuffer_in[][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : input channel filter bank samples (real part) */ - float Cldfb_ImagBuffer_in[][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : input channel filter bank samples (imaginary part) */ - float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : output channel filter bank samples (real part) */ - float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : output channel filter bank samples (imaginary part) */ +#ifdef JBM_TSM_ON_TCS + float *Cldfb_RealBuffer_in, /* i : input channel filter bank samples (real part) */ + float *Cldfb_ImagBuffer_in, /* i : input channel filter bank samples (imaginary part) */ +#else + float Cldfb_RealBuffer_in[PARAM_MC_MAX_TRANSPORT_CHANS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : CLDFB samples of the transport channels (real part) */ + float Cldfb_ImagBuffer_in[PARAM_MC_MAX_TRANSPORT_CHANS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : CLDFB samples of the transport channels (imaginary part) */ +#endif + float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : output channel filter bank samples (real part) */ + float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : output channel filter bank samples (imaginary part) */ +#ifdef JBM_TSM_ON_TCS + float *mixing_matrix[], /* i : parameter band wise mixing matrices (direct part) */ + float *mixing_matrix_res[], /* i : parameter band wise mixing matrices (residual part) */ +#else float mixing_matrix[PARAM_MC_MAX_PARAMETER_BANDS][MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS], /* i : parameter band wise mixing matrices (direct part) */ float mixing_matrix_res[PARAM_MC_MAX_PARAMETER_BANDS_RES][MAX_CICP_CHANNELS * MAX_CICP_CHANNELS], /* i : parameter band wise mixing matrices (residual part) */ - const uint16_t slot_idx_sfr, /* i : time slot index for the current slot within the current subframe */ - const uint16_t slot_idx_tot, /* i : time slot index for the current slot within the frame */ - const int16_t nX, /* i : number of input channels */ - const int16_t nY, /* i : number of output channels */ - PARAM_MC_DEC_HANDLE hParamMC /* i : handle to the Parametric MC decoder state */ +#endif + const uint16_t slot_idx_sfr, /* i : time slot index for the current slot within the current subframe */ + const uint16_t slot_idx_tot, /* i : time slot index for the current slot within the frame */ + const int16_t nX, /* i : number of input channels */ + const int16_t nY, /* i : number of output channels */ + PARAM_MC_DEC_HANDLE hParamMC /* i : handle to the Parametric MC decoder state */ ) { int16_t param_band_idx, band, ch_idx; @@ -407,8 +485,13 @@ void ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot( /* collect input signals, still in cldfb buffers */ for ( ch_idx = 0; ch_idx < nX; ch_idx++ ) { +#ifdef JBM_TSM_ON_TCS + input_f_real[ch_idx] = Cldfb_RealBuffer_in[ch_idx * hParamMC->num_freq_bands + band]; + input_f_imag[ch_idx] = Cldfb_ImagBuffer_in[ch_idx * hParamMC->num_freq_bands + band]; +#else input_f_real[ch_idx] = Cldfb_RealBuffer_in[ch_idx][slot_idx_tot][band]; input_f_imag[ch_idx] = Cldfb_ImagBuffer_in[ch_idx][slot_idx_tot][band]; +#endif } /* apply mixing matrix */ diff --git a/lib_dec/ivas_dirac_output_synthesis_dec.c b/lib_dec/ivas_dirac_output_synthesis_dec.c old mode 100755 new mode 100644 index fc76524abb1397b21d641051892c8c44aa2104d5..a7bb8e504d67758f2111602c107bf46ffcae078e --- a/lib_dec/ivas_dirac_output_synthesis_dec.c +++ b/lib_dec/ivas_dirac_output_synthesis_dec.c @@ -168,7 +168,11 @@ ivas_error ivas_dirac_dec_output_synthesis_open( } /* buffer length and interpolator */ +#ifdef JBM_TSM_ON_TCS + if ( ( dirac_output_synthesis_params->interpolator = (float *) malloc( JBM_CLDFB_SLOTS_IN_SUBFRAME * sizeof( float ) ) ) == NULL ) +#else if ( ( dirac_output_synthesis_params->interpolator = (float *) malloc( hDirAC->subframe_nbslots * sizeof( float ) ) ) == NULL ) +#endif { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } @@ -301,9 +305,17 @@ ivas_error ivas_dirac_dec_output_synthesis_open( } /* compute interpolator */ +#ifdef JBM_TSM_ON_TCS + for ( idx = 1; idx <= JBM_CLDFB_SLOTS_IN_SUBFRAME; ++idx ) +#else for ( idx = 1; idx <= hDirAC->subframe_nbslots; ++idx ) +#endif { +#ifdef JBM_TSM_ON_TCS + dirac_output_synthesis_params->interpolator[idx - 1] = (float) idx / (float) JBM_CLDFB_SLOTS_IN_SUBFRAME; +#else dirac_output_synthesis_params->interpolator[idx - 1] = (float) idx / (float) hDirAC->subframe_nbslots; +#endif } /* prepare diffuse response function */ @@ -563,17 +575,27 @@ void ivas_dirac_dec_output_synthesis_close( *------------------------------------------------------------------------*/ void ivas_dirac_dec_output_synthesis_process_slot( - const float *reference_power, /* i : Estimated power */ - const float *onset, /* i : onset filter */ - DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ + const float *reference_power, /* i : Estimated power */ + const float *onset, /* i : onset filter */ +#ifdef JBM_TSM_ON_TCS + const int16_t *azimuth, + const int16_t *elevation, + const float *diffuseness, +#endif + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ +#ifdef JBM_TSM_ON_TCS + const int16_t sh_rot_max_order, +#endif const float *p_Rmat, /* i : rotation matrix */ const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ const IVAS_OUTPUT_SETUP hOutSetup, /* i : output setup structure */ - const int16_t nchan_transport, /* i : number of transport channels*/ -#ifndef HODIRAC - const int16_t index_slot + const int16_t nchan_transport /* i : number of transport channels*/ +#if !defined( HODIRAC ) || defined( JBM_TSM_ON_TCS ) + , + const int16_t md_idx #endif #ifdef HODIRAC + , const int16_t hodirac #endif ) @@ -583,11 +605,15 @@ void ivas_dirac_dec_output_synthesis_process_slot( int16_t ch_idx; float aux_buf[CLDFB_NO_CHANNELS_MAX]; int16_t diff_start_band; +#ifndef JBM_TSM_ON_TCS const float *diffuseness; +#endif DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params; DIRAC_OUTPUT_SYNTHESIS_STATE *h_dirac_output_synthesis_state; +#ifndef JBM_TSM_ON_TCS diffuseness = hDirAC->diffuseness_vector[hDirAC->dirac_read_idx]; +#endif h_dirac_output_synthesis_params = &( hDirAC->h_output_synthesis_psd_params ); h_dirac_output_synthesis_state = &( hDirAC->h_output_synthesis_psd_state ); @@ -614,6 +640,11 @@ void ivas_dirac_dec_output_synthesis_process_slot( ivas_dirac_dec_compute_directional_responses( hDirAC, hVBAPdata, NULL, +#ifdef JBM_TSM_ON_TCS + azimuth, + elevation, + md_idx, +#endif NULL, 2, p_Rmat, @@ -623,6 +654,25 @@ void ivas_dirac_dec_output_synthesis_process_slot( { if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { +#ifdef JBM_TSM_ON_TCS + v_multc( hDirAC->energy_ratio1[md_idx], -1.f, aux_buf, num_freq_bands ); + v_addc( aux_buf, 1.f, aux_buf, num_freq_bands ); + mvr2r( hDirAC->energy_ratio1[md_idx], + h_dirac_output_synthesis_state->direct_power_factor, + num_freq_bands ); + mvr2r( aux_buf, + h_dirac_output_synthesis_state->diffuse_power_factor, + num_freq_bands ); + + v_multc( hDirAC->energy_ratio2[md_idx], -1.f, aux_buf, num_freq_bands ); + v_addc( aux_buf, 1.f, aux_buf, num_freq_bands ); + mvr2r( hDirAC->energy_ratio2[md_idx], + &h_dirac_output_synthesis_state->direct_power_factor[hDirAC->num_freq_bands], + num_freq_bands ); + mvr2r( aux_buf, + &h_dirac_output_synthesis_state->diffuse_power_factor[hDirAC->num_freq_bands], + num_freq_bands ); +#else v_multc( hDirAC->energy_ratio1[hDirAC->dirac_read_idx], -1.f, aux_buf, num_freq_bands ); v_addc( aux_buf, 1.f, aux_buf, num_freq_bands ); mvr2r( hDirAC->energy_ratio1[hDirAC->dirac_read_idx], @@ -640,21 +690,47 @@ void ivas_dirac_dec_output_synthesis_process_slot( mvr2r( aux_buf, &h_dirac_output_synthesis_state->diffuse_power_factor[hDirAC->num_freq_bands], num_freq_bands ); +#endif } else { +#ifdef JBM_TSM_ON_TCS + ivas_dirac_dec_compute_gain_factors( num_freq_bands, + hDirAC->diffuseness_vector[md_idx], + h_dirac_output_synthesis_params->max_band_decorr, + h_dirac_output_synthesis_state->direct_power_factor, + h_dirac_output_synthesis_state->diffuse_power_factor ); +#else ivas_dirac_dec_compute_gain_factors( num_freq_bands, hDirAC->diffuseness_vector[hDirAC->dirac_read_idx], h_dirac_output_synthesis_params->max_band_decorr, h_dirac_output_synthesis_state->direct_power_factor, h_dirac_output_synthesis_state->diffuse_power_factor ); +#endif } } else // ( hDirAC->hConfig->dec_param_estim == TRUE ) #endif if ( hDirAC->hConfig->dec_param_estim == TRUE ) { + /* compute direct responses */ +#ifdef JBM_TSM_ON_TCS + ivas_dirac_dec_compute_directional_responses( hDirAC, + hVBAPdata, + NULL, + azimuth, + elevation, + md_idx, + NULL, + sh_rot_max_order, + p_Rmat +#ifdef HODIRAC + , + hodirac /* i : flag for sector based dirac processing */ +#endif + ); +#else ivas_dirac_dec_compute_directional_responses( hDirAC, hVBAPdata, NULL, @@ -666,6 +742,7 @@ void ivas_dirac_dec_output_synthesis_process_slot( 0 #endif ); +#endif if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { @@ -675,6 +752,7 @@ void ivas_dirac_dec_output_synthesis_process_slot( h_dirac_output_synthesis_state->direct_power_factor, h_dirac_output_synthesis_state->diffuse_power_factor ); + v_multc( h_dirac_output_synthesis_state->direct_power_factor, 0.25f, h_dirac_output_synthesis_state->direct_power_factor, @@ -684,7 +762,6 @@ void ivas_dirac_dec_output_synthesis_process_slot( h_dirac_output_synthesis_state->diffuse_power_factor, num_freq_bands ); - /*Direct gain*/ for ( ch_idx = 0; ch_idx < min( 4, nchan_transport ); ch_idx++ ) { @@ -722,6 +799,7 @@ void ivas_dirac_dec_output_synthesis_process_slot( } } } + /*Directional gain (panning)*/ for ( ch_idx = min( 4, nchan_transport ); ch_idx < num_channels_dir; ch_idx++ ) { @@ -755,7 +833,6 @@ void ivas_dirac_dec_output_synthesis_process_slot( else { /* compute reference and diffuse power factor for this frame */ - ivas_dirac_dec_compute_power_factors( num_freq_bands, diffuseness, h_dirac_output_synthesis_params->max_band_decorr, @@ -802,9 +879,15 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ const int16_t nchan_transport, /* i : number of transport channels */ +#ifdef JBM_TSM_ON_TCS + const int16_t nbslots, /* i : number of slots to process */ +#endif const float *onset_filter #ifdef HODIRAC , +#ifdef JBM_TSM_ON_TCS + const int16_t md_idx, +#endif const int16_t hodirac /* i: flag for sector-based processing */ #endif ) @@ -846,7 +929,11 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( nchan_transport_foa = min( 4, nchan_transport ); #ifdef HODIRAC +#ifdef JBM_TSM_ON_TCS + diffuseness = hDirAC->diffuseness_vector[md_idx]; +#else diffuseness = hDirAC->diffuseness_vector[hDirAC->dirac_read_idx]; +#endif #endif /*-----------------------------------------------------------------* @@ -1056,7 +1143,11 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( * gain interpolation and output streams *-----------------------------------------------------------------*/ +#ifdef JBM_TSM_ON_TCS + for ( buf_idx = 0; buf_idx < nbslots; ++buf_idx ) +#else for ( buf_idx = 0; buf_idx < hDirAC->subframe_nbslots; ++buf_idx ) +#endif { g1 = h_dirac_output_synthesis_params.interpolator[buf_idx]; g2 = 1.f - g1; @@ -1277,10 +1368,15 @@ void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ +#ifdef JBM_TSM_ON_TCS + const int16_t nbslots, /* i : number of slots to process */ + const int16_t diff_md_idx, /* i : md slot idx of diffuseness to use */ +#endif float *reference_power_smooth, float qualityBasedSmFactor ) { - int16_t buf_idx, num_freq_bands, diff_start_band; + int16_t buf_idx, num_freq_bands; + int16_t diff_start_band; int16_t k, l; int16_t nchan_out_woLFE; float *p_power_smooth_prev, *p_power_diff_smooth_prev; @@ -1322,7 +1418,6 @@ void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( /*-----------------------------------------------------------------* * compute target PSDs *-----------------------------------------------------------------*/ - if ( hDirAC->hConfig->enc_param_start_band == 0 ) { diff_start_band = h_dirac_output_synthesis_params->use_onset_filters == 1 ? h_dirac_output_synthesis_params->max_band_decorr : 0; @@ -1350,7 +1445,6 @@ void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( h_dirac_output_synthesis_state->diffuse_responses_square, h_dirac_output_synthesis_state->cy_auto_diff_smooth ); } - /*-----------------------------------------------------------------* * compute variables for stereo transport signal type detection *-----------------------------------------------------------------*/ @@ -1403,7 +1497,14 @@ void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( indexFast = min( l, alphaMaxBinFast ); /* Estimate the smoothness of the directions based on the diffuseness parameter */ + /* TODO: check this, seems buggy in the case of parame estim on the decoder side, + because the pointer here points already to the following subframe, ist this intended?*/ +#ifdef JBM_TSM_ON_TCS + /* Workaround for BE */ + instDirectionSmoothness = 1.0f - hDirAC->diffuseness_vector[diff_md_idx][l]; /* Currently, all subframes have same energy ratio value. */ +#else instDirectionSmoothness = 1.0f - hDirAC->diffuseness_vector[hDirAC->dirac_read_idx][l]; /* Currently, all subframes have same energy ratio value. */ +#endif instDirectionSmoothness = min( max( instDirectionSmoothness, 0.0f ), 1.0f ); /* Average the direction smoothness parameter over time */ @@ -1547,8 +1648,11 @@ void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( /*-----------------------------------------------------------------* * gain interpolation and output streams *-----------------------------------------------------------------*/ - +#ifdef JBM_TSM_ON_TCS + for ( buf_idx = 0; buf_idx < nbslots; ++buf_idx ) +#else for ( buf_idx = 0; buf_idx < hDirAC->subframe_nbslots; ++buf_idx ) +#endif { g1 = h_dirac_output_synthesis_params->interpolator[buf_idx]; g2 = 1.f - g1; @@ -1790,6 +1894,11 @@ void ivas_dirac_dec_compute_directional_responses( DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ const MASA_DECODER_HANDLE hMasa, /* i : MASA decoder structure */ +#ifdef JBM_TSM_ON_TCS + const int16_t *azimuth, + const int16_t *elevation, + const int16_t md_idx, +#endif const float *surCohRatio, const int16_t shd_rot_max_order, /* i : split-order rotation method */ const float *p_Rmat /* i : rotation matrix */ @@ -1805,7 +1914,9 @@ void ivas_dirac_dec_compute_directional_responses( float direct_response_ls[MAX_OUTPUT_CHANNELS]; float direct_response_square[MAX_OUTPUT_CHANNELS]; float *direct_response; +#ifndef JBM_TSM_ON_TCS const int16_t *azimuth, *elevation; +#endif const int16_t *azimuth2, *elevation2; float direct_response_dir2[MAX_OUTPUT_CHANNELS]; float directRatio[MASA_MAXIMUM_DIRECTIONS]; @@ -1826,6 +1937,13 @@ void ivas_dirac_dec_compute_directional_responses( } num_channels_dir = hDirAC->num_outputs_dir; +#ifdef JBM_TSM_ON_TCS + if ( hDirAC->numSimultaneousDirections == 2 ) + { + azimuth2 = hDirAC->azimuth2[md_idx]; + elevation2 = hDirAC->elevation2[md_idx]; + } +#else azimuth = hDirAC->azimuth[hDirAC->dirac_read_idx]; elevation = hDirAC->elevation[hDirAC->dirac_read_idx]; if ( hDirAC->numSimultaneousDirections == 2 ) @@ -1833,6 +1951,7 @@ void ivas_dirac_dec_compute_directional_responses( azimuth2 = hDirAC->azimuth2[hDirAC->dirac_read_idx]; elevation2 = hDirAC->elevation2[hDirAC->dirac_read_idx]; } +#endif codingBand = -1; assert( num_channels_dir <= MAX_OUTPUT_CHANNELS && "Number of channels is too high" ); @@ -1913,18 +2032,29 @@ void ivas_dirac_dec_compute_directional_responses( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD || hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) { /* Synthesize the first direction */ +#ifdef JBM_TSM_ON_TCS + spreadCoherencePanningHoa( azimuth[k], elevation[k], hDirAC->spreadCoherence[md_idx][k], direct_response_hoa, num_channels_dir, hDirAC->hOutSetup.ambisonics_order ); +#else spreadCoherencePanningHoa( azimuth[k], elevation[k], hDirAC->spreadCoherence[hDirAC->dirac_read_idx][k], direct_response_hoa, num_channels_dir, hDirAC->hOutSetup.ambisonics_order ); - +#endif /* Synthesize the second direction and combine the gains */ if ( hDirAC->numSimultaneousDirections == 2 ) { +#ifdef JBM_TSM_ON_TCS + spreadCoherencePanningHoa( azimuth2[k], elevation2[k], hDirAC->spreadCoherence2[md_idx][k], direct_response_dir2, num_channels_dir, hDirAC->hOutSetup.ambisonics_order ); +#else spreadCoherencePanningHoa( azimuth2[k], elevation2[k], hDirAC->spreadCoherence2[hDirAC->dirac_read_idx][k], direct_response_dir2, num_channels_dir, hDirAC->hOutSetup.ambisonics_order ); - +#endif /* Combine gains from the two directions */ +#ifdef JBM_TSM_ON_TCS + totalDirect = hDirAC->energy_ratio1[md_idx][k] + hDirAC->energy_ratio2[md_idx][k] + EPSILON; + directRatio[0] = hDirAC->energy_ratio1[md_idx][k] / totalDirect; + directRatio[1] = hDirAC->energy_ratio2[md_idx][k] / totalDirect; +#else totalDirect = hDirAC->energy_ratio1[hDirAC->dirac_read_idx][k] + hDirAC->energy_ratio2[hDirAC->dirac_read_idx][k] + EPSILON; directRatio[0] = hDirAC->energy_ratio1[hDirAC->dirac_read_idx][k] / totalDirect; directRatio[1] = hDirAC->energy_ratio2[hDirAC->dirac_read_idx][k] / totalDirect; - +#endif for ( l = 0; l < num_channels_dir; l++ ) { direct_response_hoa[l] *= directRatio[0]; @@ -1972,20 +2102,33 @@ void ivas_dirac_dec_compute_directional_responses( else if ( hDirAC->panningConf == DIRAC_PANNING_VBAP ) /*VBAP*/ { /* Synthesize the first direction */ +#ifdef JBM_TSM_ON_TCS + spreadCoherencePanningVbap( azimuth[k], elevation[k], hDirAC->spreadCoherence[md_idx][k], direct_response_ls, num_channels_dir, hVBAPdata ); +#else spreadCoherencePanningVbap( azimuth[k], elevation[k], hDirAC->spreadCoherence[hDirAC->dirac_read_idx][k], direct_response_ls, num_channels_dir, hVBAPdata ); +#endif normalizePanningGains( direct_response_ls, num_channels_dir ); /* Synthesize the second direction and combine the gains */ if ( hDirAC->numSimultaneousDirections == 2 ) { +#ifdef JBM_TSM_ON_TCS + spreadCoherencePanningVbap( azimuth2[k], elevation2[k], hDirAC->spreadCoherence2[md_idx][k], direct_response_dir2, num_channels_dir, hVBAPdata ); +#else spreadCoherencePanningVbap( azimuth2[k], elevation2[k], hDirAC->spreadCoherence2[hDirAC->dirac_read_idx][k], direct_response_dir2, num_channels_dir, hVBAPdata ); - +#endif normalizePanningGains( direct_response_dir2, num_channels_dir ); /* Combine gains from the two directions */ +#ifdef JBM_TSM_ON_TCS + totalDirect = hDirAC->energy_ratio1[md_idx][k] + hDirAC->energy_ratio2[md_idx][k] + EPSILON; + directRatio[0] = hDirAC->energy_ratio1[md_idx][k] / totalDirect; + directRatio[1] = hDirAC->energy_ratio2[md_idx][k] / totalDirect; +#else totalDirect = hDirAC->energy_ratio1[hDirAC->dirac_read_idx][k] + hDirAC->energy_ratio2[hDirAC->dirac_read_idx][k] + EPSILON; directRatio[0] = hDirAC->energy_ratio1[hDirAC->dirac_read_idx][k] / totalDirect; directRatio[1] = hDirAC->energy_ratio2[hDirAC->dirac_read_idx][k] / totalDirect; +#endif for ( l = 0; l < num_channels_dir; l++ ) { direct_response_ls[l] *= directRatio[0]; diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 271b756f7a6658890cf47a5c3b636573f4a53497..26895a5d1f5094b4a1f1956c15144a4e7045b682 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -63,6 +63,11 @@ static ivas_error doSanityChecks_IVAS( Decoder_Struct *st_ivas ); ivas_error ivas_dec_setup( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +#ifdef JBM_TSM_ON_TCS + , + uint16_t *nSamplesRendered, /* o : number of samples flushed from the previous frame (JBM) */ + int16_t *data /* o : flushed PCM samples */ +#endif ) { int16_t k, idx, num_bits_read; @@ -112,10 +117,17 @@ ivas_error ivas_dec_setup( st_ivas->nchan_ism = nchan_ism; +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_ism_dec_config( st_ivas, st_ivas->ism_mode, nSamplesRendered, data ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_ism_dec_config( st_ivas, st_ivas->ism_mode ) ) != IVAS_ERR_OK ) { return error; } +#endif } else if ( st_ivas->ivas_format == SBA_FORMAT ) { @@ -189,7 +201,11 @@ ivas_error ivas_dec_setup( num_bits_read += MC_LS_SETUP_BITS; /* select MC format mode; reconfigure the MC format decoder */ +#ifdef JBM_TSM_ON_TCS + ivas_mc_dec_config( st_ivas, idx, nSamplesRendered, data ); +#else ivas_mc_dec_config( st_ivas, idx ); +#endif } /*-------------------------------------------------------------------* @@ -422,6 +438,7 @@ static ivas_error ivas_read_format( break; case SID_ISM: st_ivas->ivas_format = ISM_FORMAT; + break; case SID_MULTICHANNEL: st_ivas->ivas_format = MC_FORMAT; @@ -1304,6 +1321,7 @@ ivas_error ivas_init_decoder( } else if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) { + if ( ( error = ivas_td_binaural_open( st_ivas ) ) != IVAS_ERR_OK ) { return error; @@ -1316,6 +1334,19 @@ ivas_error ivas_init_decoder( return error; } } +#ifdef JBM_TSM_ON_TCS + if ( st_ivas->hDecoderConfig->voip_active ) + { + int16_t granularity; + int16_t n_channels_transport_jbm; + granularity = NS2SA( st_ivas->hDecoderConfig->output_Fs, FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ); + n_channels_transport_jbm = ivas_jbm_dec_get_num_tc_channels( st_ivas ); + if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, TC_BUFFER_MODE_RENDERER, n_channels_transport_jbm, n_channels_transport_jbm, n_channels_transport_jbm, granularity ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif } else if ( st_ivas->renderer_type == RENDERER_MC ) { @@ -1348,6 +1379,19 @@ ivas_error ivas_init_decoder( } st_ivas->binaural_latency_ns = st_ivas->hCrendWrapper->binaural_latency_ns; +#ifdef JBM_TSM_ON_TCS + if ( st_ivas->hDecoderConfig->voip_active ) + { + int16_t granularity; + int16_t n_channels_transport_jbm; + granularity = NS2SA( st_ivas->hDecoderConfig->output_Fs, FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ); + n_channels_transport_jbm = ivas_jbm_dec_get_num_tc_channels( st_ivas ); + if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, TC_BUFFER_MODE_RENDERER, n_channels_transport_jbm, n_channels_transport_jbm, n_channels_transport_jbm, granularity ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif } if ( st_ivas->ivas_format == ISM_FORMAT && @@ -1444,9 +1488,32 @@ ivas_error ivas_init_decoder( return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to open limiter handle" ); } +#ifdef JBM_TSM_ON_TCS + if ( st_ivas->hDecoderConfig->voip_active && st_ivas->hTcBuffer == NULL ) + { + /* no module has yet open the TC buffer, open a default one */ + int16_t n_channels_transport_jbm = ivas_jbm_dec_get_num_tc_channels( st_ivas ); + if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, ivas_jbm_dec_get_tc_buffer_mode( st_ivas ), n_channels_transport_jbm, n_channels_transport_jbm, n_channels_transport_jbm, NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + if ( st_ivas->hTcBuffer == NULL ) + { + /* we need the handle anyway, but without the buffer*/ + if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, TC_BUFFER_MODE_NONE, 0, 0, 0, 1 ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif + return error; } +#ifdef JBM_TSM_ON_TCS + +#endif /*------------------------------------------------------------------------- * destroy_core_dec() @@ -1667,6 +1734,10 @@ void ivas_initialize_handles_dec( st_ivas->hLsSetupCustom = NULL; st_ivas->hRenderConfig = NULL; +#ifdef JBM_TSM_ON_TCS + st_ivas->hTcBuffer = NULL; +#endif + return; } @@ -1744,6 +1815,9 @@ void ivas_destroy_dec( /* ISM renderer handle */ if ( st_ivas->hIsmRendererData != NULL ) { +#ifdef JBM_TSM_ON_TCS + free( st_ivas->hIsmRendererData->interpolator ); +#endif free( st_ivas->hIsmRendererData ); st_ivas->hIsmRendererData = NULL; } @@ -1859,6 +1933,10 @@ void ivas_destroy_dec( st_ivas->hDecoderConfig = NULL; } +#ifdef JBM_TSM_ON_TCS + ivas_jbm_dec_tc_buffer_close( &st_ivas->hTcBuffer ); +#endif + /* main IVAS handle */ free( st_ivas ); diff --git a/lib_dec/ivas_ism_dec.c b/lib_dec/ivas_ism_dec.c index e4eac7cb610b582f943a965feef67cf9ddfd03d9..5706261093a102b3ffe66ee887b8fc8fd0bea19f 100644 --- a/lib_dec/ivas_ism_dec.c +++ b/lib_dec/ivas_ism_dec.c @@ -32,6 +32,9 @@ #include #include "options.h" +#ifdef JBM_TSM_ON_TCS +#include "prot.h" +#endif #include "ivas_prot.h" #include "ivas_prot_rend.h" #ifdef DEBUGGING @@ -50,6 +53,11 @@ static ivas_error ivas_ism_bitrate_switching( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const int16_t nchan_transport_old, /* i : last number of transport channels */ const ISM_MODE last_ism_mode /* i : last ISM mode */ +#ifdef JBM_TSM_ON_TCS + , + uint16_t *nSamplesRendered, + int16_t *data +#endif ) { ivas_error error; @@ -59,6 +67,16 @@ static ivas_error ivas_ism_bitrate_switching( int16_t numCldfbAnalyses_old, numCldfbSyntheses_old, ism_mode; #endif +#ifdef JBM_TSM_ON_TCS + TC_BUFFER_MODE tc_buffer_mode_new; + int16_t tc_nchan_tc_new; + int16_t tc_nchan_allocate_new; + int16_t tc_granularity_new; + AUDIO_CONFIG intern_config_old; + IVAS_OUTPUT_SETUP hIntSetupOld; + RENDERER_TYPE renderer_type_old; +#endif + error = IVAS_ERR_OK; nCPE_old = st_ivas->nCPE; @@ -101,6 +119,14 @@ static ivas_error ivas_ism_bitrate_switching( return error; } +#ifdef JBM_TSM_ON_TCS + /* save old IntSetup, might be needed for JBM flushing...*/ + intern_config_old = st_ivas->intern_config; + hIntSetupOld = st_ivas->hIntSetup; + tc_granularity_new = 1; + renderer_type_old = st_ivas->renderer_type; +#endif + /*-----------------------------------------------------------------* * Initialize the needed renderer struct and destroy the unnecessary renderer struct *-----------------------------------------------------------------*/ @@ -113,6 +139,39 @@ static ivas_error ivas_ism_bitrate_switching( ivas_output_init( &( st_ivas->hIntSetup ), st_ivas->hDecoderConfig->output_config ); } +#ifdef JBM_TSM_ON_TCS + if ( st_ivas->hDecoderConfig->voip_active ) + { + /* transfer subframe info from DirAC or ParamMC to central tc buffer */ + if ( last_ism_mode == ISM_MODE_PARAM && st_ivas->hDirAC != NULL && ( st_ivas->renderer_type != RENDERER_MONO_DOWNMIX && st_ivas->renderer_type != RENDERER_DISABLE ) ) + { + st_ivas->hTcBuffer->nb_subframes = st_ivas->hDirAC->nb_subframes; + st_ivas->hTcBuffer->subframes_rendered = st_ivas->hDirAC->subframes_rendered; + st_ivas->hTcBuffer->num_slots = st_ivas->hDirAC->num_slots; + st_ivas->hTcBuffer->slots_rendered = st_ivas->hDirAC->slots_rendered; + mvs2s( st_ivas->hDirAC->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); + } + /* JBM: when granularity goes down (e.g. Discrete ISM with TD Obj Renderer -> ParamISM with binaural fastconv + render what still fits in the new granularity */ + tc_granularity_new = ivas_jbm_dec_get_render_granularity( st_ivas->renderer_type, st_ivas->hDecoderConfig->output_Fs ); + if ( tc_granularity_new < st_ivas->hTcBuffer->n_samples_granularity ) + { + if ( ( error = ivas_jbm_dec_flush_renderer( st_ivas, tc_granularity_new, renderer_type_old, intern_config_old, &hIntSetupOld, MC_MODE_NONE, last_ism_mode, nSamplesRendered, data ) ) != IVAS_ERR_OK ) + { + return error; + } + } + /* JBM: when granularity goes up set samples to discard at the beginning of the frame */ + else if ( tc_granularity_new > st_ivas->hTcBuffer->n_samples_granularity ) + { + if ( ( error = ivas_jbm_dec_set_discard_samples( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } +#endif + if ( st_ivas->ism_mode != last_ism_mode ) { /* EFAP handle */ @@ -145,6 +204,9 @@ static ivas_error ivas_ism_bitrate_switching( /* close the ISM renderer and reinitialize */ if ( st_ivas->hIsmRendererData != NULL ) { +#ifdef JBM_TSM_ON_TCS + free( st_ivas->hIsmRendererData->interpolator ); +#endif free( st_ivas->hIsmRendererData ); st_ivas->hIsmRendererData = NULL; } @@ -213,6 +275,9 @@ static ivas_error ivas_ism_bitrate_switching( /* Close the ISM renderer */ if ( st_ivas->hIsmRendererData != NULL ) { +#ifdef JBM_TSM_ON_TCS + free( st_ivas->hIsmRendererData->interpolator ); +#endif free( st_ivas->hIsmRendererData ); st_ivas->hIsmRendererData = NULL; } @@ -247,6 +312,50 @@ static ivas_error ivas_ism_bitrate_switching( } #endif +#ifdef JBM_TSM_ON_TCS + /*-----------------------------------------------------------------* + * Reconfigure TC buffer + *-----------------------------------------------------------------*/ + if ( st_ivas->hDecoderConfig->voip_active == 1 ) + { + int16_t tc_nchan_full_new; + DECODER_TC_BUFFER_HANDLE hTcBuffer; + + hTcBuffer = st_ivas->hTcBuffer; + tc_buffer_mode_new = ivas_jbm_dec_get_tc_buffer_mode( st_ivas ); + tc_nchan_tc_new = ivas_jbm_dec_get_num_tc_channels( st_ivas ); + tc_nchan_allocate_new = tc_nchan_tc_new; + tc_nchan_full_new = tc_nchan_tc_new; + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + tc_nchan_allocate_new = 2 * BINAURAL_CHANNELS; + tc_nchan_full_new = tc_nchan_allocate_new; + } + if ( st_ivas->ism_mode == ISM_MODE_PARAM && ( st_ivas->renderer_type != RENDERER_MONO_DOWNMIX && st_ivas->renderer_type != RENDERER_DISABLE && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + tc_nchan_full_new = 0; + } + /* reconfigure buffer */ + if ( hTcBuffer->tc_buffer_mode != tc_buffer_mode_new || hTcBuffer->nchan_transport_jbm != tc_nchan_tc_new || + hTcBuffer->nchan_buffer_full != tc_nchan_full_new || hTcBuffer->nchan_transport_internal != tc_nchan_allocate_new ) + { + if ( ( error = ivas_jbm_dec_tc_buffer_reconfigure( st_ivas, tc_buffer_mode_new, tc_nchan_tc_new, tc_nchan_allocate_new, tc_nchan_full_new, tc_granularity_new ) ) != IVAS_ERR_OK ) + { + return error; + } + } + /* transfer subframe info from central tc buffer to ParamMC or McMASA (DirAC) */ + if ( st_ivas->hDirAC != NULL ) + { + st_ivas->hDirAC->nb_subframes = st_ivas->hTcBuffer->nb_subframes; + st_ivas->hDirAC->subframes_rendered = st_ivas->hTcBuffer->subframes_rendered; + st_ivas->hDirAC->num_slots = st_ivas->hTcBuffer->num_slots; + st_ivas->hDirAC->slots_rendered = st_ivas->hTcBuffer->slots_rendered; + mvs2s( st_ivas->hTcBuffer->subframe_nbslots, st_ivas->hDirAC->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); + } + } +#endif + return error; } @@ -262,6 +371,11 @@ ivas_error ivas_ism_dec_config( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ , const ISM_MODE last_ism_mode /* i/o: last ISM mode */ +#ifdef JBM_TSM_ON_TCS + , + uint16_t *nSamplesRendered, /* o : number of samples flushed when the renderer granularity changes */ + int16_t *data +#endif ) { int32_t ivas_total_brate; @@ -302,7 +416,11 @@ ivas_error ivas_ism_dec_config( { if ( ( st_ivas->ism_mode != last_ism_mode ) || ( st_ivas->hDecoderConfig->ivas_total_brate != st_ivas->hDecoderConfig->last_ivas_total_brate ) ) { +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_ism_bitrate_switching( st_ivas, nchan_transport_old, last_ism_mode, nSamplesRendered, data ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_ism_bitrate_switching( st_ivas, nchan_transport_old, last_ism_mode ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -325,7 +443,11 @@ ivas_error ivas_ism_dec_config( /* ISM mode switching */ if ( st_ivas->ism_mode != last_ism_mode ) { +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_ism_bitrate_switching( st_ivas, nchan_transport_old, last_ism_mode, nSamplesRendered, data ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_ism_bitrate_switching( st_ivas, nchan_transport_old, last_ism_mode ) ) != IVAS_ERR_OK ) +#endif { return error; } diff --git a/lib_dec/ivas_ism_dtx_dec.c b/lib_dec/ivas_ism_dtx_dec.c index 935db95eea5708afbf995aaa599ac212607d1094..b2bc737fa20367b0ce9f3271f4c82a7567d8c2d7 100644 --- a/lib_dec/ivas_ism_dtx_dec.c +++ b/lib_dec/ivas_ism_dtx_dec.c @@ -133,8 +133,11 @@ ivas_error ivas_ism_dtx_dec( ism_mode_bstr = (ISM_MODE) ( idx + 1 ); st_ivas->ism_mode = ism_mode_bstr; } - +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_ism_dec_config( st_ivas, last_ism_mode, NULL, NULL ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_ism_dec_config( st_ivas, last_ism_mode ) ) != IVAS_ERR_OK ) +#endif { return error; } diff --git a/lib_dec/ivas_ism_param_dec.c b/lib_dec/ivas_ism_param_dec.c index 244bf1f3987925f4b01f3876d3a578d598b9068f..d58887f2da3f5c94448a97e47b1295dbea144bcb 100644 --- a/lib_dec/ivas_ism_param_dec.c +++ b/lib_dec/ivas_ism_param_dec.c @@ -157,7 +157,133 @@ static void ivas_ism_get_proto_matrix( return; } +#ifdef JBM_TSM_ON_TCS +static void ivas_param_ism_collect_slot( + DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ + float *Cldfb_RealBuffer_in, + float *Cldfb_ImagBuffer_in, + const int16_t ch, + float ref_power[], + float cx_diag[][PARAM_ISM_MAX_DMX] ) +{ + + int16_t band_idx, bin_idx; + int16_t brange[2]; + float tmp; + + /* loop over parameter bands to collect transport channel energies */ + for ( band_idx = 0; band_idx < hDirAC->hParamIsm->nbands; band_idx++ ) + { + brange[0] = hDirAC->hParamIsm->band_grouping[band_idx]; + brange[1] = hDirAC->hParamIsm->band_grouping[band_idx + 1]; + for ( bin_idx = brange[0]; bin_idx < brange[1]; bin_idx++ ) + { + tmp = 0.0f; + tmp += ( Cldfb_RealBuffer_in[bin_idx] * Cldfb_RealBuffer_in[bin_idx] ); + tmp += ( Cldfb_ImagBuffer_in[bin_idx] * Cldfb_ImagBuffer_in[bin_idx] ); + cx_diag[bin_idx][ch] += tmp; + ref_power[bin_idx] += tmp; + } + } + return; +} +static void ivas_param_ism_compute_mixing_matrix( + const int16_t nchan_ism, /* i : number of ISM channels */ + DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ + ISM_DTX_DATA_DEC hISMDTX, /* i : ISM DTX handle */ + float direct_response[MAX_NUM_OBJECTS][PARAM_ISM_MAX_CHAN], + const int16_t nchan_transport, + const int16_t nchan_out_woLFE, + float cx_diag[][PARAM_ISM_MAX_DMX], + float ref_power[], + float mixing_matrix[CLDFB_NO_CHANNELS_MAX][PARAM_ISM_MAX_CHAN * PARAM_ISM_MAX_DMX] ) +{ + int16_t band_idx, bin_idx; + int16_t i, w, obj_indx; + int16_t brange[2]; + float direct_power[MAX_NUM_OBJECTS]; + float cy_diag[PARAM_ISM_MAX_CHAN]; + float cy_diag_tmp[MAX_NUM_OBJECTS][PARAM_ISM_MAX_CHAN]; + float *dir_res_ptr; + float *proto_matrix; + float response_matrix[PARAM_ISM_MAX_CHAN * MAX_NUM_OBJECTS]; + int16_t num_wave; + + proto_matrix = hDirAC->hParamIsmRendering->proto_matrix; + + assert( ( nchan_ism == 3 ) || ( nchan_ism == 4 ) ); + assert( nchan_transport == 2 ); + + if ( hDirAC->hParamIsm->flag_noisy_speech || hISMDTX.dtx_flag ) + { + num_wave = nchan_ism; + } + else + { + num_wave = MAX_PARAM_ISM_WAVE; + } + set_zero( response_matrix, PARAM_ISM_MAX_CHAN * MAX_NUM_OBJECTS ); + + /* loop over parameter bands to compute the mixing matrix */ + for ( band_idx = 0; band_idx < hDirAC->hParamIsm->nbands; band_idx++ ) + { + brange[0] = hDirAC->hParamIsm->band_grouping[band_idx]; + brange[1] = hDirAC->hParamIsm->band_grouping[band_idx + 1]; + + /* Compute covaraince matrix from direct response*/ + for ( w = 0; w < num_wave; w++ ) + { + set_zero( cy_diag_tmp[w], nchan_out_woLFE ); + + if ( hDirAC->hParamIsm->flag_noisy_speech || hISMDTX.dtx_flag ) + { + dir_res_ptr = direct_response[w]; + } + else + { + obj_indx = hDirAC->hParamIsm->obj_indices[band_idx][0][w]; + dir_res_ptr = direct_response[obj_indx]; + } + mvr2r( dir_res_ptr, response_matrix + w * nchan_out_woLFE, nchan_out_woLFE ); + /* we only need the diagonal of Cy*/ + matrix_product_diag( dir_res_ptr, nchan_out_woLFE, 1, 0, dir_res_ptr, 1, nchan_out_woLFE, 0, cy_diag_tmp[w] ); + } + + for ( bin_idx = brange[0]; bin_idx < brange[1]; bin_idx++ ) + { + + set_zero( cy_diag, nchan_out_woLFE ); + for ( w = 0; w < num_wave; w++ ) + { + if ( hDirAC->hParamIsm->flag_noisy_speech || hISMDTX.dtx_flag ) + { + direct_power[w] = ( 1.0f / nchan_ism ) * ref_power[bin_idx]; + } + else + { + direct_power[w] = hDirAC->power_ratios[band_idx][0][w] * ref_power[bin_idx]; + } + + if ( direct_power[w] != 0.f ) + { + for ( i = 0; i < nchan_out_woLFE; i++ ) + { + cy_diag[i] += direct_power[w] * cy_diag_tmp[w][i]; + } + } + direct_power[w] = sqrtf( direct_power[w] ); + } + /* Compute mixing matrix */ + computeMixingMatricesISM( nchan_transport, num_wave, nchan_out_woLFE, response_matrix, direct_power, cx_diag[bin_idx], cy_diag, proto_matrix, 1, + PARAM_MC_REG_SX, PARAM_MC_REG_GHAT, mixing_matrix[bin_idx] ); + } + } + + return; +} + +#else static void ivas_param_ism_compute_mixing_matrix( const int16_t nchan_ism, /* i : number of ISM channels */ DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ @@ -276,7 +402,45 @@ static void ivas_param_ism_compute_mixing_matrix( return; } +#endif + +#ifdef JBM_TSM_ON_TCS +static void ivas_param_ism_render_slot( + DIRAC_DEC_HANDLE hDirAC, + float *Cldfb_RealBuffer_in[PARAM_ISM_MAX_DMX], + float *Cldfb_ImagBuffer_in[PARAM_ISM_MAX_DMX], + float Cldfb_RealBuffer[PARAM_ISM_MAX_CHAN][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + float Cldfb_ImagBuffer[PARAM_ISM_MAX_CHAN][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + float mixing_matrix[CLDFB_NO_CHANNELS_MAX][PARAM_ISM_MAX_CHAN * PARAM_ISM_MAX_DMX], + const int16_t interpolator_idx, + const int16_t out_slot_idx, + const int16_t num_ch_LS, + const int16_t nchan_transport ) +{ + int16_t outchIdx, inchIdx, bin_idx; + float tmp_1, mixing_matrix_smooth; + + tmp_1 = hDirAC->hParamIsmRendering->interpolator[interpolator_idx]; + + for ( bin_idx = 0; bin_idx < hDirAC->num_freq_bands; bin_idx++ ) + { + /* smooth the mixing matrix */ + for ( outchIdx = 0; outchIdx < num_ch_LS; outchIdx++ ) + { + for ( inchIdx = 0; inchIdx < nchan_transport; inchIdx++ ) + { + mixing_matrix_smooth = tmp_1 * mixing_matrix[bin_idx][outchIdx + inchIdx * num_ch_LS] + + ( 1 - tmp_1 ) * hDirAC->hParamIsmRendering->mixing_matrix_lin_old[bin_idx][outchIdx + inchIdx * num_ch_LS]; + Cldfb_RealBuffer[outchIdx][out_slot_idx][bin_idx] += mixing_matrix_smooth * Cldfb_RealBuffer_in[inchIdx][bin_idx]; + Cldfb_ImagBuffer[outchIdx][out_slot_idx][bin_idx] += mixing_matrix_smooth * Cldfb_ImagBuffer_in[inchIdx][bin_idx]; + } + } + } + + return; +} +#endif static void ivas_param_ism_rendering( DIRAC_DEC_HANDLE hDirAC, @@ -434,9 +598,19 @@ ivas_error ivas_param_ism_dec_open( *-----------------------------------------------------------------*/ hDirAC->slot_size = (int16_t) ( ( output_Fs / FRAMES_PER_SEC ) / CLDFB_NO_COL_MAX ); +#ifdef JBM_TSM_ON_TCS + hDirAC->hConfig = NULL; + set_s( hDirAC->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set_s( hDirAC->subframe_nbslots, JBM_CLDFB_SLOTS_IN_SUBFRAME, DEFAULT_JBM_SUBFRAMES_5MS ); + hDirAC->nb_subframes = DEFAULT_JBM_SUBFRAMES_5MS; + hDirAC->subframes_rendered = 0; + hDirAC->slots_rendered = 0; + hDirAC->num_slots = DEFAULT_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME; +#else hDirAC->subframe_nbslots = (int16_t) ( CLDFB_NO_COL_MAX * 5.f / 20.f + 0.5f ); hDirAC->nb_subframes = CLDFB_NO_COL_MAX / hDirAC->subframe_nbslots; assert( hDirAC->nb_subframes <= MAX_PARAM_SPATIAL_SUBFRAMES ); +#endif hDirAC->num_freq_bands = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); hDirAC->hParamIsm->nbands = MAX_PARAM_ISM_NBANDS; @@ -468,10 +642,24 @@ ivas_error ivas_param_ism_dec_open( if ( !( output_config == AUDIO_CONFIG_MONO || output_config == AUDIO_CONFIG_STEREO ) ) { /* Initialize Param ISM Rendering handle */ - if ( ( error = ivas_param_ism_rendering_init( hDirAC->hParamIsmRendering, hOutSetup, st_ivas->nchan_transport, CLDFB_NO_COL_MAX, output_config ) ) != IVAS_ERR_OK ) +#ifdef JBM_TSM_ON_TCS + if ( st_ivas->hDecoderConfig->voip_active ) { - return error; + if ( ( error = ivas_param_ism_rendering_init( hDirAC->hParamIsmRendering, hOutSetup, st_ivas->nchan_transport, MAX_JBM_CLDFB_TIMESLOTS, output_config ) ) != IVAS_ERR_OK ) + { + return error; + } } + else + { +#endif + if ( ( error = ivas_param_ism_rendering_init( hDirAC->hParamIsmRendering, hOutSetup, st_ivas->nchan_transport, CLDFB_NO_COL_MAX, output_config ) ) != IVAS_ERR_OK ) + { + return error; + } +#ifdef JBM_TSM_ON_TCS + } +#endif } if ( !( output_config == AUDIO_CONFIG_EXTERNAL || output_config == AUDIO_CONFIG_BINAURAL || output_config == AUDIO_CONFIG_BINAURAL_ROOM || output_config == AUDIO_CONFIG_MONO || output_config == AUDIO_CONFIG_STEREO ) ) @@ -487,14 +675,20 @@ ivas_error ivas_param_ism_dec_open( set_zero( hDirAC->azimuth_values, MAX_NUM_OBJECTS ); set_zero( hDirAC->elevation_values, MAX_NUM_OBJECTS ); +#ifdef JBM_TSM_ON_TCS + hDirAC->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES; +#else hDirAC->dirac_md_buffer_length = 0; +#endif hDirAC->dirac_bs_md_write_idx = 0; hDirAC->dirac_read_idx = 0; hDirAC->spar_to_dirac_write_idx = 0; if ( ( output_config == AUDIO_CONFIG_BINAURAL || output_config == AUDIO_CONFIG_BINAURAL_ROOM ) ) { +#ifndef JBM_TSM_ON_TCS hDirAC->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES; +#endif if ( ( hDirAC->azimuth = (int16_t **) malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); @@ -601,6 +795,54 @@ ivas_error ivas_param_ism_dec_open( st_ivas->hISMDTX.dtx_flag = 0; st_ivas->hDirAC = hDirAC; +#ifdef JBM_TSM_ON_TCS + if ( st_ivas->hDecoderConfig->voip_active ) + { + if ( st_ivas->renderer_type != RENDERER_MONO_DOWNMIX && st_ivas->renderer_type != RENDERER_DISABLE ) + { + int16_t nchan_transport = st_ivas->nchan_transport; + int16_t nchan_full = 0; + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) + { + nchan_full = nchan_transport; + hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc = NULL; + hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc = NULL; + } + else + { + hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc = (float *) malloc( MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hDirAC->num_freq_bands * sizeof( float ) ); + set_zero( hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc, MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hDirAC->num_freq_bands ); + hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc = (float *) malloc( MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hDirAC->num_freq_bands * sizeof( float ) ); + set_zero( hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc, MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hDirAC->num_freq_bands ); + } + if ( st_ivas->hTcBuffer == NULL ) + { + if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, TC_BUFFER_MODE_RENDERER, nchan_transport, nchan_transport, nchan_full, NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + else + { + hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc = NULL; + hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc = NULL; + if ( st_ivas->hTcBuffer == NULL ) + { + int16_t nchan_to_allocate = st_ivas->hDecoderConfig->nchan_out; + if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, TC_BUFFER_MODE_BUFFER, nchan_to_allocate, nchan_to_allocate, nchan_to_allocate, NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + } + else + { + hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc = NULL; + hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc = NULL; + } +#endif pop_wmops(); return error; @@ -777,6 +1019,19 @@ void ivas_param_ism_dec_close( } } +#ifdef JBM_TSM_ON_TCS + if ( hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc != NULL ) + { + free( hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc ); + hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc = NULL; + } + if ( hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc != NULL ) + { + free( hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc ); + hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc = NULL; + } +#endif + if ( hDirAC->hParamIsmRendering != NULL ) { free( hDirAC->hParamIsmRendering ); @@ -804,7 +1059,10 @@ void ivas_param_ism_dec( int16_t ch, nchan_transport, nchan_out, nchan_out_woLFE, i; int16_t subframe_idx, slot_idx, index_slot, bin_idx; int32_t ivas_total_brate; - +#ifdef JBM_TSM_ON_TCS + float ref_power[CLDFB_NO_CHANNELS_MAX]; + float cx_diag[CLDFB_NO_CHANNELS_MAX][PARAM_ISM_MAX_DMX]; +#endif /* CLDFB Input Buffers */ float Cldfb_RealBuffer_in[PARAM_ISM_MAX_DMX][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; float Cldfb_ImagBuffer_in[PARAM_ISM_MAX_DMX][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; @@ -846,6 +1104,15 @@ void ivas_param_ism_dec( push_wmops( "ivas_param_ism_dec" ); +#ifdef JBM_TSM_ON_TCS + /* set buffers to zero */ + for ( bin_idx = 0; bin_idx < CLDFB_NO_CHANNELS_MAX; bin_idx++ ) + { + set_zero( cx_diag[bin_idx], PARAM_ISM_MAX_DMX ); + } + set_zero( ref_power, CLDFB_NO_CHANNELS_MAX ); +#endif + /* Frame-level Processing */ /* De-quantization */ if ( !( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA ) ) @@ -910,6 +1177,10 @@ void ivas_param_ism_dec( for ( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX; slot_idx++ ) { cldfbAnalysis_ts( &( output_f[ch][hDirAC->num_freq_bands * slot_idx] ), Cldfb_RealBuffer_in[ch][slot_idx], Cldfb_ImagBuffer_in[ch][slot_idx], hDirAC->num_freq_bands, st_ivas->cldfbAnaDec[ch] ); + +#ifdef JBM_TSM_ON_TCS + ivas_param_ism_collect_slot( hDirAC, Cldfb_RealBuffer_in[ch][slot_idx], Cldfb_ImagBuffer_in[ch][slot_idx], ch, ref_power, cx_diag ); +#endif } } @@ -920,26 +1191,41 @@ void ivas_param_ism_dec( } /* Compute mixing matrix */ +#ifdef JBM_TSM_ON_TCS + ivas_param_ism_compute_mixing_matrix( st_ivas->nchan_ism, hDirAC, st_ivas->hISMDTX, direct_response, nchan_transport, nchan_out_woLFE, cx_diag, ref_power, mixing_matrix ); +#else ivas_param_ism_compute_mixing_matrix( st_ivas->nchan_ism, hDirAC, st_ivas->hISMDTX, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, direct_response, nchan_transport, nchan_out_woLFE, 0, CLDFB_NO_COL_MAX, mixing_matrix ); - +#endif /* subframe loop for synthesis*/ for ( subframe_idx = 0; subframe_idx < hDirAC->nb_subframes; subframe_idx++ ) { +#ifdef JBM_TSM_ON_TCS + uint16_t slot_idx_start = subframe_idx * hDirAC->subframe_nbslots[subframe_idx]; +#else uint16_t slot_idx_start = subframe_idx * hDirAC->subframe_nbslots; +#endif uint16_t idx_in; uint16_t idx_lfe; /* Set some memories to zero */ for ( ch = 0; ch < nchan_out_woLFE; ch++ ) { +#ifdef JBM_TSM_ON_TCS + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) +#else for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots; slot_idx++ ) +#endif { set_f( Cldfb_RealBuffer[ch][slot_idx], 0.0f, hDirAC->num_freq_bands ); set_f( Cldfb_ImagBuffer[ch][slot_idx], 0.0f, hDirAC->num_freq_bands ); } } +#ifdef JBM_TSM_ON_TCS + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) +#else for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots; slot_idx++ ) +#endif { index_slot = slot_idx_start + slot_idx; @@ -957,8 +1243,11 @@ void ivas_param_ism_dec( { if ( ( hSetup.num_lfe > 0 ) && ( hSetup.index_lfe[idx_lfe] == ch ) ) { +#ifdef JBM_TSM_ON_TCS + set_zero( &( output_f[ch][slot_idx_start * hDirAC->num_freq_bands] ), hDirAC->subframe_nbslots[subframe_idx] * hDirAC->num_freq_bands ); +#else set_zero( &( output_f[ch][slot_idx_start * hDirAC->num_freq_bands] ), hDirAC->subframe_nbslots * hDirAC->num_freq_bands ); - +#endif if ( idx_lfe < ( hSetup.num_lfe - 1 ) ) { idx_lfe++; @@ -970,14 +1259,22 @@ void ivas_param_ism_dec( float *ImagBuffer[16]; /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ +#ifdef JBM_TSM_ON_TCS + for ( i = 0; i < hDirAC->subframe_nbslots[subframe_idx]; i++ ) +#else for ( i = 0; i < hDirAC->subframe_nbslots; i++ ) +#endif { RealBuffer[i] = Cldfb_RealBuffer[idx_in][i]; ImagBuffer[i] = Cldfb_ImagBuffer[idx_in][i]; } - +#ifdef JBM_TSM_ON_TCS + cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][slot_idx_start * hDirAC->num_freq_bands] ), + hDirAC->num_freq_bands * hDirAC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch] ); +#else cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][slot_idx_start * hDirAC->num_freq_bands] ), hDirAC->num_freq_bands * hDirAC->subframe_nbslots, st_ivas->cldfbSynDec[ch] ); +#endif idx_in++; } @@ -1008,6 +1305,402 @@ void ivas_param_ism_dec( return; } +#ifdef JBM_TSM_ON_TCS +void ivas_ism_dec_digest_tc( + Decoder_Struct *st_ivas ) +{ + + ivas_jbm_dec_td_renderers_adapt_subframes( st_ivas ); + + if ( + st_ivas->renderer_type == RENDERER_TD_PANNING || + st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC || + st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || + st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM || + ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM && st_ivas->hDecoderConfig->Opt_Headrotation == 0 ) ) + { + int16_t i, num_objects; + int16_t azimuth, elevation; + /* we have a full frame interpolator, adapt it */ + /* for BE testing */ + if ( ( st_ivas->hDecoderConfig->output_Fs / (int32_t) FRAMES_PER_SECOND ) == st_ivas->hTcBuffer->n_samples_available ) + { + int16_t interpolator_length = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / (int32_t) FRAMES_PER_SECOND ); + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) + { + st_ivas->hIsmRendererData->interpolator[0] = 0.0f; + for ( i = 1; i < interpolator_length; i++ ) + { + st_ivas->hIsmRendererData->interpolator[i] = st_ivas->hIsmRendererData->interpolator[i - 1] + 1.f / ( interpolator_length - 1 ); + } + } + else + { + for ( i = 0; i < interpolator_length; i++ ) + { + st_ivas->hIsmRendererData->interpolator[i] = (float) i / ( (float) interpolator_length - 1 ); + } + } + } + else + { + ivas_jbm_dec_get_adapted_linear_interpolator( (int16_t) ( st_ivas->hDecoderConfig->output_Fs / (int32_t) FRAMES_PER_SECOND ), + st_ivas->hTcBuffer->n_samples_available, + st_ivas->hIsmRendererData->interpolator ); + } + /* also get the gains here */ + num_objects = st_ivas->nchan_transport; + for ( i = 0; i < num_objects; i++ ) + { + mvr2r( st_ivas->hIsmRendererData->gains[i], st_ivas->hIsmRendererData->prev_gains[i], MAX_OUTPUT_CHANNELS ); + if ( st_ivas->intern_config == AUDIO_CONFIG_STEREO ) + { + ivas_ism_get_stereo_gains( st_ivas->hIsmMetaData[i]->azimuth, + st_ivas->hIsmMetaData[i]->elevation, + &st_ivas->hIsmRendererData->gains[i][0], + &st_ivas->hIsmRendererData->gains[i][1] ); + } + else + { + // TODO tmu review when #215 is resolved + azimuth = (int16_t) floorf( st_ivas->hIsmMetaData[i]->azimuth + 0.5f ); + elevation = (int16_t) floorf( st_ivas->hIsmMetaData[i]->elevation + 0.5f ); + if ( ( st_ivas->renderer_type == RENDERER_TD_PANNING || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) && st_ivas->hHeadTrackData == NULL ) + { + + + if ( st_ivas->hIntSetup.is_planar_setup ) + { + /* If no elevation support in output format, then rendering should be done with zero elevation */ + elevation = 0; + } + if ( st_ivas->hEFAPdata != NULL ) + { + efap_determine_gains( st_ivas->hEFAPdata, st_ivas->hIsmRendererData->gains[i], azimuth, elevation, EFAP_MODE_EFAP ); + } + } + else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) + { + /*get HOA gets for direction (ACN/SN3D)*/ + ivas_dirac_dec_get_response( azimuth, elevation, st_ivas->hIsmRendererData->gains[i], st_ivas->hIntSetup.ambisonics_order ); + } + } + } + } + return; +} + +void ivas_param_ism_dec_digest_tc( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const uint16_t nCldfbSlots, /* i : number of CLFBS slots in the transport channels */ + float *transport_channels_f[] /* i : synthesized core-coder transport channels/DirAC output */ +) +{ + int16_t ch, nchan_transport, nchan_out, nchan_out_woLFE, i; + int16_t slot_idx, bin_idx; + int32_t ivas_total_brate; + float ref_power[CLDFB_NO_CHANNELS_MAX]; + float cx_diag[CLDFB_NO_CHANNELS_MAX][PARAM_ISM_MAX_DMX]; + /* Direct Response/EFAP Gains */ + float direct_response[MAX_NUM_OBJECTS][PARAM_ISM_MAX_CHAN]; + + DIRAC_DEC_HANDLE hDirAC; + + /* Initialization */ + hDirAC = st_ivas->hDirAC; + assert( hDirAC ); + + nchan_transport = st_ivas->nchan_transport; + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + + if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) + { + nchan_out = st_ivas->nchan_ism; + nchan_out_woLFE = nchan_out; + st_ivas->hDecoderConfig->nchan_out = nchan_out; + } + else + { + nchan_out = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; + nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE; + } + + push_wmops( "ivas_param_ism_dec" ); + + /* general setup */ + ivas_jbm_dec_get_adapted_linear_interpolator( DEFAULT_JBM_CLDFB_TIMESLOTS, nCldfbSlots, hDirAC->hParamIsmRendering->interpolator ); + + ivas_dirac_dec_set_md_map( st_ivas, nCldfbSlots ); + + /* set buffers to zero */ + for ( bin_idx = 0; bin_idx < CLDFB_NO_CHANNELS_MAX; bin_idx++ ) + { + set_zero( cx_diag[bin_idx], PARAM_ISM_MAX_DMX ); + } + set_zero( ref_power, CLDFB_NO_CHANNELS_MAX ); + + /* Frame-level Processing */ + /* De-quantization */ + if ( !( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA ) ) + { + ivas_param_ism_dec_dequant_DOA( hDirAC, st_ivas->nchan_ism ); + ivas_param_ism_dec_dequant_powrat( hDirAC ); + st_ivas->hISMDTX.dtx_flag = 0; + } + else + { + st_ivas->hISMDTX.dtx_flag = 1; + } + + /* obtain the direct response using EFAP */ + if ( !( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) ) + { + for ( i = 0; i < st_ivas->nchan_ism; i++ ) + { + efap_determine_gains( st_ivas->hEFAPdata, direct_response[i], hDirAC->azimuth_values[i], hDirAC->elevation_values[i], EFAP_MODE_EFAP ); + } + } + else + { + int16_t j; + + for ( i = 0; i < st_ivas->nchan_ism; i++ ) + { + for ( j = 0; j < nchan_out_woLFE; j++ ) + { + if ( i == j ) + { + direct_response[i][j] = 1.0f; + } + else + { + direct_response[i][j] = 0.0f; + } + } + } + + for ( i = 0; i < nchan_transport; i++ ) + { + for ( j = 0; j < nchan_out_woLFE; j++ ) + { + if ( i == j ) + { + hDirAC->hParamIsmRendering->proto_matrix[( i * nchan_out_woLFE ) + j] = 1.0f; + } + else + { + hDirAC->hParamIsmRendering->proto_matrix[( i * nchan_out_woLFE ) + j] = 0.0f; + } + } + } + } + + for ( ch = 0; ch < nchan_transport; ch++ ) + { + /*-----------------------------------------------------------------* + * CLDFB Analysis + *-----------------------------------------------------------------*/ + for ( slot_idx = 0; slot_idx < nCldfbSlots; slot_idx++ ) + { + float RealBuffer[CLDFB_NO_CHANNELS_MAX]; + float ImagBuffer[CLDFB_NO_CHANNELS_MAX]; + + cldfbAnalysis_ts( &( transport_channels_f[ch][hDirAC->num_freq_bands * slot_idx] ), RealBuffer, ImagBuffer, hDirAC->num_freq_bands, st_ivas->cldfbAnaDec[ch] ); + mvr2r( RealBuffer, &hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc[slot_idx * hDirAC->num_freq_bands * nchan_transport + ch * hDirAC->num_freq_bands], hDirAC->num_freq_bands ); + mvr2r( ImagBuffer, &hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc[slot_idx * hDirAC->num_freq_bands * nchan_transport + ch * hDirAC->num_freq_bands], hDirAC->num_freq_bands ); + + ivas_param_ism_collect_slot( hDirAC, RealBuffer, ImagBuffer, ch, ref_power, cx_diag ); + } + } + + /* Obtain Mixing Matrix on a frame-level */ + for ( bin_idx = 0; bin_idx < hDirAC->num_freq_bands; bin_idx++ ) + { + set_f( hDirAC->hParamIsmRendering->mixing_matrix_lin[bin_idx], 0.0f, nchan_transport * nchan_out_woLFE ); + } + + /* Compute mixing matrix */ + ivas_param_ism_compute_mixing_matrix( st_ivas->nchan_ism, hDirAC, st_ivas->hISMDTX, direct_response, nchan_transport, nchan_out_woLFE, cx_diag, ref_power, hDirAC->hParamIsmRendering->mixing_matrix_lin ); + + + pop_wmops(); + + return; +} + +static void ivas_ism_param_dec_render_sf( Decoder_Struct *st_ivas, + IVAS_OUTPUT_SETUP hSetup, + const int16_t nchan_transport, + const int16_t nchan_out, + const int16_t nchan_out_woLFE, + float *output_f[] /* o : rendered time signal */ +) +{ + + int16_t ch, slot_idx, i, index_slot; + /* CLDFB Output Buffers */ + float Cldfb_RealBuffer[PARAM_ISM_MAX_CHAN][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer[PARAM_ISM_MAX_CHAN][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float *Cldfb_RealBuffer_in[PARAM_ISM_MAX_DMX]; + float *Cldfb_ImagBuffer_in[PARAM_ISM_MAX_DMX]; + DIRAC_DEC_HANDLE hDirAC; + + int16_t slot_idx_start; + int16_t idx_in; + int16_t idx_lfe; + int16_t subframe_idx; + + hDirAC = st_ivas->hDirAC; + slot_idx_start = hDirAC->slots_rendered; + subframe_idx = hDirAC->subframes_rendered; + + /* Set some memories to zero */ + for ( ch = 0; ch < nchan_out_woLFE; ch++ ) + { + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + set_f( Cldfb_RealBuffer[ch][slot_idx], 0.0f, hDirAC->num_freq_bands ); + set_f( Cldfb_ImagBuffer[ch][slot_idx], 0.0f, hDirAC->num_freq_bands ); + } + } + + for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + index_slot = slot_idx_start + slot_idx; + + for ( ch = 0; ch < nchan_transport; ch++ ) + { + Cldfb_RealBuffer_in[ch] = &hDirAC->hParamIsmRendering->Cldfb_RealBuffer_tc[index_slot * hDirAC->num_freq_bands * nchan_transport + ch * hDirAC->num_freq_bands]; + Cldfb_ImagBuffer_in[ch] = &hDirAC->hParamIsmRendering->Cldfb_ImagBuffer_tc[index_slot * hDirAC->num_freq_bands * nchan_transport + ch * hDirAC->num_freq_bands]; + } + + + /* Compute bandwise rendering to target LS using covariance rendering */ + ivas_param_ism_render_slot( hDirAC, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, + Cldfb_RealBuffer, Cldfb_ImagBuffer, hDirAC->hParamIsmRendering->mixing_matrix_lin, index_slot, slot_idx, + nchan_out_woLFE, nchan_transport ); + } + + /* CLDFB Synthesis */ + idx_in = 0; + idx_lfe = 0; + + for ( ch = 0; ch < nchan_out; ch++ ) + { + if ( ( hSetup.num_lfe > 0 ) && ( hSetup.index_lfe[idx_lfe] == ch ) ) + { + set_zero( output_f[ch], hDirAC->subframe_nbslots[subframe_idx] * hDirAC->num_freq_bands ); + if ( idx_lfe < ( hSetup.num_lfe - 1 ) ) + { + idx_lfe++; + } + } + else + { + float *RealBuffer[16]; + float *ImagBuffer[16]; + + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ + for ( i = 0; i < hDirAC->subframe_nbslots[subframe_idx]; i++ ) + { + RealBuffer[i] = Cldfb_RealBuffer[idx_in][i]; + ImagBuffer[i] = Cldfb_ImagBuffer[idx_in][i]; + } + cldfbSynthesis( RealBuffer, ImagBuffer, output_f[ch], + hDirAC->num_freq_bands * hDirAC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch] ); + idx_in++; + } + } + hDirAC->slots_rendered += hDirAC->subframe_nbslots[subframe_idx]; + hDirAC->subframes_rendered++; +} + +void ivas_param_ism_dec_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ + uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ + uint16_t *nSamplesAvailable, /* o : number of CLDFB slots still to render */ + float *output_f[] /* o : rendered time signal */ +) +{ + int16_t ch, slots_to_render, first_sf, last_sf, subframe_idx; + uint16_t slot_size, n_samples_sf; + DIRAC_DEC_HANDLE hDirAC; + IVAS_OUTPUT_SETUP hSetup; + int16_t nchan_transport, nchan_out, nchan_out_woLFE; + float *output_f_local[MAX_OUTPUT_CHANNELS]; + + hDirAC = st_ivas->hDirAC; + hSetup = st_ivas->hIntSetup; +#ifdef DEBUGGING + assert( hDirAC ); +#endif + nchan_transport = st_ivas->nchan_transport; + if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) + { + nchan_out = st_ivas->nchan_ism; + nchan_out_woLFE = nchan_out; + st_ivas->hDecoderConfig->nchan_out = nchan_out; + } + else + { + nchan_out = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; + nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE; + } + slot_size = NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); + /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ + slots_to_render = min( hDirAC->num_slots - hDirAC->slots_rendered, nSamplesAsked / slot_size ); + *nSamplesRendered = slots_to_render * slot_size; + first_sf = hDirAC->subframes_rendered; + last_sf = first_sf; + while ( slots_to_render > 0 ) + { + slots_to_render -= hDirAC->subframe_nbslots[last_sf]; + last_sf++; + } +#ifdef DEBUGGING + assert( slots_to_render == 0 ); +#endif + for ( ch = 0; ch < nchan_out; ch++ ) + { + output_f_local[ch] = &output_f[ch][0]; + } + for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + { + ivas_ism_param_dec_render_sf( st_ivas, hSetup, nchan_transport, nchan_out, nchan_out_woLFE, output_f_local ); + n_samples_sf = hDirAC->subframe_nbslots[subframe_idx] * st_ivas->hDirAC->slot_size; + for ( ch = 0; ch < nchan_out; ch++ ) + { + output_f_local[ch] += n_samples_sf; + } + } + if ( hDirAC->slots_rendered == hDirAC->num_slots ) + { + /* copy the memories */ + /* store mixing matrix for next subframe */ + ivas_param_ism_update_mixing_matrix( hDirAC, hDirAC->hParamIsmRendering->mixing_matrix_lin, nchan_transport, nchan_out_woLFE ); + + /* store MetaData parameters */ + for ( ch = 0; ch < st_ivas->nchan_ism; ch++ ) + { + if ( st_ivas->hDirAC->azimuth_values[ch] > 180.0f ) + { + st_ivas->hIsmMetaData[ch]->azimuth = st_ivas->hDirAC->azimuth_values[ch] - 360.0f; + } + else + { + st_ivas->hIsmMetaData[ch]->azimuth = st_ivas->hDirAC->azimuth_values[ch]; + } + + st_ivas->hIsmMetaData[ch]->elevation = st_ivas->hDirAC->elevation_values[ch]; + } + } + *nSamplesAvailable = ( hDirAC->num_slots - hDirAC->slots_rendered ) * slot_size; + return; +} + +#endif + /*-------------------------------------------------------------------------* * ivas_param_ism_params_to_masa_param_mapping() diff --git a/lib_dec/ivas_ism_renderer.c b/lib_dec/ivas_ism_renderer.c index 06f5f18467d22b9aab921d93dee89494702a1db5..95c153fc807fd19d529eecd4aa4de64a2d4c8ed6 100644 --- a/lib_dec/ivas_ism_renderer.c +++ b/lib_dec/ivas_ism_renderer.c @@ -58,6 +58,9 @@ ivas_error ivas_ism_renderer_open( { int16_t i; uint16_t interpolator_length; +#ifdef JBM_TSM_ON_TCS + uint16_t init_interpolator_length; +#endif ivas_error error; error = IVAS_ERR_OK; @@ -78,14 +81,34 @@ ivas_error ivas_ism_renderer_open( for ( i = 0; i < MAX_NUM_OBJECTS; i++ ) { set_f( st_ivas->hIsmRendererData->prev_gains[i], 0.0f, MAX_OUTPUT_CHANNELS ); +#ifdef JBM_TSM_ON_TCS + set_f( st_ivas->hIsmRendererData->gains[i], 0.0f, MAX_OUTPUT_CHANNELS ); +#endif } +#ifdef JBM_TSM_ON_TCS + if ( st_ivas->hDecoderConfig->voip_active ) + { + init_interpolator_length = NS2SA( st_ivas->hDecoderConfig->output_Fs, MAX_JBM_CLDFB_TIMESLOTS * CLDFB_SLOT_NS ); + interpolator_length = (uint16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ); + } + else + { + init_interpolator_length = (uint16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ); + interpolator_length = init_interpolator_length; + } + st_ivas->hIsmRendererData->interpolator = (float *) malloc( sizeof( float ) * init_interpolator_length ); + for ( i = 0; i < interpolator_length; i++ ) + { + st_ivas->hIsmRendererData->interpolator[i] = (float) i / ( (float) interpolator_length - 1 ); + } +#else interpolator_length = (uint16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ); for ( i = 0; i < interpolator_length; i++ ) { st_ivas->hIsmRendererData->interpolator[i] = (float) i / ( (float) interpolator_length - 1 ); } - +#endif return error; } @@ -97,9 +120,13 @@ ivas_error ivas_ism_renderer_open( *-------------------------------------------------------------------------*/ void ivas_ism_render( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ +#ifdef JBM_TSM_ON_TCS + float *output_f[], /* i/o: core-coder transport channels/object output */ +#else float output_f[][L_FRAME48k], /* i/o: core-coder transport channels/object output */ - const int16_t output_frame /* i : output frame length per channel */ +#endif + const int16_t output_frame /* i : output frame length per channel */ ) { int16_t i, j, k, j2; @@ -205,6 +232,87 @@ void ivas_ism_render( return; } +#ifdef JBM_TSM_ON_TCS +void ivas_ism_render_sf( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float *output_f[], /* i/o: core-coder transport channels/object output */ + const int16_t n_samples_to_render /* i : output frame length per channel */ +) +{ + int16_t i, j, k, j2; + float *g1, g2, *tc; + int16_t num_objects, nchan_out_woLFE, lfe_index; + int16_t azimuth, elevation; + int16_t tc_offset; + int16_t interp_offset; + float Rmat[3][3]; + float gain, prev_gain; + + num_objects = st_ivas->nchan_transport; + nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE; + + tc_offset = st_ivas->hTcBuffer->n_samples_rendered; + interp_offset = st_ivas->hTcBuffer->n_samples_rendered; + + for ( i = 0; i < nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; i++ ) + { + set_f( output_f[i], 0.0f, n_samples_to_render ); + } + + if ( st_ivas->hHeadTrackData != NULL && st_ivas->hHeadTrackData->num_quaternions >= 0 ) + { + /* Calculate rotation matrix from the quaternion */ + QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[st_ivas->hHeadTrackData->num_quaternions++], Rmat ); + ivas_jbm_dec_get_adapted_linear_interpolator( n_samples_to_render, + n_samples_to_render, + st_ivas->hIsmRendererData->interpolator ); + interp_offset = 0; + } + + for ( i = 0; i < num_objects; i++ ) + { + + /* Head rotation: rotate the object positions depending the head's orientation */ + if ( st_ivas->hHeadTrackData != NULL && st_ivas->hHeadTrackData->num_quaternions >= 0 ) + { + rotateAziEle( st_ivas->hIsmMetaData[i]->azimuth, st_ivas->hIsmMetaData[i]->elevation, &azimuth, &elevation, Rmat, st_ivas->hIntSetup.is_planar_setup ); + if ( st_ivas->hEFAPdata != NULL ) + { + efap_determine_gains( st_ivas->hEFAPdata, st_ivas->hIsmRendererData->gains[i], azimuth, elevation, EFAP_MODE_EFAP ); + } + } + + lfe_index = 0; + for ( j = 0, j2 = 0; j < nchan_out_woLFE; j++, j2++ ) + { + if ( ( st_ivas->hIntSetup.num_lfe > 0 ) && ( st_ivas->hIntSetup.index_lfe[lfe_index] == j ) ) + { + ( lfe_index < ( st_ivas->hIntSetup.num_lfe - 1 ) ) ? ( lfe_index++, j2++ ) : j2++; + } + + gain = st_ivas->hIsmRendererData->gains[i][j]; + prev_gain = st_ivas->hIsmRendererData->prev_gains[i][j]; + if ( fabsf( gain ) > 0.0f || fabsf( prev_gain ) > 0.0f ) + { + g1 = &st_ivas->hIsmRendererData->interpolator[interp_offset]; + tc = &st_ivas->hTcBuffer->tc[i][tc_offset]; + for ( k = 0; k < n_samples_to_render; k++ ) + { + g2 = 1.0f - *g1; + output_f[j2][k] += ( *( g1++ ) * gain + g2 * prev_gain ) * *( tc++ ); + } + } + /* update here only in case of head rotation */ + if ( st_ivas->hHeadTrackData != NULL && st_ivas->hHeadTrackData->num_quaternions >= 0 ) + { + st_ivas->hIsmRendererData->prev_gains[i][j] = gain; + } + } + } + return; +} +#endif + /*-------------------------------------------------------------------------* * ivas_ism_get_stereo_gains() diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c new file mode 100644 index 0000000000000000000000000000000000000000..13a062fd9312a68e0d2b27d22c07c5a2f7a180e5 --- /dev/null +++ b/lib_dec/ivas_jbm_dec.c @@ -0,0 +1,1742 @@ +/****************************************************************************************************** + + (C) 2022-2023 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 "ivas_cnst.h" +#include "rom_com.h" +#include "prot.h" +#include "ivas_prot.h" +#include "ivas_prot_rend.h" +#include "ivas_rom_com.h" +#include +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + + +#ifdef JBM_TSM_ON_TCS + +/*-----------------------------------------------------------------------* + * Local function prototypes + *-----------------------------------------------------------------------*/ +static void ivas_jbm_dec_copy_tc( Decoder_Struct *st_ivas, const int16_t nSamplesForRendering, int16_t *nSamplesResidual, float *data, float *tc_digest_f[] ); +static void ivas_jbm_dec_tc_buffer_playout( Decoder_Struct *st_ivas, const uint16_t nSamplesAsked, uint16_t *nSamplesRendered, float *output[] ); + + +/*--------------------------------------------------------------------------* + * ivas_jbm_dec_tc() + * + * Principal IVAS decoder routine, decoding of metadata and transport channels + *--------------------------------------------------------------------------*/ +ivas_error ivas_jbm_dec_tc( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float *data /* o : transport channel signal */ +) +{ + int16_t n, output_frame, nchan_out; + Decoder_State *st; /* used for bitstream handling */ + float output[MAX_TRANSPORT_CHANNELS][L_FRAME48k]; /* 'float' buffer for transport channels, MAX_TRANSPORT_CHANNELS channels */ /* IVAS_fmToDo: buffer can be allocated dynamically based on the actual number of output channels */ + int16_t nchan_remapped; + float output_lfe_ch[L_FRAME48k]; + int16_t nb_bits_metadata[MAX_SCE]; + int32_t output_Fs, ivas_total_brate; + AUDIO_CONFIG output_config; + ivas_error error; + float *p_output[MAX_TRANSPORT_CHANNELS]; + + error = IVAS_ERR_OK; + + push_wmops( "ivas_jbm_dec_tc" ); + + /*----------------------------------------------------------------* + * Initialization of local vars after struct has been set + *----------------------------------------------------------------*/ + + output_Fs = st_ivas->hDecoderConfig->output_Fs; + nchan_out = st_ivas->hTcBuffer->nchan_transport_jbm; + output_config = st_ivas->hDecoderConfig->output_config; + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + + output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); + + for ( n = 0; n < MAX_TRANSPORT_CHANNELS; n++ ) + { + p_output[n] = &output[n][0]; + } + + /*----------------------------------------------------------------* + * Decoding + Rendering + *----------------------------------------------------------------*/ + + if ( st_ivas->bfi && st_ivas->ini_frame == 0 ) + { + /* zero output when first frame(s) is lost */ + for ( n = 0; n < nchan_out; n++ ) + { + set_f( output[n], 0.0f, output_frame ); + } + +#ifdef DEBUG_MODE_INFO + create_sce_dec( st_ivas, 0, ivas_total_brate ); + output_debug_mode_info_dec( st_ivas->hSCE[0]->hCoreCoder, 1, output_frame, NULL ); + destroy_sce_dec( st_ivas->hSCE[0] ); + st_ivas->hSCE[0] = NULL; +#endif + } + else if ( st_ivas->ivas_format == STEREO_FORMAT ) + { + st_ivas->hCPE[0]->element_brate = ivas_total_brate; + + if ( ( error = ivas_cpe_dec( st_ivas, 0, output, output_frame, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* HP filtering */ + for ( n = 0; n < min( nchan_out, st_ivas->nchan_transport ); n++ ) + { + hp20( output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } + if ( st_ivas->renderer_type == RENDERER_MC && st_ivas->hDecoderConfig->nchan_out == 1 ) + { +#ifdef MC_PARAMUPMIX_MODE + ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, p_output, p_output ); +#else + ivas_ls_setup_conversion( st_ivas, output_frame, p_output, p_output ); +#endif + } + } + else if ( st_ivas->ivas_format == ISM_FORMAT ) + { + /* Metadata decoding and configuration */ + if ( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA ) + { + if ( ( error = ivas_ism_dtx_dec( st_ivas, nb_bits_metadata ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + // VE: call ivas_ism_metadata_dec() with 'st_ivas' - TBD + if ( ( error = ivas_ism_metadata_dec( ivas_total_brate, st_ivas->nchan_ism, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, st_ivas->hDirAC->hParamIsm, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else /* ISM_MODE_DISC */ + { + if ( ( error = ivas_ism_metadata_dec( ivas_total_brate, st_ivas->nchan_ism, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, NULL, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + for ( n = 0; n < st_ivas->nchan_transport; n++ ) + { + if ( ( error = ivas_sce_dec( st_ivas, n, &output[n], output_frame, nb_bits_metadata[n] ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* HP filtering */ + hp20( output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } + if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) + { + ivas_mono_downmix_render_passive( st_ivas, output, output_frame ); + } + } + else if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) + { + set_s( nb_bits_metadata, 0, MAX_SCE ); + + /* read parameters from the bitstream */ + if ( st_ivas->hQMetaData != NULL && st_ivas->sba_mode != SBA_MODE_SPAR ) + { + st = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0] : st_ivas->hCPE[0]->hCoreCoder[0]; + + if ( st_ivas->ivas_format == SBA_FORMAT ) + { + ivas_dirac_dec_read_BS( ivas_total_brate, st, st_ivas->hDirAC, st_ivas->hQMetaData, &nb_bits_metadata[0], st_ivas->sba_mode, +#ifdef HODIRAC + st_ivas->sba_analysis_order > 1 && ivas_total_brate > IVAS_256k, +#endif + 0 ); + } + else + { + if ( ( error = ivas_masa_decode( st_ivas, st, &nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + else if ( st_ivas->sba_mode == SBA_MODE_SPAR ) + { + if ( st_ivas->hQMetaData != NULL ) + { + st = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0] : st_ivas->hCPE[0]->hCoreCoder[0]; + ivas_dirac_dec_read_BS( + ivas_total_brate, + st, + st_ivas->hDirAC, + st_ivas->hQMetaData, + &nb_bits_metadata[0], + st_ivas->sba_mode, +#ifdef HODIRAC + st_ivas->sba_analysis_order > 1 && ivas_total_brate > IVAS_256k, +#endif + st_ivas->hSpar->dirac_to_spar_md_bands ); + } + + if ( ( error = ivas_spar_dec( st_ivas, nb_bits_metadata ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( st_ivas->nchan_transport == CPE_CHANNELS && st_ivas->nCPE >= 1 ) + { + st_ivas->hCPE[0]->element_brate = ivas_total_brate; + } + + /* core-decoding of transport channels */ + if ( st_ivas->nSCE == 1 ) + { + if ( ( error = ivas_sce_dec( st_ivas, 0, &output[0], output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->nCPE == 1 ) + { + if ( ( error = ivas_cpe_dec( st_ivas, 0, output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->nCPE > 1 ) + { + if ( ( error = ivas_mct_dec( st_ivas, output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + +#ifdef DEBUG_SBA_AUDIO_DUMP + /* Dump audio signal after core-decoding */ + ivas_spar_dump_signal_wav( output_frame, NULL, output, st_ivas->nchan_transport, spar_foa_dec_wav[0], "core-decoding" ); +#endif + /* TCs remapping */ + nchan_remapped = st_ivas->nchan_transport; + if ( st_ivas->sba_dirac_stereo_flag ) + { + nchan_remapped = nchan_out; + + if ( st_ivas->sba_mode == SBA_MODE_SPAR ) + { + ivas_agc_dec_process( st_ivas->hSpar->hAgcDec, output, output, st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, output_frame ); + + if ( st_ivas->hSpar->hPCA != NULL ) + { + ivas_pca_dec( st_ivas->hSpar->hPCA, output_frame, st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->hDecoderConfig->last_ivas_total_brate, st_ivas->bfi, output ); + } + + ivas_spar_dec_gen_umx_mat( st_ivas->hSpar->hMdDec, st_ivas->nchan_transport, IVAS_MAX_NUM_BANDS, st_ivas->bfi +#ifdef SPAR_TUNING + , + ivas_get_spar_dec_md_num_subframes( st_ivas->sba_order, st_ivas->hDecoderConfig->ivas_total_brate ) +#endif + ); + } + + ivas_sba_dirac_stereo_dec( st_ivas, output, output_frame, st_ivas->ivas_format == MC_FORMAT ); + } + else if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ( ivas_total_brate > IVAS_SID_5k2 || ( ivas_total_brate <= IVAS_SID_5k2 && st_ivas->nCPE > 0 && st_ivas->hCPE[0]->nchan_out == 1 ) ) ) + { + nchan_remapped = 1; /* Only one channel transported */ + } + + /* HP filtering */ +#ifndef DEBUG_SPAR_BYPASS_EVS_CODEC + for ( n = 0; n < nchan_remapped; n++ ) + { + hp20( output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } +#endif + if ( st_ivas->ivas_format == SBA_FORMAT ) + { + nchan_remapped = ivas_sba_remapTCs( output, st_ivas, output_frame ); + + if ( st_ivas->sba_mode == SBA_MODE_SPAR && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + ivas_sba_mix_matrix_determiner( st_ivas->hSpar, output, st_ivas->bfi, nchan_remapped, output_frame ); + } + else if ( st_ivas->sba_mode == SBA_MODE_SPAR ) + { + ivas_spar_dec_agc_pca( st_ivas, output, output_frame ); + } + } + + if ( st_ivas->ivas_format == MASA_FORMAT ) + { + ivas_masa_prerender( st_ivas, output, output_frame ); + } + else if ( st_ivas->ivas_format == SBA_FORMAT && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + float gain = 0.8414f; /* Todo: Temporary gain for roughly matching the loudness. To be tuned later together with other outputs. */ + + for ( n = 0; n < nchan_remapped; n++ ) + { + v_multc( output[n], gain, output[n], output_frame ); + } + } + } + else if ( st_ivas->ivas_format == MC_FORMAT ) + { + st = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0] : st_ivas->hCPE[0]->hCoreCoder[0]; + + /* LFE channel decoder */ + if ( st_ivas->mc_mode == MC_MODE_MCT ) + { + if ( st_ivas->hCPE[1]->hCoreCoder[1]->hTcxCfg == NULL ) + { + st_ivas->hCPE[1]->hCoreCoder[1]->hTcxCfg = st_ivas->hCPE[1]->hCoreCoder[0]->hTcxCfg; + } + ivas_lfe_dec( st_ivas->hLFE, st, output_frame, st_ivas->bfi, output_lfe_ch ); + } + + if ( st_ivas->mc_mode == MC_MODE_MCT ) + { + if ( ( error = ivas_mct_dec( st_ivas, output, output_frame, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + mvr2r( output_lfe_ch, output[LFE_CHANNEL], output_frame ); + + /* HP filtering */ + for ( n = 0; n < st_ivas->nchan_transport; n++ ) + { + if ( n != LFE_CHANNEL ) + { + hp20( output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } + } + if ( st_ivas->transport_config != st_ivas->intern_config && ( st_ivas->intern_config == AUDIO_CONFIG_FOA || st_ivas->intern_config == AUDIO_CONFIG_HOA2 || st_ivas->intern_config == AUDIO_CONFIG_HOA3 ) ) + { + if ( ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) <= ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ) ) + { + ivas_mc2sba( st_ivas->hTransSetup, p_output, p_output, output_frame, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE ); + } + } + if ( ( st_ivas->renderer_type == RENDERER_MC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) && ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) >= ( st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe ) ) + { + if ( st_ivas->renderer_type == RENDERER_MC ) + { +#ifdef MC_PARAMUPMIX_MODE + ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, p_output, p_output ); +#else + ivas_ls_setup_conversion( st_ivas, output_frame, p_output, p_output ); +#endif + } + else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + { + ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, output_frame, st_ivas->hOutSetup.ambisonics_order, 0.f ); + } + } + } + else if ( st_ivas->mc_mode == MC_MODE_PARAMMC ) + { + /* read Parametric MC parameters from the bitstream */ + ivas_param_mc_dec_read_BS( ivas_total_brate, st, st_ivas->hParamMC, &nb_bits_metadata[0] ); + + if ( st_ivas->nCPE == 1 ) + { + if ( ( error = ivas_cpe_dec( st_ivas, 0, output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->nCPE > 1 ) + { + if ( ( error = ivas_mct_dec( st_ivas, output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* HP filtering */ + for ( n = 0; n < st_ivas->nchan_transport; n++ ) + { + hp20( output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } + + /* Rendering */ + if ( output_config == AUDIO_CONFIG_MONO || output_config == AUDIO_CONFIG_STEREO ) + { +#ifdef MC_PARAMUPMIX_MODE + ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, p_output, p_output ); +#else + ivas_ls_setup_conversion( st_ivas, output_frame, p_output, p_output ); +#endif + } + } + else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) + { + if ( st_ivas->hOutSetup.separateChannelEnabled ) + { + st = st_ivas->hCPE[0]->hCoreCoder[0]; /* Metadata is always with CPE in the case of separated channel */ + } + + /* read McMASA parameters from the bitstream */ + if ( ( error = ivas_masa_decode( st_ivas, st, &nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->hOutSetup.separateChannelEnabled ) + { + /* Decode the transport audio signals */ + if ( ( error = ivas_cpe_dec( st_ivas, 0, output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Identify the index of the separated channel, always LFE_CHANNEL-1 here */ + n = LFE_CHANNEL - 1; + + /* Decode the separated channel to output[n] to be combined with the synthesized channels */ + if ( ( error = ivas_sce_dec( st_ivas, 0, &output[n], output_frame, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Delay the separated channel to sync with CLDFB delay of the DirAC synthesis, and synthesize the LFE signal. */ + if ( output_config == AUDIO_CONFIG_5_1 || output_config == AUDIO_CONFIG_7_1 || + output_config == AUDIO_CONFIG_5_1_4 || output_config == AUDIO_CONFIG_7_1_4 || + output_config == AUDIO_CONFIG_5_1_2 || ( output_config == AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe > 0 ) ) + { + ivas_lfe_synth_with_filters( st_ivas->hMasa->hMasaLfeSynth, output, output_frame, n, LFE_CHANNEL ); + } + else if ( output_config == AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe == 0 ) + { + /* Delay the separated channel to sync with the DirAC rendering */ + delay_signal( output[n], output_frame, st_ivas->hMasa->hMasaLfeSynth->delayBuffer_syncDirAC, st_ivas->hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_size ); + } + } + else + { + if ( st_ivas->nSCE == 1 ) + { + if ( ( error = ivas_sce_dec( st_ivas, 0, output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->nCPE == 1 ) + { + if ( ( error = ivas_cpe_dec( st_ivas, 0, output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + if ( st_ivas->sba_dirac_stereo_flag ) /* use the flag to trigger the DFT upmix */ + { + ivas_sba_dirac_stereo_dec( st_ivas, output, output_frame, 1 ); + } + + /* HP filtering */ + for ( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) + { + hp20( output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } + + if ( st_ivas->renderer_type == RENDERER_MCMASA_MONO_STEREO ) + { + ivas_mono_stereo_downmix_mcmasa( st_ivas, output, output_frame ); + } + } + } + + + /*----------------------------------------------------------------* + * Write IVAS transport channels + *----------------------------------------------------------------*/ + + ivas_syn_output_f( p_output, output_frame, st_ivas->hTcBuffer->nchan_transport_jbm, data ); + + + /*----------------------------------------------------------------* + * Common updates + *----------------------------------------------------------------*/ + + if ( !st_ivas->bfi ) /* do not update if first frame(s) are lost or NO_DATA */ + { + st_ivas->hDecoderConfig->last_ivas_total_brate = ivas_total_brate; + st_ivas->last_active_ivas_total_brate = ( ivas_total_brate <= IVAS_SID_5k2 ) ? st_ivas->last_active_ivas_total_brate : ivas_total_brate; + } + + if ( st_ivas->ini_frame < MAX_FRAME_COUNTER && !( st_ivas->bfi && st_ivas->ini_frame == 0 ) ) /* keep "st_ivas->ini_frame = 0" until first good received frame */ + { + st_ivas->ini_frame++; + } + + if ( st_ivas->ini_active_frame < MAX_FRAME_COUNTER && !( st_ivas->bfi && st_ivas->ini_frame == 0 ) && ivas_total_brate > IVAS_SID_5k2 ) /* needed in MASA decoder in case the first active frame is BFI, and there were SID-frames decoded before */ + { + st_ivas->ini_active_frame++; + } + +#ifdef DEBUG_MODE_INFO + dbgwrite( &st_ivas->bfi, sizeof( int16_t ), 1, output_frame, "res/bfi" ); + dbgwrite( &st_ivas->BER_detect, sizeof( int16_t ), 1, output_frame, "res/BER_detect" ); + { + float tmpF = ivas_total_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, output_frame, "res/ivas_total_brate.dec" ); + } +#endif + + pop_wmops(); + return error; +} + +/*--------------------------------------------------------------------------* + * ivas_jbm_dec_feed_tc_to_renderer() + * + * Feed decoded transport channels and metadata to the IVAS renderer routine + *--------------------------------------------------------------------------*/ + +ivas_error ivas_jbm_dec_feed_tc_to_renderer( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t nSamplesForRendering, /* i: : number of TC samples available for rendering */ + int16_t *nSamplesResidual, /* o: : number of samples not fitting into the renderer grid and buffer for the next call*/ + float *data /* i : transport channels */ +) +{ + + float data_f[MAX_CLDFB_DIGEST_CHANNELS][MAX_JBM_L_FRAME48k]; /* 'float' buffer for transport channels that will be directly converted with the CLDFB */ + float *p_data_f[MAX_CLDFB_DIGEST_CHANNELS]; + int16_t n_render_timeslots; + int16_t n; + ivas_error error; + + error = IVAS_ERR_OK; + + push_wmops( "ivas_jbm_dec_feed_tc_to_rendererer" ); + + for ( n = 0; n < MAX_CLDFB_DIGEST_CHANNELS; n++ ) + { + p_data_f[n] = &data_f[n][0]; + } + ivas_jbm_dec_copy_tc( st_ivas, nSamplesForRendering, nSamplesResidual, data, p_data_f ); + n_render_timeslots = st_ivas->hTcBuffer->n_samples_available / st_ivas->hTcBuffer->n_samples_granularity; + + if ( st_ivas->hTcBuffer->tc_buffer_mode == TC_BUFFER_MODE_BUFFER ) + { + ivas_jbm_dec_td_renderers_adapt_subframes( st_ivas ); + } + else if ( st_ivas->ivas_format == STEREO_FORMAT ) + { + ivas_jbm_dec_td_renderers_adapt_subframes( st_ivas ); + } + else if ( st_ivas->ivas_format == ISM_FORMAT ) + { + /* Rendering */ + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + ivas_dirac_dec_set_md_map( st_ivas, n_render_timeslots ); + ivas_param_ism_params_to_masa_param_mapping( st_ivas ); + } + else if ( st_ivas->renderer_type == RENDERER_PARAM_ISM || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + { + ivas_param_ism_dec_digest_tc( st_ivas, n_render_timeslots, p_data_f ); + } + } + else /* ISM_MODE_DISC */ + { + ivas_ism_dec_digest_tc( st_ivas ); + } + } + else if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) + { + ivas_sba_dec_digest_tc( st_ivas, n_render_timeslots, st_ivas->hTcBuffer->n_samples_available ); + } + else if ( st_ivas->ivas_format == MC_FORMAT ) + { + if ( st_ivas->mc_mode == MC_MODE_MCT ) + { + ivas_jbm_dec_td_renderers_adapt_subframes( st_ivas ); + } + else if ( st_ivas->mc_mode == MC_MODE_PARAMMC ) + { + ivas_param_mc_dec_digest_tc( st_ivas, (uint8_t) n_render_timeslots, p_data_f ); + } + else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) + { + ivas_sba_dec_digest_tc( st_ivas, n_render_timeslots, st_ivas->hTcBuffer->n_samples_available ); + } + } + + pop_wmops(); + + return error; +} + + +/*--------------------------------------------------------------------------* + * ivas_dec_render() + * + * Principal IVAS rendering routine + *--------------------------------------------------------------------------*/ +ivas_error ivas_jbm_dec_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const uint16_t nSamplesAsked, /* i : number of samples wanted */ + uint16_t *nSamplesRendered, /* o : number of samples rendered */ + uint16_t *nSamplesAvailableNext, /* o : number of samples still available in the rendering pipeline */ + int16_t *data /* o : output synthesis signal */ +) +{ + + int16_t n, nchan_out; + int16_t nchan_transport; + float output[MAX_OUTPUT_CHANNELS][L_FRAME48k]; /* 'float' buffer for output synthesis, MAX_OUTPUT_CHANNELS channels */ /* IVAS_fmToDo: buffer can be allocated dynamically based on the actual number of output channels */ + int16_t nchan_remapped; + int32_t output_Fs; + AUDIO_CONFIG output_config; + int16_t nSamplesAskedLocal; + ivas_error error; + float *p_output[MAX_OUTPUT_CHANNELS]; + float *p_tc[MAX_TRANSPORT_CHANNELS]; + + error = IVAS_ERR_OK; + + push_wmops( "ivas_dec_render" ); + + /*----------------------------------------------------------------* + * Initialization of local vars after struct has been set + *----------------------------------------------------------------*/ + + output_Fs = st_ivas->hDecoderConfig->output_Fs; + nchan_out = st_ivas->hDecoderConfig->nchan_out; + nchan_transport = st_ivas->hTcBuffer->nchan_transport_jbm; + output_config = st_ivas->hDecoderConfig->output_config; + nSamplesAskedLocal = nSamplesAsked + st_ivas->hTcBuffer->n_samples_discard; + for ( n = 0; n < MAX_OUTPUT_CHANNELS; n++ ) + { + p_output[n] = &output[n][0]; + } + + for ( n = 0; n < st_ivas->hTcBuffer->nchan_transport_internal; n++ ) + { + p_tc[n] = &st_ivas->hTcBuffer->tc[n][st_ivas->hTcBuffer->n_samples_rendered]; + } + + /*----------------------------------------------------------------* + * Rendering + *----------------------------------------------------------------*/ + + if ( st_ivas->ivas_format == UNDEFINED_FORMAT ) + { + assert( 0 ); + } + else if ( st_ivas->hTcBuffer->tc_buffer_mode == TC_BUFFER_MODE_BUFFER ) + { + ivas_jbm_dec_tc_buffer_playout( st_ivas, nSamplesAskedLocal, nSamplesRendered, p_output ); + } + else if ( st_ivas->ivas_format == STEREO_FORMAT ) + { + /* Rendering */ + if ( st_ivas->renderer_type == RENDERER_MC ) + { + *nSamplesRendered = min( st_ivas->hTcBuffer->n_samples_available, nSamplesAskedLocal ); +#ifdef MC_PARAMUPMIX_MODE + ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, *nSamplesRendered, p_tc, p_output ); +#else + ivas_ls_setup_conversion( st_ivas, output_frame, p_output, p_output ); +#endif + } + } + else if ( st_ivas->ivas_format == ISM_FORMAT ) + { + /* Rendering */ + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + ivas_dirac_dec_binaural_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, st_ivas->nchan_transport, p_output ); + } + else if ( st_ivas->renderer_type == RENDERER_PARAM_ISM || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + { + ivas_param_ism_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ); + + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + { + /* Convert CICP19 -> Ambisonics */ + ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0.f ); + } + } + } + else /* ISM_MODE_DISC */ + { + *nSamplesRendered = min( st_ivas->hTcBuffer->n_samples_available, nSamplesAskedLocal ); + /* Loudspeaker or Ambisonics rendering */ + if ( st_ivas->renderer_type == RENDERER_TD_PANNING || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) + { + /* Convert to CICPxx; used also for ISM->CICP19->binaural_room rendering */ + ivas_ism_render_sf( st_ivas, p_output, *nSamplesRendered ); + } + else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) + { + /* Convert to Ambisonics; used also for ISM->HOA3->binaural rendering */ + ivas_ism2sba_sf( st_ivas->hTcBuffer->tc, p_output, st_ivas->hIsmRendererData, st_ivas->nchan_transport, *nSamplesRendered, st_ivas->hTcBuffer->n_samples_rendered, st_ivas->hIntSetup.ambisonics_order ); + } + + /* Binaural rendering */ + if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) + { + ObjRenderIVASSubframe( st_ivas, p_output, *nSamplesRendered ); + } + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) + { + if ( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, + AUDIO_CONFIG_7_1_4, + AUDIO_CONFIG_BINAURAL_ROOM, + st_ivas->hDecoderConfig, + NULL, + NULL, + NULL, + st_ivas->hTcBuffer, + p_output, + p_output, + *nSamplesRendered, + output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + ivas_binaural_add_LFE( st_ivas, *nSamplesRendered, p_output, p_output ); + } +#ifdef DEBUGGING + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + ivas_binaural_cldfb_sf( st_ivas, *nSamplesRendered, p_output ); + } +#endif + } + } + else if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) + { + nchan_remapped = nchan_transport; + /* Loudspeakers, Ambisonics or Binaural rendering */ + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + ivas_dirac_dec_binaural_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output ); + } + else if ( st_ivas->sba_mode == SBA_MODE_DIRAC || st_ivas->ivas_format == MASA_FORMAT ) + { + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC ) + { + *nSamplesRendered = min( st_ivas->hTcBuffer->n_samples_available, nSamplesAskedLocal ); + for ( n = 0; n < nchan_remapped; n++ ) + { + mvr2r( st_ivas->hTcBuffer->tc[n] + st_ivas->hTcBuffer->n_samples_rendered, p_output[n], *nSamplesRendered ); + } + ivas_sba_linear_renderer( p_output, *nSamplesRendered, nchan_remapped, output_config, st_ivas->hOutSetup, st_ivas->hoa_dec_mtx ); + } + else if ( st_ivas->renderer_type == RENDERER_DIRAC ) + { + ivas_dirac_dec_render( st_ivas, nchan_remapped, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ); + } + } + else /* SBA_MODE_SPAR */ + { + ivas_sba_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ); + } + } + else if ( st_ivas->ivas_format == MC_FORMAT ) + { + if ( st_ivas->mc_mode == MC_MODE_MCT ) + { + *nSamplesRendered = min( st_ivas->hTcBuffer->n_samples_available, nSamplesAskedLocal ); + if ( st_ivas->transport_config != st_ivas->intern_config && ( st_ivas->intern_config == AUDIO_CONFIG_FOA || st_ivas->intern_config == AUDIO_CONFIG_HOA2 || st_ivas->intern_config == AUDIO_CONFIG_HOA3 ) ) + { + ivas_mc2sba( st_ivas->hTransSetup, p_tc, p_output, *nSamplesRendered, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE ); + } + + /* Rendering */ + if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) + { + if ( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, + st_ivas->intern_config, + st_ivas->hOutSetup.output_config, + st_ivas->hDecoderConfig, + st_ivas->hHeadTrackData, + &st_ivas->hIntSetup, + st_ivas->hEFAPdata, + st_ivas->hTcBuffer, + p_tc, + p_output, + *nSamplesRendered, + output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + ivas_binaural_add_LFE( st_ivas, *nSamplesRendered, st_ivas->hTcBuffer->tc, p_output ); + } + else if ( st_ivas->renderer_type == RENDERER_MC ) + { + *nSamplesRendered = min( st_ivas->hTcBuffer->n_samples_available, nSamplesAskedLocal ); +#ifdef MC_PARAMUPMIX_MODE + ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, *nSamplesRendered, p_tc, p_output ); +#else + ivas_ls_setup_conversion( st_ivas, *nSamplesRendered, p_tc, p_output ); +#endif + } + else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + { + ivas_mc2sba( st_ivas->hIntSetup, p_tc, p_output, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0.f ); + } + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) + { + ObjRenderIVASSubframe( st_ivas, p_output, *nSamplesRendered ); + ivas_binaural_add_LFE( st_ivas, *nSamplesRendered, st_ivas->hTcBuffer->tc, p_output ); + } + } + else if ( st_ivas->mc_mode == MC_MODE_PARAMMC ) + { + ivas_param_mc_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ); + } + else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) + { + + /* Rendering */ + int16_t offset = st_ivas->hDirAC->slots_rendered * st_ivas->hDirAC->slot_size; + nchan_remapped = st_ivas->nchan_transport; + + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + ivas_dirac_dec_binaural_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output ); + } + else if ( st_ivas->renderer_type == RENDERER_DIRAC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) /* rendering to CICPxx and Ambisonics */ + { + ivas_dirac_dec_render( st_ivas, nchan_remapped, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ); + + + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + { + /* we still need to copy the separate channel if available */ + if ( st_ivas->hOutSetup.separateChannelEnabled ) + { + mvr2r( st_ivas->hTcBuffer->tc[LFE_CHANNEL - 1] + offset, output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); + } + ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0.f ); + } + else if ( st_ivas->intern_config == AUDIO_CONFIG_5_1 && ( output_config == AUDIO_CONFIG_5_1_2 || output_config == AUDIO_CONFIG_5_1_4 || output_config == AUDIO_CONFIG_7_1 ) ) + { + for ( n = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; n < st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; n++ ) + { + set_zero( output[n], *nSamplesRendered ); + } + } + } + /* copy discrete C and TD LFE from internal TC to output */ + if ( st_ivas->hOutSetup.separateChannelEnabled ) + { + if ( output_config == AUDIO_CONFIG_5_1 || output_config == AUDIO_CONFIG_7_1 || + output_config == AUDIO_CONFIG_5_1_4 || output_config == AUDIO_CONFIG_7_1_4 || + output_config == AUDIO_CONFIG_5_1_2 || ( output_config == AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe > 0 ) ) + { + mvr2r( st_ivas->hTcBuffer->tc[LFE_CHANNEL] + offset, output[LFE_CHANNEL], *nSamplesRendered ); + mvr2r( st_ivas->hTcBuffer->tc[LFE_CHANNEL - 1] + offset, output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); + } + else if ( output_config == AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe == 0 ) + { + /* Delay the separated channel to sync with the DirAC rendering */ + mvr2r( st_ivas->hTcBuffer->tc[LFE_CHANNEL - 1] + offset, output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); + } + } + } + } + + /*----------------------------------------------------------------* + * Write IVAS output channels + * - compensation for saturation + * - float to integer conversion + *----------------------------------------------------------------*/ + st_ivas->hTcBuffer->n_samples_available -= *nSamplesRendered; + st_ivas->hTcBuffer->n_samples_rendered += *nSamplesRendered; + if ( st_ivas->hTcBuffer->n_samples_discard > 0 ) + { + for ( n = 0; n < MAX_OUTPUT_CHANNELS; n++ ) + { + p_output[n] += st_ivas->hTcBuffer->n_samples_discard; + } + *nSamplesRendered -= st_ivas->hTcBuffer->n_samples_discard; + st_ivas->hTcBuffer->n_samples_discard = 0; + } + + ivas_limiter_dec( st_ivas->hLimiter, p_output, nchan_out, *nSamplesRendered, st_ivas->BER_detect ); + +#ifdef DEBUGGING + st_ivas->noClipping += +#endif + ivas_syn_output( p_output, *nSamplesRendered, nchan_out, data ); + + *nSamplesAvailableNext = st_ivas->hTcBuffer->n_samples_available; + + pop_wmops(); + return error; +} + + +/*--------------------------------------------------------------------------* + * ivas_jbm_dec_dec_flush_renderer() + * + * Flush samples if renderer granularity changes on a bitrate change + *--------------------------------------------------------------------------*/ +ivas_error ivas_jbm_dec_flush_renderer( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t tc_granularity_new, /* i : new renderer granularity */ + const RENDERER_TYPE renderer_type_old, /* i : old renderer type */ + const AUDIO_CONFIG intern_config_old, /* i : old internal config */ + const IVAS_OUTPUT_SETUP_HANDLE hIntSetupOld, /* i : old internal output setup */ + const MC_MODE mc_mode_old, /* i : old MC mode */ + const ISM_MODE ism_mode_old, /* i : old ISM mode */ + uint16_t *nSamplesRendered, /* o : number of samples flushed */ + int16_t *data /* o : rendered samples */ +) +{ + ivas_error error; + int16_t n_samples_still_available; + int16_t n_slots_still_available; + int16_t n_samples_to_render; + DECODER_TC_BUFFER_HANDLE hTcBuffer; + float output[MAX_CICP_CHANNELS][L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; + float *p_output[MAX_CICP_CHANNELS]; + + error = IVAS_ERR_OK; + + *nSamplesRendered = 0; + hTcBuffer = st_ivas->hTcBuffer; + /* get number of possible slots in new granularity */ + n_samples_still_available = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_rendered; + n_slots_still_available = n_samples_still_available / tc_granularity_new; + *nSamplesRendered = n_slots_still_available * tc_granularity_new; + n_samples_to_render = *nSamplesRendered; + n_samples_still_available -= n_samples_to_render; + assert( n_samples_still_available < tc_granularity_new ); + if ( n_slots_still_available ) + { + int ch_idx; + /* render what is still there with zero padding */ + for ( ch_idx = 0; ch_idx < hTcBuffer->nchan_buffer_full; ch_idx++ ) + { + /* move it at the beginning of the TC buffer with zero padding */ + mvr2r( hTcBuffer->tc[ch_idx] + hTcBuffer->n_samples_rendered, hTcBuffer->tc[ch_idx], n_samples_to_render ); + set_zero( hTcBuffer->tc[ch_idx] + n_samples_to_render, hTcBuffer->n_samples_granularity - n_samples_to_render ); + mvr2r( hTcBuffer->tc[ch_idx] + hTcBuffer->n_samples_rendered + n_samples_to_render, hTcBuffer->tc[ch_idx] + hTcBuffer->n_samples_granularity, n_samples_still_available ); + } + /* simple change of the slot info */ + hTcBuffer->num_slots = 1; + hTcBuffer->nb_subframes = 1; + hTcBuffer->subframes_rendered = 0; + hTcBuffer->slots_rendered = 0; + hTcBuffer->subframe_nbslots[0] = 1; + hTcBuffer->n_samples_buffered = hTcBuffer->n_samples_granularity + n_samples_still_available; + hTcBuffer->n_samples_available = 0; + hTcBuffer->n_samples_flushed = n_samples_to_render; + hTcBuffer->n_samples_rendered = hTcBuffer->n_samples_granularity; + + for ( ch_idx = 0; ch_idx < MAX_CICP_CHANNELS; ch_idx++ ) + { + p_output[ch_idx] = output[ch_idx]; + } + + if ( st_ivas->ivas_format == ISM_FORMAT ) + { + if ( ism_mode_old == ISM_MODE_DISC ) + { + /* Binaural rendering */ + if ( renderer_type_old == RENDERER_BINAURAL_OBJECTS_TD ) + { + ObjRenderIVASSubframe( st_ivas, p_output, hTcBuffer->n_samples_granularity ); + } + else if ( renderer_type_old == RENDERER_BINAURAL_MIXER_CONV_ROOM ) + { + /* Convert to CICPxx; used also for ISM->CICP19->binaural_room rendering */ + set_f( st_ivas->hIsmRendererData->interpolator, 1.0f, hTcBuffer->n_samples_granularity ); + ivas_ism_render_sf( st_ivas, p_output, hTcBuffer->n_samples_granularity ); + if ( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, + AUDIO_CONFIG_7_1_4, + AUDIO_CONFIG_BINAURAL_ROOM, + st_ivas->hDecoderConfig, + NULL, + NULL, + NULL, + st_ivas->hTcBuffer, + p_output, + p_output, + hTcBuffer->n_samples_granularity, + st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + ivas_binaural_add_LFE( st_ivas, hTcBuffer->n_samples_granularity, p_output, p_output ); + } + } + else + { + return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong ISM_MODE in VoIP renderer flushing!" ); + } + } + else if ( st_ivas->ivas_format == MC_FORMAT ) + { + if ( mc_mode_old == MC_MODE_MCT ) + { + if ( renderer_type_old == RENDERER_BINAURAL_MIXER_CONV || renderer_type_old == RENDERER_BINAURAL_MIXER_CONV_ROOM ) + { + if ( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, + intern_config_old, + st_ivas->hOutSetup.output_config, + st_ivas->hDecoderConfig, + st_ivas->hHeadTrackData, + hIntSetupOld, + st_ivas->hEFAPdata, + st_ivas->hTcBuffer, + hTcBuffer->tc, + p_output, + hTcBuffer->n_samples_granularity, + st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + ivas_binaural_add_LFE( st_ivas, hTcBuffer->n_samples_granularity, st_ivas->hTcBuffer->tc, p_output ); + } + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) + { + ObjRenderIVASSubframe( st_ivas, p_output, hTcBuffer->n_samples_granularity ); + ivas_binaural_add_LFE( st_ivas, hTcBuffer->n_samples_granularity, st_ivas->hTcBuffer->tc, p_output ); + } + } + else + { + return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong MC_MODE in VoIP renderer flushing!" ); + } + } + else + { + return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong IVAS format in VoIP renderer flushing!" ); + } + } + + /* Only write out the valid data*/ + ivas_limiter_dec( st_ivas->hLimiter, p_output, st_ivas->hDecoderConfig->nchan_out, *nSamplesRendered, st_ivas->BER_detect ); + +#ifdef DEBUGGING + st_ivas->noClipping += +#endif + ivas_syn_output( p_output, *nSamplesRendered, st_ivas->hDecoderConfig->nchan_out, data ); + + + return error; +} + +/*--------------------------------------------------------------------------* + * ivas_jbm_dec_set_discard_samples() + * + * Set number of samples to discard in the first subframe if the renderer granularity changes on a bitrate change + *--------------------------------------------------------------------------*/ +ivas_error ivas_jbm_dec_set_discard_samples( + Decoder_Struct *st_ivas /* i/o: main IVAS decoder structre */ +) +{ + int16_t nMaxSlotsPerSubframe, nSlotsInFirstSubframe; + ivas_error error; + + error = IVAS_ERR_OK; + + /* render first frame with front zero padding and discarding those samples */ + nMaxSlotsPerSubframe = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / st_ivas->hTcBuffer->n_samples_granularity; + nSlotsInFirstSubframe = nMaxSlotsPerSubframe - st_ivas->hTcBuffer->subframe_nbslots[st_ivas->hTcBuffer->nb_subframes - 1]; + if ( nSlotsInFirstSubframe > 0 ) + { + st_ivas->hTcBuffer->n_samples_discard = ( nMaxSlotsPerSubframe - nSlotsInFirstSubframe ) * st_ivas->hTcBuffer->n_samples_granularity; + /* set last subframes number to max to ensure correct continuation */ + st_ivas->hTcBuffer->subframe_nbslots[st_ivas->hTcBuffer->nb_subframes - 1] = nMaxSlotsPerSubframe; + } + return error; +} + +/*--------------------------------------------------------------------------* + * ivas_jbm_dec_get_adapted_linear_interpolator() + * + * Get an interpolator that is adapted to time scale modified IVAS frame + *--------------------------------------------------------------------------*/ + +void ivas_jbm_dec_get_adapted_linear_interpolator( + const int16_t default_interp_length, /* i : default length of the (full-frame) interpolator */ + const int16_t interp_length, /* i : length of the interpolator to be created */ + float *interpolator /* o : the interpolator */ +) +{ + int16_t jbm_segment_len, idx; + float dec; +#ifdef DEBUGGING + assert( default_interp_length % 2 == 0 ); +#endif + + jbm_segment_len = ( default_interp_length >> 1 ); + dec = 1.0f / default_interp_length; + + interpolator[interp_length - 1] = 1.0f; + for ( idx = interp_length - 2; idx >= jbm_segment_len; idx-- ) + { + interpolator[idx] = max( 0.0f, interpolator[idx + 1] - dec ); + } + if ( interpolator[idx + 1] > 0.0f ) + { + dec = interpolator[idx + 1] / ( jbm_segment_len + 1 ); + for ( ; idx >= 0; idx-- ) + { + interpolator[idx] = interpolator[idx + 1] - dec; + } + } + else + { + set_f( interpolator, 0.0f, idx + 1 ); + } +} + +/*--------------------------------------------------------------------------* + * ivas_jbm_dec_get_adapted_subframes() + * + * Get an interpolator that is adapted to time scale modified IVAS frame + *--------------------------------------------------------------------------*/ +void ivas_jbm_dec_get_adapted_subframes( + const int16_t nCldfbTs, /* i : number of time slots in the current frame */ + int16_t *subframe_nbslots, /* i/o: subframe grid */ + int16_t *nb_subframes /* i/o: number of subframes in the frame */ +) +{ + uint16_t nSlotsInLastSubframe, nSlotsInFirstSubframe; + uint16_t nCldfbSlotsLocal = nCldfbTs; + /* get last subframe size from previous frame, determine how many slots have to be processed + in the first subframe (i.e. potential leftover of a 5ms subframe) */ + nSlotsInFirstSubframe = ( PARAM_MC_MAX_NSLOTS_IN_SUBFRAME - subframe_nbslots[*nb_subframes - 1] ); + *nb_subframes = 0; + if ( nSlotsInFirstSubframe > 0 ) + { + *nb_subframes = 1; + nCldfbSlotsLocal -= nSlotsInFirstSubframe; + } + *nb_subframes += (int16_t) ceilf( (float) nCldfbSlotsLocal / (float) PARAM_MC_MAX_NSLOTS_IN_SUBFRAME ); + nSlotsInLastSubframe = nCldfbSlotsLocal % PARAM_MC_MAX_NSLOTS_IN_SUBFRAME; + set_s( subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set_s( subframe_nbslots, PARAM_MC_MAX_NSLOTS_IN_SUBFRAME, *nb_subframes ); + if ( nSlotsInFirstSubframe > 0 ) + { + subframe_nbslots[0] = nSlotsInFirstSubframe; + } + if ( nSlotsInLastSubframe > 0 ) + { + subframe_nbslots[*nb_subframes - 1] = nSlotsInLastSubframe; + } + return; +} + +/*--------------------------------------------------------------------------* + * ivas_jbm_dec_get_adapted_linear_interpolator() + * + * Get an meta data map adapted to a time scale modified IVAS frame + *--------------------------------------------------------------------------*/ +void ivas_jbm_dec_get_md_map( + const int16_t default_len, /* i : default frame length in metadata slots */ + const int16_t len, /* i : length of the modfied frames in metadata slots */ + const int16_t subframe_len, /* i : default length of a subframe */ + const int16_t offset, /* i : current read offset into the md buffer */ + const int16_t buf_len, /* i : length of the metadata buffer */ + int16_t *map /* o : metadata index map */ +) +{ + int16_t jbm_segment_len, map_idx, src_idx, src_idx_map; + float dec, src_idx_f; +#ifdef DEBUGGING + assert( default_len % 2 == 0 ); +#endif + + jbm_segment_len = ( default_len >> 1 ); + dec = 1.0f / default_len; + + + for ( map_idx = len - 1, src_idx = default_len - 1; map_idx >= jbm_segment_len; map_idx--, src_idx-- ) + { + src_idx_map = max( 0, src_idx / subframe_len ); + map[map_idx] = ( offset + src_idx_map ) % buf_len; + } + /* changed part (first segment), interpolate index to parameters + (we do not want to interpolate and smooth acutal direction/diffuseness values even more) */ + if ( src_idx >= 0 ) + { + dec = ( (float) ( src_idx + 1 ) ) / ( (float) jbm_segment_len ); + src_idx_f = (float) ( src_idx + 1 ) - dec; + for ( ; map_idx >= 0; map_idx-- ) + { + src_idx = max( 0, ( (int16_t) round_f( src_idx_f ) ) / subframe_len ); + map[map_idx] = ( offset + src_idx ) % buf_len; + src_idx_f -= dec; + } + } + else + { + set_s( map, offset, map_idx + 1 ); + } +} + +/*--------------------------------------------------------------------------* + * ivas_jbm_dec_get_num_tc_channels() + * + * Get the number of transport channels provided by the JBM transport channel decode function + *--------------------------------------------------------------------------*/ +int16_t ivas_jbm_dec_get_num_tc_channels( Decoder_Struct *st_ivas ) /* i : IVAS decoder handle */ +{ + int16_t num_tc; + int32_t ivas_total_brate; + AUDIO_CONFIG output_config; + + if ( st_ivas->renderer_type == RENDERER_DISABLE ) + { + num_tc = st_ivas->hDecoderConfig->nchan_out; + } + else + { + num_tc = st_ivas->nchan_transport; + } + output_config = st_ivas->hDecoderConfig->output_config; + + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + if ( st_ivas->ivas_format == STEREO_FORMAT && st_ivas->hDecoderConfig->nchan_out == 1 ) + { + num_tc = 1; + } + else if ( st_ivas->ivas_format == ISM_FORMAT ) + { + if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) + { + num_tc = 1; + } + } + else if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) + { + if ( st_ivas->sba_dirac_stereo_flag ) + { + num_tc = CPE_CHANNELS; + } + else if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ( ivas_total_brate > IVAS_SID_5k2 || ( ivas_total_brate <= IVAS_SID_5k2 && st_ivas->nCPE > 0 && st_ivas->hCPE[0]->nchan_out == 1 ) ) ) + { + num_tc = 1; /* Only one channel transported */ + } + + if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL && st_ivas->nchan_transport == 2 && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_SID_5k2 ) + { + num_tc = CPE_CHANNELS; + } + if ( st_ivas->ivas_format == SBA_FORMAT ) + { + if ( ( st_ivas->sba_mode != SBA_MODE_SPAR && st_ivas->sba_planar && num_tc >= 3 ) || + ( ( st_ivas->sba_mode == SBA_MODE_SPAR ) && num_tc == 3 ) ) + { + num_tc++; + } + } + } + else if ( st_ivas->ivas_format == MC_FORMAT ) + { + if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_MONO ) + { + num_tc = 1; + } + else if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO ) + { + num_tc = 2; + } + else if ( st_ivas->mc_mode == MC_MODE_MCT ) + { + /* do all static dmx already in the TC decoder if less channels than transported... */ + if ( st_ivas->transport_config != st_ivas->intern_config && ( st_ivas->intern_config == AUDIO_CONFIG_FOA || st_ivas->intern_config == AUDIO_CONFIG_HOA2 || st_ivas->intern_config == AUDIO_CONFIG_HOA3 ) ) + { + if ( ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) > ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ) ) + { + num_tc = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; + } + } + else if ( ( st_ivas->renderer_type == RENDERER_MC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) && ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) >= ( st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe ) ) + { + num_tc = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; + } + } + else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) + { + if ( st_ivas->hOutSetup.separateChannelEnabled ) + { + num_tc++; + } + if ( st_ivas->hOutSetup.separateChannelEnabled && ( output_config == AUDIO_CONFIG_5_1 || output_config == AUDIO_CONFIG_7_1 || + output_config == AUDIO_CONFIG_5_1_4 || output_config == AUDIO_CONFIG_7_1_4 || + output_config == AUDIO_CONFIG_5_1_2 || ( output_config == AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe > 0 ) ) ) + { + /* LFE is synthesized in TD with the TCs*/ + num_tc++; + } + } + } + + return num_tc; +} + +/*--------------------------------------------------------------------------* + * ivas_jbm_dec_copy_tc() + * + * Copy interleaved transport chnannels to the correct buffers, update the TC + * buffer handle + *--------------------------------------------------------------------------*/ +void ivas_jbm_dec_copy_tc( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t nSamplesForRendering, /* i : number of samples to digest */ + int16_t *nSamplesResidual, /* o : number of samples that will be left for the next frame */ + float *data, /* i : (interleaved) transport channel samples */ + float *tc_digest_f[] /* o : samples that will be directly digestest (eg. by CLDFB) */ +) +{ + int16_t ch; + DECODER_TC_BUFFER_HANDLE hTcBuffer; + int16_t n_samples_still_available, m; + int16_t n_ch_full_copy; + int16_t n_ch_res_copy; + + + hTcBuffer = st_ivas->hTcBuffer; + n_samples_still_available = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_rendered; + hTcBuffer->n_samples_buffered = n_samples_still_available + nSamplesForRendering + hTcBuffer->n_samples_discard; + hTcBuffer->n_samples_available = hTcBuffer->n_samples_granularity * ( hTcBuffer->n_samples_buffered / hTcBuffer->n_samples_granularity ); + *nSamplesResidual = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_available; + n_ch_full_copy = min( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); + n_ch_res_copy = hTcBuffer->nchan_transport_jbm - hTcBuffer->nchan_buffer_full; + + for ( ch = 0; ch < n_ch_full_copy; ch++ ) + { + set_zero( hTcBuffer->tc[ch], hTcBuffer->n_samples_discard ); + mvr2r( hTcBuffer->tc[ch] + hTcBuffer->n_samples_rendered, hTcBuffer->tc[ch] + hTcBuffer->n_samples_discard, n_samples_still_available ); + for ( m = 0; m < nSamplesForRendering; m++ ) + { + hTcBuffer->tc[ch][n_samples_still_available + hTcBuffer->n_samples_discard + m] = data[m * st_ivas->hTcBuffer->nchan_transport_jbm + ch]; + } + } + if ( n_ch_res_copy > 0 ) + { + for ( ; ch < hTcBuffer->nchan_transport_jbm; ch++ ) + { + mvr2r( hTcBuffer->tc[ch], tc_digest_f[ch], n_samples_still_available ); + for ( m = 0; m < nSamplesForRendering; m++ ) + { + tc_digest_f[ch][n_samples_still_available + m] = data[m * st_ivas->hTcBuffer->nchan_transport_jbm + ch]; + } + mvr2r( tc_digest_f[ch] + hTcBuffer->n_samples_available, hTcBuffer->tc[ch], *nSamplesResidual ); + } + } + hTcBuffer->n_samples_rendered = 0; + return; +} + + +int16_t ivas_jbm_dec_get_render_granularity( const RENDERER_TYPE rendererType, + const int32_t output_Fs ) +{ + int16_t render_granularity; + + if ( rendererType == RENDERER_BINAURAL_OBJECTS_TD || rendererType == RENDERER_BINAURAL_MIXER_CONV || rendererType == RENDERER_BINAURAL_MIXER_CONV_ROOM ) + { + render_granularity = NS2SA( output_Fs, FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ); + } + else + { + render_granularity = NS2SA( output_Fs, CLDFB_SLOT_NS ); + } + + return render_granularity; +} + +/*--------------------------------------------------------------------------* + * ivas_jbm_dec_tc_buffer_open() + * + * open and initialize the transport channel buffer + *--------------------------------------------------------------------------*/ +ivas_error ivas_jbm_dec_tc_buffer_open( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const TC_BUFFER_MODE tc_buffer_mode, /* i : buffer mode */ + const int16_t nchan_transport_jbm, /* i : number of real transport channels */ + const int16_t nchan_transport_internal, /* i : number of totally buffered channels */ + const int16_t nchan_full, /* i : nubmer of channels to fully store */ + const int16_t n_samples_granularity /* i : granularity of the renderer/buffer */ +) +{ + int16_t nsamp_to_allocate; + DECODER_TC_BUFFER_HANDLE hTcBuffer; + ivas_error error; + int16_t nMaxSlotsPerSubframe; + int16_t nchan_residual; + int16_t ch_idx; + + error = IVAS_ERR_OK; + + /*-----------------------------------------------------------------* + * prepare library opening + *-----------------------------------------------------------------*/ + + if ( ( hTcBuffer = (DECODER_TC_BUFFER_HANDLE) malloc( sizeof( DECODER_TC_BUFFER ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TC Buffer\n" ) ); + } + hTcBuffer->tc_buffer_mode = tc_buffer_mode; + hTcBuffer->nchan_transport_jbm = nchan_transport_jbm; + hTcBuffer->nchan_transport_internal = nchan_transport_internal; + hTcBuffer->nchan_buffer_full = nchan_full; + nchan_residual = nchan_transport_internal - nchan_full; + hTcBuffer->n_samples_granularity = n_samples_granularity; + hTcBuffer->n_samples_available = 0; + hTcBuffer->n_samples_buffered = 0; + hTcBuffer->n_samples_rendered = 0; + hTcBuffer->slots_rendered = 0; + hTcBuffer->subframes_rendered = 0; + hTcBuffer->n_samples_discard = 0; + hTcBuffer->n_samples_flushed = 0; + hTcBuffer->nb_subframes = MAX_PARAM_SPATIAL_SUBFRAMES; + nsamp_to_allocate = 0; + nMaxSlotsPerSubframe = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / hTcBuffer->n_samples_granularity; + hTcBuffer->num_slots = nMaxSlotsPerSubframe * MAX_PARAM_SPATIAL_SUBFRAMES; + set_s( hTcBuffer->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set_s( hTcBuffer->subframe_nbslots, nMaxSlotsPerSubframe, MAX_PARAM_SPATIAL_SUBFRAMES ); + + if ( hTcBuffer->tc_buffer_mode == TC_BUFFER_MODE_NONE ) + { + hTcBuffer->tc_buffer = NULL; + for ( ch_idx = 0; ch_idx < MAX_TRANSPORT_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc[ch_idx] = NULL; + } + } + else + { + int16_t n_samp_full = ( NS2SA( st_ivas->hDecoderConfig->output_Fs, MAX_JBM_L_FRAME_NS ) + hTcBuffer->n_samples_granularity - 1 ); + int16_t n_samp_residual = hTcBuffer->n_samples_granularity - 1; + int32_t offset; + nsamp_to_allocate = hTcBuffer->nchan_buffer_full * n_samp_full; + nsamp_to_allocate += nchan_residual * n_samp_residual; + hTcBuffer->tc_buffer = (float *) malloc( nsamp_to_allocate * sizeof( float ) ); + set_zero( hTcBuffer->tc_buffer, nsamp_to_allocate ); + offset = 0; + for ( ch_idx = 0; ch_idx < hTcBuffer->nchan_buffer_full; ch_idx++ ) + { + hTcBuffer->tc[ch_idx] = &hTcBuffer->tc_buffer[offset]; + offset += n_samp_full; + } + for ( ; ch_idx < hTcBuffer->nchan_transport_internal; ch_idx++ ) + { + hTcBuffer->tc[ch_idx] = &hTcBuffer->tc_buffer[offset]; + offset += n_samp_residual; + } + for ( ; ch_idx < MAX_TRANSPORT_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc[ch_idx] = NULL; + } + } + + st_ivas->hTcBuffer = hTcBuffer; + return error; +} + +/*--------------------------------------------------------------------------* + * ivas_jbm_dec_tc_buffer_reconfigure() + * + * open and initialize the transport channel buffer + *--------------------------------------------------------------------------*/ +ivas_error ivas_jbm_dec_tc_buffer_reconfigure( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const TC_BUFFER_MODE tc_buffer_mode, /* i : new buffer mode */ + const int16_t nchan_transport_jbm, /* i : new number of real transport channels */ + const int16_t nchan_transport_internal, /* i : new number of totally buffered channels */ + const int16_t nchan_full, /* i : new number of channels to fully store */ + const int16_t n_samples_granularity /* i : new granularity of the renderer/buffer */ +) +{ + ivas_error error; + int16_t nsamp_to_allocate, n_samp_full, n_samp_residual, offset, nchan_residual; + int16_t ch_idx; + DECODER_TC_BUFFER_HANDLE hTcBuffer; + + error = IVAS_ERR_OK; + + hTcBuffer = st_ivas->hTcBuffer; + + /* if granularity changes, adapt subframe_nb_slots */ + if ( n_samples_granularity != hTcBuffer->n_samples_granularity ) + { +#ifdef DEBUGGING + int16_t nMaxSlotsPerSubframeOld; +#endif + int16_t nMaxSlotsPerSubframeNew; + + nMaxSlotsPerSubframeNew = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / n_samples_granularity; +#ifdef DEBUGGING + nMaxSlotsPerSubframeOld = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / st_ivas->hTcBuffer->n_samples_granularity; + assert( hTcBuffer->subframe_nbslots[hTcBuffer->subframes_rendered - 1] == nMaxSlotsPerSubframeOld ); + if ( n_samples_granularity < hTcBuffer->n_samples_granularity ) + { + assert( ( hTcBuffer->n_samples_granularity % n_samples_granularity ) == 0 ); + } + else + { + assert( ( n_samples_granularity % hTcBuffer->n_samples_granularity ) == 0 ); + } +#endif + /* if samples were flushed, take that into account here */ + if ( n_samples_granularity < hTcBuffer->n_samples_granularity && hTcBuffer->n_samples_flushed > 0 ) + { + hTcBuffer->subframe_nbslots[hTcBuffer->subframes_rendered - 1] = hTcBuffer->n_samples_flushed / n_samples_granularity; + hTcBuffer->n_samples_flushed = 0; + } + else + { + hTcBuffer->subframe_nbslots[hTcBuffer->subframes_rendered - 1] = nMaxSlotsPerSubframeNew; + } + } + + hTcBuffer->tc_buffer_mode = tc_buffer_mode; + hTcBuffer->nchan_transport_jbm = nchan_transport_jbm; + hTcBuffer->nchan_transport_internal = nchan_transport_internal; + hTcBuffer->nchan_buffer_full = nchan_full; + nchan_residual = nchan_transport_internal - nchan_full; + hTcBuffer->n_samples_granularity = n_samples_granularity; + /* what is remaining from last frames needs always be smaller than n_samples_granularity */ + assert( ( hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_rendered ) < n_samples_granularity ); + + /* realloc buffers */ + free( hTcBuffer->tc_buffer ); + n_samp_full = ( NS2SA( st_ivas->hDecoderConfig->output_Fs, MAX_JBM_L_FRAME_NS ) + hTcBuffer->n_samples_granularity - 1 ); + n_samp_residual = hTcBuffer->n_samples_granularity - 1; + nsamp_to_allocate = hTcBuffer->nchan_buffer_full * n_samp_full; + nsamp_to_allocate += nchan_residual * n_samp_residual; + hTcBuffer->tc_buffer = (float *) malloc( nsamp_to_allocate * sizeof( float ) ); + set_zero( hTcBuffer->tc_buffer, nsamp_to_allocate ); + offset = 0; + for ( ch_idx = 0; ch_idx < hTcBuffer->nchan_buffer_full; ch_idx++ ) + { + hTcBuffer->tc[ch_idx] = &hTcBuffer->tc_buffer[offset]; + offset += n_samp_full; + } + for ( ; ch_idx < hTcBuffer->nchan_transport_internal; ch_idx++ ) + { + hTcBuffer->tc[ch_idx] = &hTcBuffer->tc_buffer[offset]; + offset += n_samp_residual; + } + for ( ; ch_idx < MAX_TRANSPORT_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc[ch_idx] = NULL; + } + + return error; +} + +void ivas_jbm_dec_tc_buffer_playout( + Decoder_Struct *st_ivas, + const uint16_t nSamplesAsked, + uint16_t *nSamplesRendered, + float *output[] ) +{ + + int16_t ch_idx, slot_size, slots_to_render, first_sf, last_sf; + + slot_size = st_ivas->hTcBuffer->n_samples_granularity; + /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ + slots_to_render = min( st_ivas->hTcBuffer->num_slots - st_ivas->hTcBuffer->slots_rendered, nSamplesAsked / slot_size ); + st_ivas->hTcBuffer->slots_rendered += slots_to_render; + *nSamplesRendered = (uint16_t) slots_to_render * slot_size; + first_sf = st_ivas->hTcBuffer->subframes_rendered; + last_sf = first_sf; + while ( slots_to_render > 0 ) + { + slots_to_render -= st_ivas->hTcBuffer->subframe_nbslots[last_sf]; + last_sf++; + } + for ( ch_idx = 0; ch_idx < st_ivas->hTcBuffer->nchan_transport_jbm; ch_idx++ ) + { + mvr2r( st_ivas->hTcBuffer->tc[ch_idx] + st_ivas->hTcBuffer->n_samples_rendered, output[ch_idx], *nSamplesRendered ); + } + + st_ivas->hTcBuffer->subframes_rendered = last_sf; +} + +void ivas_jbm_dec_tc_buffer_close( + DECODER_TC_BUFFER_HANDLE *phTcBuffer /* i/o: TC buffer handle */ +) +{ + int16_t i; + + if ( *phTcBuffer != NULL ) + { + for ( i = 0; i < MAX_TRANSPORT_CHANNELS; i++ ) + { + ( *phTcBuffer )->tc[i] = NULL; + } + if ( ( *phTcBuffer )->tc_buffer != NULL ) + { + free( ( *phTcBuffer )->tc_buffer ); + ( *phTcBuffer )->tc_buffer = NULL; + } + + free( *phTcBuffer ); + *phTcBuffer = NULL; + } + return; +} + +void ivas_jbm_dec_td_renderers_adapt_subframes( + Decoder_Struct *st_ivas ) +{ + int16_t nMaxSlotsPerSubframe, nSlotsAvailable; + uint16_t nSlotsInLastSubframe, nSlotsInFirstSubframe; + nMaxSlotsPerSubframe = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / st_ivas->hTcBuffer->n_samples_granularity; + nSlotsAvailable = st_ivas->hTcBuffer->n_samples_available / st_ivas->hTcBuffer->n_samples_granularity; + st_ivas->hTcBuffer->num_slots = nSlotsAvailable; + st_ivas->hTcBuffer->n_samples_available = nSlotsAvailable * st_ivas->hTcBuffer->n_samples_granularity; + nSlotsInFirstSubframe = nMaxSlotsPerSubframe - st_ivas->hTcBuffer->subframe_nbslots[st_ivas->hTcBuffer->nb_subframes - 1]; + st_ivas->hTcBuffer->nb_subframes = 0; + if ( nSlotsInFirstSubframe > 0 ) + { + st_ivas->hTcBuffer->nb_subframes = 1; + nSlotsAvailable -= nSlotsInFirstSubframe; + } + st_ivas->hTcBuffer->nb_subframes += (int16_t) ceilf( (float) nSlotsAvailable / (float) nMaxSlotsPerSubframe ); + nSlotsInLastSubframe = nSlotsAvailable % nMaxSlotsPerSubframe; + set_s( st_ivas->hTcBuffer->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set_s( st_ivas->hTcBuffer->subframe_nbslots, nMaxSlotsPerSubframe, st_ivas->hTcBuffer->nb_subframes ); + if ( nSlotsInFirstSubframe > 0 ) + { + st_ivas->hTcBuffer->subframe_nbslots[0] = nSlotsInFirstSubframe; + } + if ( nSlotsInLastSubframe > 0 ) + { + st_ivas->hTcBuffer->subframe_nbslots[st_ivas->hTcBuffer->nb_subframes - 1] = nSlotsInLastSubframe; + } + st_ivas->hTcBuffer->slots_rendered = 0; + st_ivas->hTcBuffer->subframes_rendered = 0; +} + +TC_BUFFER_MODE ivas_jbm_dec_get_tc_buffer_mode( Decoder_Struct *st_ivas ) +{ + TC_BUFFER_MODE buffer_mode; + buffer_mode = TC_BUFFER_MODE_BUFFER; + + /*:TODO: wrap this maybe nicer without directly accessing the st_ivas struct...*/ + switch ( st_ivas->renderer_type ) + { + /* all renderers where we are done after TC decoding (might include DMX to mono/stereo */ + case RENDERER_DISABLE: + case RENDERER_MCMASA_MONO_STEREO: + case RENDERER_MONO_DOWNMIX: + buffer_mode = TC_BUFFER_MODE_BUFFER; + break; + case RENDERER_TD_PANNING: + case RENDERER_BINAURAL_OBJECTS_TD: + case RENDERER_BINAURAL_FASTCONV: + case RENDERER_BINAURAL_FASTCONV_ROOM: + case RENDERER_BINAURAL_PARAMETRIC: + case RENDERER_BINAURAL_PARAMETRIC_ROOM: + case RENDERER_STEREO_PARAMETRIC: + case RENDERER_DIRAC: + case RENDERER_PARAM_ISM: + case RENDERER_BINAURAL_MIXER_CONV: + case RENDERER_BINAURAL_MIXER_CONV_ROOM: + buffer_mode = TC_BUFFER_MODE_RENDERER; + break; + case RENDERER_MC_PARAMMC: + if ( st_ivas->hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) + { + buffer_mode = TC_BUFFER_MODE_BUFFER; /* TCs are already the DMX to mono or stereo */ + } + else + { + buffer_mode = TC_BUFFER_MODE_RENDERER; + } + break; + case RENDERER_MC: + if ( ivas_jbm_dec_get_num_tc_channels( st_ivas ) != st_ivas->hDecoderConfig->nchan_out ) + { + buffer_mode = TC_BUFFER_MODE_RENDERER; + } + break; + case RENDERER_SBA_LINEAR_ENC: + if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT && ( st_ivas->renderer_type == RENDERER_MC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) && ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) >= ( st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe ) ) + { + buffer_mode = TC_BUFFER_MODE_BUFFER; + } + else + { + buffer_mode = TC_BUFFER_MODE_RENDERER; + } + break; + case RENDERER_SBA_LINEAR_DEC: + if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR && ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_MONO || st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO ) ) + { + buffer_mode = TC_BUFFER_MODE_BUFFER; + } + else + { + buffer_mode = TC_BUFFER_MODE_RENDERER; + } + break; +#ifdef DEBUGGING + default: + assert( 0 ); +#endif + } + + + return buffer_mode; +} +#endif diff --git a/lib_dec/ivas_masa_dec.c b/lib_dec/ivas_masa_dec.c index 2dde4a2bdc67e4794b56b99e77cd90fa8555bfec..e69cedc6a2f2e5ff24a6631f7297b20d50720d8a 100644 --- a/lib_dec/ivas_masa_dec.c +++ b/lib_dec/ivas_masa_dec.c @@ -400,6 +400,25 @@ ivas_error ivas_masa_dec_open( st_ivas->hMasa = hMasa; +#ifdef JBM_TSM_ON_TCS + /* allocate transport channels*/ + if ( st_ivas->hDecoderConfig->voip_active == 1 && st_ivas->hTcBuffer == NULL && st_ivas->renderer_type != RENDERER_DISABLE && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + int16_t nchan_to_allocate; + TC_BUFFER_MODE buffer_mode; + buffer_mode = TC_BUFFER_MODE_RENDERER; + if ( st_ivas->mc_mode == MC_MODE_MCMASA && ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO || st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_MONO ) ) + { + buffer_mode = TC_BUFFER_MODE_BUFFER; + } + nchan_to_allocate = ivas_jbm_dec_get_num_tc_channels( st_ivas ); + if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, buffer_mode, nchan_to_allocate, nchan_to_allocate, nchan_to_allocate, NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif /* JBM_TMS_ON_TCS*/ + return error; } @@ -1245,15 +1264,277 @@ ivas_error ivas_masa_dec_reconfigure( ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &tmp, &tmp, &tmp ); +#ifdef JBM_TSM_ON_TCS + if ( st_ivas->hDecoderConfig->voip_active == 1 ) + { + int16_t tc_nchan_to_allocate; + int16_t tc_nchan_transport; + TC_BUFFER_MODE buffer_mode_new; + + buffer_mode_new = ivas_jbm_dec_get_tc_buffer_mode( st_ivas ); + tc_nchan_transport = ivas_jbm_dec_get_num_tc_channels( st_ivas ); + tc_nchan_to_allocate = tc_nchan_transport; + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + tc_nchan_to_allocate = 2 * BINAURAL_CHANNELS; + } + if ( tc_nchan_transport != st_ivas->hTcBuffer->nchan_transport_jbm || tc_nchan_to_allocate != st_ivas->hTcBuffer->nchan_transport_internal || buffer_mode_new != st_ivas->hTcBuffer->tc_buffer_mode ) + { + if ( ( error = ivas_jbm_dec_tc_buffer_reconfigure( st_ivas, buffer_mode_new, tc_nchan_transport, tc_nchan_to_allocate, tc_nchan_to_allocate, NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } +#endif return error; } +#ifdef JBM_TSM_ON_TCS +#ifndef FIX_355_REFACTOR_PARAMBIN_TO_5MS /*-------------------------------------------------------------------* * ivas_spar_param_to_masa_param_mapping() * * Determine MASA metadata from the SPAR metadata *-------------------------------------------------------------------*/ +void ivas_spar_param_to_masa_param_mapping_sf( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ + int16_t azimuth[CLDFB_NO_CHANNELS_MAX], + int16_t elevation[CLDFB_NO_CHANNELS_MAX], + float energy_ratio1[CLDFB_NO_CHANNELS_MAX], + float spreadCoherence[CLDFB_NO_CHANNELS_MAX], + float surroundingCoherence[CLDFB_NO_CHANNELS_MAX], + float inRe[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : Input audio in CLDFB domain, real */ + float inIm[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /* i : Input audio in CLDFB domain, imag */ +) +{ + int16_t i, j, sf, band, bin, slot, ch, nBins, nchan_transport; + int16_t mixer_mat_index; + DIRAC_DEC_HANDLE hDirAC; + SPAR_DEC_HANDLE hSpar; + DIFFUSE_DISTRIBUTION_HANDLE hDiffuseDist; + float mixer_mat_sf_bands_real[SPAR_DIRAC_SPLIT_START_BAND][FOA_CHANNELS][FOA_CHANNELS]; + float mixer_mat_sf_bins_real[CLDFB_NO_CHANNELS_MAX][FOA_CHANNELS][FOA_CHANNELS]; + int16_t *band_grouping; + int16_t band_start, band_end; + float transportSignalEnergies[2][CLDFB_NO_CHANNELS_MAX]; + float transportSignalCrossCorrelation[CLDFB_NO_CHANNELS_MAX]; + float instEne; + float inCovarianceMtx[FOA_CHANNELS][FOA_CHANNELS]; + float foaCovarianceMtx[FOA_CHANNELS][FOA_CHANNELS]; + float Iy, Iz, Ix, E, azi, ele, I, ratio; + float diffuseGainX, diffuseGainY, diffuseGainZ, diffuseGainSum; + int16_t slot_idx_start; + int16_t slot_idx; + float slot_fac; + int16_t subframe_idx; + + + /* Set values */ + hDirAC = st_ivas->hDirAC; + hSpar = st_ivas->hSpar; + hDirAC->numSimultaneousDirections = 1; + hDiffuseDist = st_ivas->hDirAC->hDiffuseDist; + nchan_transport = st_ivas->nchan_transport; + band_grouping = hDirAC->band_grouping; + subframe_idx = hSpar->subframes_rendered; + slot_idx_start = hSpar->slots_rendered; + + /* Init arrays */ + for ( i = 0; i < FOA_CHANNELS; i++ ) + { + set_zero( inCovarianceMtx[i], FOA_CHANNELS ); + } + for ( band = 0; band < SPAR_DIRAC_SPLIT_START_BAND; band++ ) + { + for ( i = 0; i < FOA_CHANNELS; i++ ) + { + for ( j = 0; j < FOA_CHANNELS; j++ ) + { + mixer_mat_sf_bands_real[band][i][j] = 0.0f; + } + } + } + + + slot_fac = 1.0f / (float) hSpar->subframe_nbslots[subframe_idx]; + + /* Delay the SPAR mixing matrices to have them synced with the audio */ + for ( slot_idx = 0; slot_idx < hSpar->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + sf = hSpar->render_to_md_map[slot_idx + slot_idx_start] / JBM_CLDFB_SLOTS_IN_SUBFRAME; + if ( sf < SPAR_META_DELAY_SUBFRAMES ) + { + mixer_mat_index = sf + MAX_PARAM_SPATIAL_SUBFRAMES - SPAR_META_DELAY_SUBFRAMES + 1; + for ( band = 0; band < SPAR_DIRAC_SPLIT_START_BAND; band++ ) + { + for ( i = 0; i < FOA_CHANNELS; i++ ) + { + for ( j = 0; j < FOA_CHANNELS; j++ ) + { + mixer_mat_sf_bands_real[band][i][j] += slot_fac * st_ivas->hSpar->hMdDec->mixer_mat_prev[mixer_mat_index][i][j][band]; + } + } + } + } + else + { + mixer_mat_index = sf - SPAR_META_DELAY_SUBFRAMES; + for ( band = 0; band < SPAR_DIRAC_SPLIT_START_BAND; band++ ) + { + for ( i = 0; i < FOA_CHANNELS; i++ ) + { + for ( j = 0; j < FOA_CHANNELS; j++ ) + { + mixer_mat_sf_bands_real[band][i][j] += slot_fac * st_ivas->hSpar->hMdDec->mixer_mat[i][j][band + mixer_mat_index * IVAS_MAX_NUM_BANDS]; + } + } + } + } + } + + /* Map the mixing matrices from the frequency bands to frequency bins */ + bin = 0; + + for ( band = 0; band < SPAR_DIRAC_SPLIT_START_BAND; band++ ) + { + band_start = band_grouping[band]; + band_end = band_grouping[band + 1]; + for ( bin = band_start; bin < band_end; bin++ ) + { + for ( i = 0; i < FOA_CHANNELS; i++ ) + { + for ( j = 0; j < FOA_CHANNELS; j++ ) + { + mixer_mat_sf_bins_real[bin][i][j] = mixer_mat_sf_bands_real[band][i][j]; + } + } + } + } + + nBins = bin; + + + /* Determine MASA metadata */ + + /* Determine transport signal energies and cross correlations when more than 1 TC */ + if ( nchan_transport == 2 ) + { + set_zero( transportSignalEnergies[0], nBins ); + set_zero( transportSignalEnergies[1], nBins ); + set_zero( transportSignalCrossCorrelation, nBins ); + for ( slot = 0; slot < hDirAC->subframe_nbslots[subframe_idx]; slot++ ) + + { + for ( bin = 0; bin < nBins; bin++ ) + { + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + instEne = ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ); + instEne += ( inIm[ch][slot][bin] * inIm[ch][slot][bin] ); + transportSignalEnergies[ch][bin] += instEne; + } + transportSignalCrossCorrelation[bin] += inRe[0][slot][bin] * inRe[1][slot][bin]; + transportSignalCrossCorrelation[bin] += inIm[0][slot][bin] * inIm[1][slot][bin]; + } + } + } + + if ( hDiffuseDist != NULL ) + { + set_zero( hDiffuseDist->diffuseRatioX, CLDFB_NO_CHANNELS_MAX ); + set_zero( hDiffuseDist->diffuseRatioY, CLDFB_NO_CHANNELS_MAX ); + set_zero( hDiffuseDist->diffuseRatioZ, CLDFB_NO_CHANNELS_MAX ); + } + + for ( bin = 0; bin < nBins; bin++ ) + { + /* Set the energy of the first transport signal */ + if ( nchan_transport == 1 ) + { + inCovarianceMtx[0][0] = 1.0f; /* In case of 1TC, fixed value can be used */ + } + else + { + inCovarianceMtx[0][0] = transportSignalEnergies[0][bin]; /* In case of 2TC, use actual energies */ + } + /* Decorrelated channels assumed to have the same energy as the source channel */ + inCovarianceMtx[1][1] = inCovarianceMtx[0][0]; + inCovarianceMtx[2][2] = inCovarianceMtx[0][0]; + inCovarianceMtx[3][3] = inCovarianceMtx[0][0]; + + /* In case residuals were transmitted, use their actual energies and cross correlations */ + if ( nchan_transport == 2 ) + { + inCovarianceMtx[1][1] = transportSignalEnergies[1][bin]; + inCovarianceMtx[0][1] = transportSignalCrossCorrelation[bin]; + inCovarianceMtx[1][0] = inCovarianceMtx[0][1]; + } + + compute_foa_cov_matrix( foaCovarianceMtx, inCovarianceMtx, mixer_mat_sf_bins_real[bin] ); + + /* Estimate MASA metadata */ + Iy = foaCovarianceMtx[0][1]; /* Intensity in Y direction */ + Iz = foaCovarianceMtx[0][2]; /* Intensity in Z direction */ + Ix = foaCovarianceMtx[0][3]; /* Intensity in X direction */ + I = sqrtf( Ix * Ix + Iy * Iy + Iz * Iz ); /* Intensity vector length */ + E = ( foaCovarianceMtx[0][0] + foaCovarianceMtx[1][1] + foaCovarianceMtx[2][2] + foaCovarianceMtx[3][3] ) / 2.0f; /* Overall energy */ + azi = atan2f( Iy, Ix ); /* Azimuth */ + ele = atan2f( Iz, sqrtf( Ix * Ix + Iy * Iy ) ); /* Elevation */ + ratio = I / fmaxf( 1e-12f, E ); /* Energy ratio */ + ratio = fmaxf( 0.0f, fminf( 1.0f, ratio ) ); + + azimuth[bin] = (int16_t) roundf( azi / PI_OVER_180 ); + elevation[bin] = (int16_t) roundf( ele / PI_OVER_180 ); + energy_ratio1[bin] = ratio; + + spreadCoherence[bin] = 0.0f; + surroundingCoherence[bin] = 0.0f; + + /* Determine directional distribution of the indirect audio based on the SPAR mixing matrices (and the transport audio signals when 2 TC) */ + if ( hDiffuseDist != NULL ) + { + if ( nchan_transport == 1 ) + { + diffuseGainY = fabsf( mixer_mat_sf_bins_real[bin][1][1] ); + diffuseGainX = fabsf( mixer_mat_sf_bins_real[bin][3][2] ); + diffuseGainZ = fabsf( mixer_mat_sf_bins_real[bin][2][3] ); + } + else if ( nchan_transport == 2 ) + { + diffuseGainY = fabsf( mixer_mat_sf_bins_real[bin][1][1] * transportSignalEnergies[1][bin] ); + diffuseGainX = fabsf( mixer_mat_sf_bins_real[bin][3][2] * transportSignalEnergies[0][bin] ) + fabsf( mixer_mat_sf_bins_real[bin][3][1] * transportSignalEnergies[1][bin] ); + diffuseGainZ = fabsf( mixer_mat_sf_bins_real[bin][2][3] * transportSignalEnergies[0][bin] ) + fabsf( mixer_mat_sf_bins_real[bin][2][1] * transportSignalEnergies[1][bin] ); + } + else + { + diffuseGainY = 1.0f; + diffuseGainX = 1.0f; + diffuseGainZ = 1.0f; + } + + diffuseGainSum = diffuseGainY + diffuseGainX + diffuseGainZ; + + if ( diffuseGainSum == 0.0f ) + { + hDiffuseDist->diffuseRatioX[bin] = 1.0f / 3.0f; + hDiffuseDist->diffuseRatioY[bin] = 1.0f / 3.0f; + hDiffuseDist->diffuseRatioZ[bin] = 1.0f / 3.0f; + } + else + { + hDiffuseDist->diffuseRatioX[bin] = diffuseGainX / ( diffuseGainSum + EPSILON ); + hDiffuseDist->diffuseRatioY[bin] = diffuseGainY / ( diffuseGainSum + EPSILON ); + hDiffuseDist->diffuseRatioZ[bin] = diffuseGainZ / ( diffuseGainSum + EPSILON ); + } + } + } + + return; +} +#endif +#endif #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS void ivas_spar_param_to_masa_param_mapping( @@ -1268,8 +1549,8 @@ void ivas_spar_param_to_masa_param_mapping( int16_t dirac_write_idx; DIRAC_DEC_HANDLE hDirAC; DIFFUSE_DISTRIBUTION_HANDLE hDiffuseDist; - float mixer_mat_sf_bands_real[MAX_PARAM_SPATIAL_SUBFRAMES][SPAR_DIRAC_SPLIT_START_BAND][FOA_CHANNELS][FOA_CHANNELS]; - float mixer_mat_sf_bins_real[MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX][FOA_CHANNELS][FOA_CHANNELS]; + float mixer_mat_sf_bands_real[SPAR_DIRAC_SPLIT_START_BAND][FOA_CHANNELS][FOA_CHANNELS]; + float mixer_mat_sf_bins_real[CLDFB_NO_CHANNELS_MAX][FOA_CHANNELS][FOA_CHANNELS]; int16_t *band_grouping; int16_t band_start, band_end; float transportSignalEnergies[2][CLDFB_NO_CHANNELS_MAX]; @@ -1279,6 +1560,12 @@ void ivas_spar_param_to_masa_param_mapping( float foaCovarianceMtx[FOA_CHANNELS][FOA_CHANNELS]; float Iy, Iz, Ix, E, azi, ele, I, ratio; float diffuseGainX, diffuseGainY, diffuseGainZ, diffuseGainSum; +#ifdef JBM_TSM_ON_TCS + int16_t slot_idx, slot_idx_start, sf; + SPAR_DEC_HANDLE hSpar; + float slot_fac; +#endif + /* Set values */ hDirAC = st_ivas->hDirAC; @@ -1286,7 +1573,12 @@ void ivas_spar_param_to_masa_param_mapping( hDiffuseDist = st_ivas->hDirAC->hDiffuseDist; nchan_transport = st_ivas->nchan_transport; band_grouping = hDirAC->band_grouping; +#ifdef JBM_TSM_ON_TCS + hSpar = st_ivas->hSpar; + dirac_write_idx = hDirAC->render_to_md_map[subframe]; +#else dirac_write_idx = hDirAC->dirac_read_idx; /* Mixing matrices, from which MASA meta is determined, already have the delay compensation */ +#endif /* Init arrays */ for ( i = 0; i < FOA_CHANNELS; i++ ) @@ -1295,34 +1587,61 @@ void ivas_spar_param_to_masa_param_mapping( } /* Delay the SPAR mixing matrices to have them synced with the audio */ - if ( subframe < SPAR_META_DELAY_SUBFRAMES ) +#ifdef JBM_TSM_ON_TCS + slot_idx_start = hSpar->slots_rendered; + slot_fac = 1.0f / (float) hSpar->subframe_nbslots[subframe]; + + for ( slot_idx = 0; slot_idx < hSpar->subframe_nbslots[subframe]; slot_idx++ ) { - mixer_mat_index = subframe + MAX_PARAM_SPATIAL_SUBFRAMES - SPAR_META_DELAY_SUBFRAMES + 1; - for ( band = 0; band < SPAR_DIRAC_SPLIT_START_BAND; band++ ) + sf = hSpar->render_to_md_map[slot_idx + slot_idx_start] / JBM_CLDFB_SLOTS_IN_SUBFRAME; +#endif + if ( subframe < SPAR_META_DELAY_SUBFRAMES ) { - for ( i = 0; i < FOA_CHANNELS; i++ ) +#ifdef JBM_TSM_ON_TCS + mixer_mat_index = sf + MAX_PARAM_SPATIAL_SUBFRAMES - SPAR_META_DELAY_SUBFRAMES + 1; +#else + mixer_mat_index = subframe + MAX_PARAM_SPATIAL_SUBFRAMES - SPAR_META_DELAY_SUBFRAMES + 1; +#endif + for ( band = 0; band < SPAR_DIRAC_SPLIT_START_BAND; band++ ) { - for ( j = 0; j < FOA_CHANNELS; j++ ) + for ( i = 0; i < FOA_CHANNELS; i++ ) { - mixer_mat_sf_bands_real[subframe][band][i][j] = st_ivas->hSpar->hMdDec->mixer_mat_prev[mixer_mat_index][i][j][band]; + for ( j = 0; j < FOA_CHANNELS; j++ ) + { +#ifdef JBM_TSM_ON_TCS + mixer_mat_sf_bands_real[band][i][j] = slot_fac * st_ivas->hSpar->hMdDec->mixer_mat_prev[mixer_mat_index][i][j][band]; +#else + mixer_mat_sf_bands_real[band][i][j] = st_ivas->hSpar->hMdDec->mixer_mat_prev[mixer_mat_index][i][j][band]; +#endif + } } } } - } - else - { - mixer_mat_index = subframe - SPAR_META_DELAY_SUBFRAMES; - for ( band = 0; band < SPAR_DIRAC_SPLIT_START_BAND; band++ ) + else { - for ( i = 0; i < FOA_CHANNELS; i++ ) +#ifdef JBM_TSM_ON_TCS + mixer_mat_index = sf - SPAR_META_DELAY_SUBFRAMES; +#else + mixer_mat_index = subframe - SPAR_META_DELAY_SUBFRAMES; +#endif + for ( band = 0; band < SPAR_DIRAC_SPLIT_START_BAND; band++ ) { - for ( j = 0; j < FOA_CHANNELS; j++ ) + for ( i = 0; i < FOA_CHANNELS; i++ ) { - mixer_mat_sf_bands_real[subframe][band][i][j] = st_ivas->hSpar->hMdDec->mixer_mat[i][j][band + mixer_mat_index * IVAS_MAX_NUM_BANDS]; + for ( j = 0; j < FOA_CHANNELS; j++ ) + { +#ifdef JBM_TSM_ON_TCS + mixer_mat_sf_bands_real[band][i][j] = slot_fac * st_ivas->hSpar->hMdDec->mixer_mat[i][j][band + mixer_mat_index * IVAS_MAX_NUM_BANDS]; +#else + mixer_mat_sf_bands_real[band][i][j] = st_ivas->hSpar->hMdDec->mixer_mat[i][j][band + mixer_mat_index * IVAS_MAX_NUM_BANDS]; +#endif + } } } } +#ifdef JBM_TSM_ON_TCS } +#endif /* Map the mixing matrices from the frequency bands to frequency bins */ bin = 0; @@ -1336,7 +1655,7 @@ void ivas_spar_param_to_masa_param_mapping( { for ( j = 0; j < FOA_CHANNELS; j++ ) { - mixer_mat_sf_bins_real[subframe][bin][i][j] = mixer_mat_sf_bands_real[subframe][band][i][j]; + mixer_mat_sf_bins_real[bin][i][j] = mixer_mat_sf_bands_real[band][i][j]; } } } @@ -1351,7 +1670,11 @@ void ivas_spar_param_to_masa_param_mapping( set_zero( transportSignalEnergies[1], nBins ); set_zero( transportSignalCrossCorrelation, nBins ); +#ifdef JBM_TSM_ON_TCS + for ( slot = 0; slot < hDirAC->subframe_nbslots[subframe]; slot++ ) +#else for ( slot = 0; slot < hDirAC->subframe_nbslots; slot++ ) +#endif { for ( bin = 0; bin < nBins; bin++ ) { @@ -1369,9 +1692,15 @@ void ivas_spar_param_to_masa_param_mapping( if ( hDiffuseDist != NULL ) { +#ifdef JBM_TSM_ON_TCS + set_zero( hDiffuseDist->diffuseRatioX, CLDFB_NO_CHANNELS_MAX ); + set_zero( hDiffuseDist->diffuseRatioY, CLDFB_NO_CHANNELS_MAX ); + set_zero( hDiffuseDist->diffuseRatioZ, CLDFB_NO_CHANNELS_MAX ); +#else set_zero( hDiffuseDist->diffuseRatioX[subframe], CLDFB_NO_CHANNELS_MAX ); set_zero( hDiffuseDist->diffuseRatioY[subframe], CLDFB_NO_CHANNELS_MAX ); set_zero( hDiffuseDist->diffuseRatioZ[subframe], CLDFB_NO_CHANNELS_MAX ); +#endif } for ( bin = 0; bin < nBins; bin++ ) @@ -1398,7 +1727,7 @@ void ivas_spar_param_to_masa_param_mapping( inCovarianceMtx[1][0] = inCovarianceMtx[0][1]; } - compute_foa_cov_matrix( foaCovarianceMtx, inCovarianceMtx, mixer_mat_sf_bins_real[subframe][bin] ); + compute_foa_cov_matrix( foaCovarianceMtx, inCovarianceMtx, mixer_mat_sf_bins_real[bin] ); /* Estimate MASA metadata */ Iy = foaCovarianceMtx[0][1]; /* Intensity in Y direction */ @@ -1424,15 +1753,15 @@ void ivas_spar_param_to_masa_param_mapping( { if ( nchan_transport == 1 ) { - diffuseGainY = fabsf( mixer_mat_sf_bins_real[subframe][bin][1][1] ); - diffuseGainX = fabsf( mixer_mat_sf_bins_real[subframe][bin][3][2] ); - diffuseGainZ = fabsf( mixer_mat_sf_bins_real[subframe][bin][2][3] ); + diffuseGainY = fabsf( mixer_mat_sf_bins_real[bin][1][1] ); + diffuseGainX = fabsf( mixer_mat_sf_bins_real[bin][3][2] ); + diffuseGainZ = fabsf( mixer_mat_sf_bins_real[bin][2][3] ); } else if ( nchan_transport == 2 ) { - diffuseGainY = fabsf( mixer_mat_sf_bins_real[subframe][bin][1][1] * transportSignalEnergies[1][bin] ); - diffuseGainX = fabsf( mixer_mat_sf_bins_real[subframe][bin][3][2] * transportSignalEnergies[0][bin] ) + fabsf( mixer_mat_sf_bins_real[subframe][bin][3][1] * transportSignalEnergies[1][bin] ); - diffuseGainZ = fabsf( mixer_mat_sf_bins_real[subframe][bin][2][3] * transportSignalEnergies[0][bin] ) + fabsf( mixer_mat_sf_bins_real[subframe][bin][2][1] * transportSignalEnergies[1][bin] ); + diffuseGainY = fabsf( mixer_mat_sf_bins_real[bin][1][1] * transportSignalEnergies[1][bin] ); + diffuseGainX = fabsf( mixer_mat_sf_bins_real[bin][3][2] * transportSignalEnergies[0][bin] ) + fabsf( mixer_mat_sf_bins_real[bin][3][1] * transportSignalEnergies[1][bin] ); + diffuseGainZ = fabsf( mixer_mat_sf_bins_real[bin][2][3] * transportSignalEnergies[0][bin] ) + fabsf( mixer_mat_sf_bins_real[bin][2][1] * transportSignalEnergies[1][bin] ); } else { @@ -1443,6 +1772,20 @@ void ivas_spar_param_to_masa_param_mapping( diffuseGainSum = diffuseGainY + diffuseGainX + diffuseGainZ; +#ifdef JBM_TSM_ON_TCS + if ( diffuseGainSum == 0.0f ) + { + hDiffuseDist->diffuseRatioX[bin] = 1.0f / 3.0f; + hDiffuseDist->diffuseRatioY[bin] = 1.0f / 3.0f; + hDiffuseDist->diffuseRatioZ[bin] = 1.0f / 3.0f; + } + else + { + hDiffuseDist->diffuseRatioX[bin] = diffuseGainX / ( diffuseGainSum + EPSILON ); + hDiffuseDist->diffuseRatioY[bin] = diffuseGainY / ( diffuseGainSum + EPSILON ); + hDiffuseDist->diffuseRatioZ[bin] = diffuseGainZ / ( diffuseGainSum + EPSILON ); + } +#else if ( diffuseGainSum == 0.0f ) { hDiffuseDist->diffuseRatioX[subframe][bin] = 1.0f / 3.0f; @@ -1455,6 +1798,7 @@ void ivas_spar_param_to_masa_param_mapping( hDiffuseDist->diffuseRatioY[subframe][bin] = diffuseGainY / ( diffuseGainSum + EPSILON ); hDiffuseDist->diffuseRatioZ[subframe][bin] = diffuseGainZ / ( diffuseGainSum + EPSILON ); } +#endif } } @@ -1485,6 +1829,9 @@ void ivas_spar_param_to_masa_param_mapping( float foaCovarianceMtx[FOA_CHANNELS][FOA_CHANNELS]; float Iy, Iz, Ix, E, azi, ele, I, ratio; float diffuseGainX, diffuseGainY, diffuseGainZ, diffuseGainSum; +#ifdef JBM_TSM_ON_TCS + int16_t slot_idx_start; +#endif /* Set values */ hDirAC = st_ivas->hDirAC; @@ -1555,6 +1902,10 @@ void ivas_spar_param_to_masa_param_mapping( } nBins = bin; +#ifdef JBM_TSM_ON_TCS + slot_idx_start = st_ivas->hSpar->slots_rendered; +#endif + /* Determine MASA metadata */ for ( sf = firstSubframe; sf < ( firstSubframe + nSubframes ); sf++ ) { @@ -1564,10 +1915,17 @@ void ivas_spar_param_to_masa_param_mapping( set_zero( transportSignalEnergies[0], nBins ); set_zero( transportSignalEnergies[1], nBins ); set_zero( transportSignalCrossCorrelation, nBins ); - - for ( slot = 0; slot < hDirAC->subframe_nbslots; slot++ ) +#ifdef JBM_TSM_ON_TCS + for ( slot = 0; slot < (uint8_t) hDirAC->subframe_nbslots[sf]; slot++ ) +#else + for ( slot = 0; slot < (uint8_t) hDirAC->subframe_nbslots; slot++ ) +#endif { +#ifdef JBM_TSM_ON_TCS + int16_t slotThis = slot + slot_idx_start; +#else int16_t slotThis = slot + ( hDirAC->subframe_nbslots * sf ); +#endif for ( bin = 0; bin < nBins; bin++ ) { @@ -1675,6 +2033,9 @@ void ivas_spar_param_to_masa_param_mapping( } dirac_write_idx = ( dirac_write_idx + 1 ) % hDirAC->dirac_md_buffer_length; +#ifdef JBM_TSM_ON_TCS + slot_idx_start += st_ivas->hSpar->subframe_nbslots[sf]; +#endif } return; diff --git a/lib_dec/ivas_mc_param_dec.c b/lib_dec/ivas_mc_param_dec.c index 65748bdf9558532621deff3270e518e416437120..d19e2d33ccb1ab0ff5254d1a3b7dcbd48b23adc1 100644 --- a/lib_dec/ivas_mc_param_dec.c +++ b/lib_dec/ivas_mc_param_dec.c @@ -76,7 +76,11 @@ typedef struct parameter_band_mapping_struct static void ivas_param_mc_dec_init( PARAM_MC_DEC_HANDLE hParamMC, const int16_t nchan_in, const int16_t nchan_out ); +#ifdef JBM_TSM_ON_TCS +static void param_mc_protoSignalComputation( float *RealBuffer, float *ImagBuffer, float *proto_frame_f, const PARAM_MC_DIFF_PROTO_INFO *diff_proto_info, const int16_t num_freq_bands ); +#else static void param_mc_protoSignalComputation( float RealBuffer[PARAM_MC_MAX_TRANSPORT_CHANS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], float ImagBuffer[PARAM_MC_MAX_TRANSPORT_CHANS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], float *proto_frame_f, const PARAM_MC_DIFF_PROTO_INFO *diff_proto_info, const int16_t slot_index, const int16_t num_freq_bands ); +#endif static void ivas_param_mc_dec_copy_diffuse_proto( PARAM_MC_DEC_HANDLE hParamMC, float Cldfb_buffer_real[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float Cldfb_buffer_imag[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nY, const int16_t slot_idx ); @@ -86,13 +90,23 @@ static int16_t ivas_param_mc_uniform_decoder( float *seq, const int16_t sz_seq, static void ivas_param_mc_dequantize_cov( PARAM_MC_DEC_HANDLE hDirAC, float *ild_q, float *icc_q, const int16_t param_band_index, const int16_t nY_int, const PARAM_MC_SYNTHESIS_CONF synth_conf, const int16_t nY, const int16_t nX, float *Cx_state, float *Cproto, float *Cy_state ); +#ifdef JBM_TSM_ON_TCS +static void ivas_param_mc_get_mixing_matrices( PARAM_MC_DEC_HANDLE hParamMC, IVAS_OUTPUT_SETUP *hSynthesisOutputSetup, float Cx_in[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], float *mixing_matrix[], float *mixing_matrix_res[], const int16_t nY_int, const PARAM_MC_SYNTHESIS_CONF synth_conf, const int16_t nX, const int16_t nY ); + +static void ivas_param_mc_get_mono_stereo_mixing_matrices( PARAM_MC_DEC_HANDLE hParamMC, float Cx_in[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], float *mixing_matrix[], float *mixing_matrix_res[], const int16_t nY_intern, const int16_t nX, const int16_t nY_cov ); +#else static void ivas_param_mc_get_mixing_matrices( PARAM_MC_DEC_HANDLE hParamMC, IVAS_OUTPUT_SETUP *hSynthesisOutputSetup, float Cx_in[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], float mixing_matrix[PARAM_MC_MAX_PARAMETER_BANDS][MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS], float mixing_matrix_res[PARAM_MC_MAX_PARAMETER_BANDS_RES][MAX_CICP_CHANNELS * MAX_CICP_CHANNELS], const int16_t nY_int, const PARAM_MC_SYNTHESIS_CONF synth_conf, const int16_t nX, const int16_t nY ); static void ivas_param_mc_get_mono_stereo_mixing_matrices( PARAM_MC_DEC_HANDLE hParamMC, float Cx_in[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], float mixing_matrix[PARAM_MC_MAX_PARAMETER_BANDS][MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS], float mixing_matrix_res[PARAM_MC_MAX_PARAMETER_BANDS_RES][MAX_CICP_CHANNELS * MAX_CICP_CHANNELS], const int16_t nY_intern, const int16_t nX, const int16_t nY_cov ); +#endif +#ifdef JBM_TSM_ON_TCS +static void param_mc_update_mixing_matrices( PARAM_MC_DEC_HANDLE hParamMC, float *mixing_matrix[], float *mixing_matrix_res[], const uint16_t nX, const uint16_t nY ); +#else static void param_mc_update_mixing_matrices( PARAM_MC_DEC_HANDLE hParamMC, float mixing_matrix[PARAM_MC_MAX_PARAMETER_BANDS][MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS], float mixing_matrix_res[PARAM_MC_MAX_PARAMETER_BANDS_RES][MAX_CICP_CHANNELS * MAX_CICP_CHANNELS], const uint16_t nX, const uint16_t nY ); +#endif -static void param_mc_compute_interpolator( const uint16_t bAttackPresent, const uint16_t attackPos, const uint16_t interp_length, float *interpolator ); +static void ivas_param_mc_dec_compute_interpolator( const uint16_t bAttackPresent, const uint16_t attackPos, const uint16_t interp_length, float *interpolator ); static void param_mc_set_num_synth_bands( const int32_t output_Fs, PARAM_MC_DEC_HANDLE hParamMC ); @@ -224,7 +238,13 @@ ivas_error ivas_param_mc_dec_open( *-----------------------------------------------------------------*/ hParamMC->slot_size = (int16_t) ( output_Fs / FRAMES_PER_SEC ) / CLDFB_NO_COL_MAX; +#ifdef JBM_TSM_ON_TCS + set_s( hParamMC->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set_s( hParamMC->subframe_nbslots, PARAM_MC_MAX_NSLOTS_IN_SUBFRAME, DEFAULT_JBM_SUBFRAMES_5MS ); + hParamMC->nb_subframes = DEFAULT_JBM_SUBFRAMES_5MS; +#else hParamMC->subframe_nbslots = CLDFB_NO_COL_MAX / PARAM_MC_NSUBFRAMES_DEC; +#endif hParamMC->num_freq_bands = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); hParamMC->max_band_energy_compensation = hParamMC->num_freq_bands; @@ -420,6 +440,9 @@ ivas_error ivas_param_mc_dec_open( return error; } +#ifdef JBM_TSM_ON_TCS + ivas_param_mc_dec_compute_interpolator( 0, 0, DEFAULT_JBM_CLDFB_TIMESLOTS, hParamMC->h_output_synthesis_params.interpolator ); +#endif /* Head rotation */ if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) && st_ivas->hDecoderConfig->Opt_Headrotation ) @@ -455,6 +478,30 @@ ivas_error ivas_param_mc_dec_open( ivas_param_mc_dec_init( hParamMC, nchan_transport, nchan_out_cov ); +#ifdef JBM_TSM_ON_TCS + if ( st_ivas->hDecoderConfig->voip_active && hParamMC->synthesis_conf != PARAM_MC_SYNTH_MONO_STEREO ) + { + hParamMC->Cldfb_RealBuffer_tc = (float *) malloc( MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hParamMC->num_freq_bands * sizeof( float ) ); + set_zero( hParamMC->Cldfb_RealBuffer_tc, MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hParamMC->num_freq_bands ); + hParamMC->Cldfb_ImagBuffer_tc = (float *) malloc( MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hParamMC->num_freq_bands * sizeof( float ) ); + set_zero( hParamMC->Cldfb_ImagBuffer_tc, MAX_JBM_CLDFB_TIMESLOTS * nchan_transport * hParamMC->num_freq_bands ); + if ( st_ivas->hTcBuffer == NULL ) + { + if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, TC_BUFFER_MODE_RENDERER, nchan_transport, nchan_transport, 0, NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + else + { + hParamMC->Cldfb_RealBuffer_tc = NULL; + hParamMC->Cldfb_ImagBuffer_tc = NULL; + } + hParamMC->subframes_rendered = 0; + hParamMC->slots_rendered = 0; +#endif + st_ivas->hParamMC = hParamMC; return error; @@ -597,12 +644,14 @@ ivas_error ivas_param_mc_dec_reconfig( #endif } - /*-----------------------------------------------------------------* - * set input parameters - *-----------------------------------------------------------------*/ + /*-----------------------------------------------------------------* + * set input parameters + *-----------------------------------------------------------------*/ +#ifndef JBM_TSM_ON_TCS hParamMC->slot_size = (int16_t) ( output_Fs / FRAMES_PER_SEC ) / CLDFB_NO_COL_MAX; hParamMC->subframe_nbslots = CLDFB_NO_COL_MAX / PARAM_MC_NSUBFRAMES_DEC; +#endif hParamMC->num_freq_bands = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); hParamMC->max_band_energy_compensation = hParamMC->num_freq_bands; @@ -914,6 +963,10 @@ ivas_error ivas_param_mc_dec_reconfig( return error; } +#ifdef JBM_TSM_ON_TCS + ivas_param_mc_dec_compute_interpolator( 0, 0, DEFAULT_JBM_CLDFB_TIMESLOTS, hParamMC->h_output_synthesis_params.interpolator ); +#endif + ivas_dirac_dec_output_synthesis_cov_init( &( hParamMC->h_output_synthesis_cov_state ), nchan_transport, nchan_out_cov, hParamMC->hMetadataPMC->num_parameter_bands, max_param_band_residual ); @@ -1124,6 +1177,19 @@ void ivas_param_mc_dec_close( hParamMC->hoa_encoder = NULL; } +#ifdef JBM_TSM_ON_TCS + if ( hParamMC->Cldfb_RealBuffer_tc != NULL ) + { + free( hParamMC->Cldfb_RealBuffer_tc ); + hParamMC->Cldfb_RealBuffer_tc = NULL; + } + if ( hParamMC->Cldfb_ImagBuffer_tc != NULL ) + { + free( hParamMC->Cldfb_ImagBuffer_tc ); + hParamMC->Cldfb_ImagBuffer_tc = NULL; + } +#endif + free( *hParamMC_out ); *hParamMC_out = NULL; @@ -1241,7 +1307,9 @@ void ivas_param_mc_dec_read_BS( num_lfe_bands = 0; } - param_mc_compute_interpolator( hMetadataPMC->bAttackPresent, hMetadataPMC->attackIndex, PARAM_MC_MAX_NSLOTS, hParamMC->h_output_synthesis_params.interpolator ); +#ifndef JBM_TSM_ON_TCS + ivas_param_mc_dec_compute_interpolator( hMetadataPMC->bAttackPresent, hMetadataPMC->attackIndex, PARAM_MC_MAX_NSLOTS, hParamMC->h_output_synthesis_params.interpolator ); +#endif if ( hMetadataPMC->flag_use_adaptive_icc_map == 1 ) { @@ -1328,8 +1396,10 @@ void ivas_param_mc_dec_read_BS( /* for PLC, use the saved ILDs and ICCs from the past and set the transient flag and transient position to zero */ hMetadataPMC->bAttackPresent = 0; hMetadataPMC->attackIndex = 0; +#ifndef JBM_TSM_ON_TCS #ifdef FIX_431_PARAMMC_PLC_INTERPOLATOR - param_mc_compute_interpolator( hMetadataPMC->bAttackPresent, hMetadataPMC->attackIndex, PARAM_MC_MAX_NSLOTS, hParamMC->h_output_synthesis_params.interpolator ); + ivas_param_mc_dec_compute_interpolator( hMetadataPMC->bAttackPresent, hMetadataPMC->attackIndex, PARAM_MC_MAX_NSLOTS, hParamMC->h_output_synthesis_params.interpolator ); +#endif #endif } @@ -1338,6 +1408,149 @@ void ivas_param_mc_dec_read_BS( return; } +#ifdef JBM_TSM_ON_TCS +void ivas_param_mc_dec_digest_tc( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const uint8_t nCldfbSlots, /* i : number of CLFBS slots in the transport channels */ + float *transport_channels_f[] /* i : synthesized core-coder transport channels/DirAC output */ +) +{ + PARAM_MC_DEC_HANDLE hParamMC; + int16_t i, ch; + int16_t slot_idx, param_band_idx; + int16_t nchan_transport, nchan_out_transport, nchan_out_cldfb; + int16_t nchan_out_cov; + /*CLDFB*/ + float cx[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; + float cx_imag[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; + float real_part, imag_part; + /* format converter */ + int16_t channel_active[MAX_OUTPUT_CHANNELS]; + IVAS_OUTPUT_SETUP *hSynthesisOutputSetup; + + hParamMC = st_ivas->hParamMC; + assert( hParamMC ); + + push_wmops( "param_mc_dec_digest_tc" ); + + set_s( channel_active, 0, MAX_CICP_CHANNELS ); + nchan_transport = st_ivas->nchan_transport; + nchan_out_transport = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; + + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + nchan_out_cldfb = BINAURAL_CHANNELS; + set_s( channel_active, 1, nchan_out_cldfb ); + nchan_out_cov = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; + hSynthesisOutputSetup = &st_ivas->hTransSetup; + } + else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB ) + { + nchan_out_cov = nchan_out_transport; + nchan_out_cldfb = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; + hSynthesisOutputSetup = &st_ivas->hTransSetup; + } + else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) + { + nchan_out_cov = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; + nchan_out_cldfb = nchan_out_cov; + set_s( channel_active, 1, nchan_out_cov ); + hSynthesisOutputSetup = &st_ivas->hOutSetup; + } + else + { + nchan_out_cov = nchan_out_transport; + nchan_out_cldfb = nchan_out_transport; + set_s( channel_active, 1, nchan_out_cov ); + hSynthesisOutputSetup = &st_ivas->hTransSetup; + } + + /* adapt transient position */ + if ( hParamMC->hMetadataPMC->bAttackPresent ) + { + hParamMC->hMetadataPMC->attackIndex = (int16_t) max( 0, hParamMC->hMetadataPMC->attackIndex + ( ( nCldfbSlots - DEFAULT_JBM_CLDFB_TIMESLOTS ) / 2 ) ); + } + /* adapt subframes */ + hParamMC->num_slots = nCldfbSlots; + hParamMC->slots_rendered = 0; + hParamMC->subframes_rendered = 0; + ivas_jbm_dec_get_adapted_subframes( nCldfbSlots, hParamMC->subframe_nbslots, &hParamMC->nb_subframes ); + + ivas_param_mc_dec_compute_interpolator( hParamMC->hMetadataPMC->bAttackPresent, hParamMC->hMetadataPMC->attackIndex, nCldfbSlots, hParamMC->h_output_synthesis_params.interpolator ); + + for ( param_band_idx = 0; param_band_idx < PARAM_MC_MAX_PARAMETER_BANDS; param_band_idx++ ) + { + set_zero( cx[param_band_idx], PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS ); + set_zero( cx_imag[param_band_idx], PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS ); + } + + /* slot loop for gathering the input data */ + for ( slot_idx = 0; slot_idx < nCldfbSlots; slot_idx++ ) + { + float RealBuffer[CLDFB_NO_CHANNELS_MAX]; + float ImagBuffer[CLDFB_NO_CHANNELS_MAX]; + + /* CLDFB Analysis*/ + for ( ch = 0; ch < nchan_transport; ch++ ) + { + cldfbAnalysis_ts( &( transport_channels_f[ch][hParamMC->num_freq_bands * slot_idx] ), RealBuffer, ImagBuffer, hParamMC->num_freq_bands, st_ivas->cldfbAnaDec[ch] ); + + mvr2r( RealBuffer, &hParamMC->Cldfb_RealBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport + ch * hParamMC->num_freq_bands], hParamMC->num_freq_bands ); + mvr2r( ImagBuffer, &hParamMC->Cldfb_ImagBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport + ch * hParamMC->num_freq_bands], hParamMC->num_freq_bands ); + } + + if ( slot_idx >= 2 * hParamMC->hMetadataPMC->attackIndex ) + { + ivas_dirac_dec_output_synthesis_cov_param_mc_collect_slot( &hParamMC->Cldfb_RealBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport], &hParamMC->Cldfb_ImagBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport], cx, cx_imag, hParamMC, nchan_transport ); + } + } + + /* map from complex input covariance to real values */ + for ( param_band_idx = 0; param_band_idx < hParamMC->num_param_bands_synth; param_band_idx++ ) + { + /* Cx for transport channels */ + for ( i = 0; i < nchan_transport * nchan_transport; i++ ) + { + real_part = cx[param_band_idx][i]; + imag_part = cx_imag[param_band_idx][i]; + + /* (a-ib)(c+id) = ac + bd + i(ad-bc) */ + if ( param_band_idx < hParamMC->max_param_band_abs_cov ) + { + cx[param_band_idx][i] = sqrtf( real_part * real_part + imag_part * imag_part ); + } + else + { + cx[param_band_idx][i] = real_part; + } + } + } + + /* we have to do it similar to the encoder in case of attacks (i.e. accumulate two bands) to ensure correct DMX of the target covariance*/ + if ( hParamMC->hMetadataPMC->bAttackPresent && ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) ) + { + for ( param_band_idx = 0; param_band_idx < hParamMC->num_param_bands_synth; param_band_idx += 2 ) + { + v_add( cx[param_band_idx], cx[param_band_idx + 1], cx[param_band_idx], nchan_transport * nchan_transport ); + mvr2r( cx[param_band_idx], cx[param_band_idx + 1], nchan_transport * nchan_transport ); + } + } + + + if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) + { + ivas_param_mc_get_mono_stereo_mixing_matrices( hParamMC, cx, hParamMC->h_output_synthesis_cov_state.mixing_matrix, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, nchan_out_transport, nchan_transport, nchan_out_cov ); + } + else + { + /* generate mixing matrices */ + ivas_param_mc_get_mixing_matrices( hParamMC, hSynthesisOutputSetup, cx, hParamMC->h_output_synthesis_cov_state.mixing_matrix, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, nchan_out_transport, hParamMC->synthesis_conf, nchan_transport, nchan_out_cov ); + } + + pop_wmops(); + + return; +} /*------------------------------------------------------------------------- * ivas_param_mc_dec() @@ -1345,6 +1558,321 @@ void ivas_param_mc_dec_read_BS( * Parametric MC decoding process *------------------------------------------------------------------------*/ +void ivas_param_mc_dec_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ + uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ + uint16_t *nSamplesAvailable, /* o : number of CLDFB slots still to render */ + float *output_f[] /* o : rendered time signal */ +) +{ + PARAM_MC_DEC_HANDLE hParamMC; + int16_t i, ch; + int16_t subframe_idx; + int16_t slot_idx, slot_idx_start, slot_idx_start_cldfb_synth, first_sf, last_sf, slots_to_render; + int16_t nchan_transport, nchan_out_transport, nchan_out_cldfb; + int16_t nchan_out_cov; + /*CLDFB*/ + float Cldfb_RealBuffer[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + /*Decorrelator*/ + float onset_filter[MAX_CICP_CHANNELS * CLDFB_NO_CHANNELS_MAX]; + /* format converter */ + int16_t channel_active[MAX_OUTPUT_CHANNELS]; + uint16_t nband_synth, nbands_to_zero; + uint16_t nchan_out_init; + uint32_t output_Fs; + + hParamMC = st_ivas->hParamMC; + assert( hParamMC ); + + push_wmops( "param_mc_dec_render" ); + + set_s( channel_active, 0, MAX_CICP_CHANNELS ); + nchan_transport = st_ivas->nchan_transport; + nchan_out_transport = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; + nchan_out_init = nchan_out_transport; + output_Fs = st_ivas->hDecoderConfig->output_Fs; + + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + nchan_out_cldfb = BINAURAL_CHANNELS; + set_s( channel_active, 1, nchan_out_cldfb ); + if ( st_ivas->hHeadTrackData ) + { + nchan_out_init = MAX_INTERN_CHANNELS; + } + nchan_out_cov = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; + } + else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB ) + { + nchan_out_cov = nchan_out_transport; + nchan_out_cldfb = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; + } + else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) + { + nchan_out_cov = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; + nchan_out_cldfb = nchan_out_cov; + set_s( channel_active, 1, nchan_out_cov ); + } + else + { + nchan_out_cov = nchan_out_transport; + nchan_out_cldfb = nchan_out_transport; + set_s( channel_active, 1, nchan_out_cov ); + } + + /* set everything to zero that will not be decoded */ + nband_synth = hParamMC->band_grouping[hParamMC->num_param_bands_synth]; + nbands_to_zero = hParamMC->num_freq_bands - nband_synth; + for ( ch = 0; ch < nchan_out_init; ch++ ) + { + for ( slot_idx = 0; slot_idx < JBM_CLDFB_SLOTS_IN_SUBFRAME; slot_idx++ ) + { + set_zero( &( Cldfb_RealBuffer[ch][slot_idx][nband_synth] ), nbands_to_zero ); + set_zero( &( Cldfb_ImagBuffer[ch][slot_idx][nband_synth] ), nbands_to_zero ); + } + } + + /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ + slots_to_render = min( hParamMC->num_slots - hParamMC->slots_rendered, nSamplesAsked / NS2SA( output_Fs, CLDFB_SLOT_NS ) ); + *nSamplesRendered = slots_to_render * NS2SA( output_Fs, CLDFB_SLOT_NS ); + first_sf = hParamMC->subframes_rendered; + last_sf = first_sf; + while ( slots_to_render > 0 ) + { + slots_to_render -= hParamMC->subframe_nbslots[last_sf]; + last_sf++; + } +#ifdef DEBUGGING + assert( slots_to_render == 0 ); +#endif + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + { + for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + { + slots_to_render += hParamMC->subframe_nbslots[subframe_idx]; + } + } + slot_idx_start = hParamMC->slots_rendered; + slot_idx_start_cldfb_synth = 0; + for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + { + for ( slot_idx = 0; slot_idx < hParamMC->subframe_nbslots[subframe_idx]; slot_idx++, hParamMC->slots_rendered++ ) + { + + if ( hParamMC->max_band_decorr > 0 ) + { + /*-----------------------------------------------------------------* + * protoype signal computation + *-----------------------------------------------------------------*/ + + param_mc_protoSignalComputation( &hParamMC->Cldfb_RealBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + &hParamMC->Cldfb_ImagBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + hParamMC->proto_frame_f, hParamMC->diff_proto_info, + hParamMC->num_freq_bands ); + + /*-----------------------------------------------------------------* + * frequency domain decorrelation + *-----------------------------------------------------------------*/ + + /* decorrelate prototype frame */ + ivas_dirac_dec_decorr_process( hParamMC->num_freq_bands, + hParamMC->num_outputs_diff, + hParamMC->diff_proto_info->num_protos_diff, + DIRAC_SYNTHESIS_COV_MC_LS, + nchan_transport, + hParamMC->proto_frame_f, + hParamMC->diff_proto_info->num_protos_diff, + hParamMC->diff_proto_info->proto_index_diff, + hParamMC->proto_frame_dec_f, + onset_filter, + hParamMC->h_freq_domain_decorr_ap_params, + hParamMC->h_freq_domain_decorr_ap_state ); + + /* copy decorrelated frame directly to output CLDFB buffer, acts also as intermediate */ + /* memory for the decorrelated signal */ + ivas_param_mc_dec_copy_diffuse_proto( hParamMC, Cldfb_RealBuffer, Cldfb_ImagBuffer, nchan_out_cov, slot_idx ); + } + + /*-----------------------------------------------------------------* + * output synthesis + *-----------------------------------------------------------------*/ + + ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot( &hParamMC->Cldfb_RealBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + &hParamMC->Cldfb_ImagBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + Cldfb_RealBuffer, Cldfb_ImagBuffer, + hParamMC->h_output_synthesis_cov_state.mixing_matrix, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, slot_idx, slot_idx + slot_idx_start, + nchan_transport, nchan_out_cov, hParamMC ); + + if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) ) + { + if ( st_ivas->hHeadTrackData && st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) + { + ivas_param_mc_mc2sba_cldfb( st_ivas->hTransSetup, hParamMC->hoa_encoder, slot_idx, Cldfb_RealBuffer, Cldfb_ImagBuffer, nband_synth, GAIN_LFE ); + } + else + { + /* remove LFE */ + uint16_t idx_out; + uint16_t idx_lfe; + IVAS_OUTPUT_SETUP hLsSetup; + + hLsSetup = st_ivas->hTransSetup; + + /* If LFE should be rendered, add it to other channels before removing */ + if ( st_ivas->hBinRenderer->render_lfe ) + { + for ( idx_lfe = 0; idx_lfe < hLsSetup.num_lfe; idx_lfe++ ) + { + /* Copy just the first band of LFE*/ + v_multc( Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], ( GAIN_LFE / hLsSetup.nchan_out_woLFE ), Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1 ); + v_multc( Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], ( GAIN_LFE / hLsSetup.nchan_out_woLFE ), Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1 ); + + for ( ch = 0; ch < ( hLsSetup.nchan_out_woLFE + hLsSetup.num_lfe ); ch++ ) + { + if ( hLsSetup.index_lfe[idx_lfe] != ch ) + { + v_add( Cldfb_RealBuffer[ch][slot_idx], Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], Cldfb_RealBuffer[ch][slot_idx], 1 ); + v_add( Cldfb_ImagBuffer[ch][slot_idx], Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], Cldfb_ImagBuffer[ch][slot_idx], 1 ); + } + } + } + } + + idx_out = 0; + idx_lfe = 0; + + for ( ch = 0; ch < ( hLsSetup.nchan_out_woLFE + hLsSetup.num_lfe ); ch++ ) + { + if ( ( hLsSetup.num_lfe > 0 ) && ( hLsSetup.index_lfe[idx_lfe] == ch ) ) + { + if ( idx_lfe < ( hLsSetup.num_lfe - 1 ) ) + { + idx_lfe++; + } + } + else if ( ch != idx_out ) + { + mvr2r( Cldfb_RealBuffer[ch][slot_idx], Cldfb_RealBuffer[idx_out][slot_idx], nband_synth ); + mvr2r( Cldfb_ImagBuffer[ch][slot_idx], Cldfb_ImagBuffer[idx_out][slot_idx], nband_synth ); + idx_out++; + } + else + { + idx_out++; + } + } + } + } + } + + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + ivas_binRenderer( st_ivas->hBinRenderer, st_ivas->hHeadTrackData, hParamMC->subframe_nbslots[subframe_idx], + Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer ); + } + else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB ) + { + /* format conversion*/ + ivas_lssetupconversion_process_param_mc( st_ivas, hParamMC->subframe_nbslots[subframe_idx], Cldfb_RealBuffer, Cldfb_ImagBuffer, channel_active ); + } + + /* CLDFB synthesis */ + for ( ch = 0; ch < nchan_out_cldfb; ch++ ) + { + float *RealBuffer[16]; + float *ImagBuffer[16]; + + if ( channel_active[ch] ) + { + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ + for ( i = 0; i < hParamMC->subframe_nbslots[subframe_idx]; i++ ) + { + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + RealBuffer[i] = Cldfb_RealBuffer_Binaural[ch][i]; + ImagBuffer[i] = Cldfb_ImagBuffer_Binaural[ch][i]; + } + else + { + RealBuffer[i] = Cldfb_RealBuffer[ch][i]; + ImagBuffer[i] = Cldfb_ImagBuffer[ch][i]; + } + } + cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands] ), + hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch] ); + } + else + { + set_f( &( output_f[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands] ), 0.0f, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx] ); + } + } + slot_idx_start += hParamMC->subframe_nbslots[subframe_idx]; + slot_idx_start_cldfb_synth += hParamMC->subframe_nbslots[subframe_idx]; + } + + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + { + ivas_mc2sba( st_ivas->hIntSetup, output_f, output_f, hParamMC->num_freq_bands * slots_to_render, st_ivas->hOutSetup.ambisonics_order, 0.f ); + } + + /* update */ + if ( hParamMC->slots_rendered == hParamMC->num_slots ) + { + hParamMC->hMetadataPMC->last_coded_bwidth = hParamMC->hMetadataPMC->coded_bwidth; + param_mc_update_mixing_matrices( hParamMC, hParamMC->h_output_synthesis_cov_state.mixing_matrix, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, nchan_transport, nchan_out_cov ); + } + hParamMC->subframes_rendered = last_sf; + *nSamplesAvailable = ( hParamMC->num_slots - hParamMC->slots_rendered ) * NS2SA( output_Fs, CLDFB_SLOT_NS ); + pop_wmops(); + + return; +} +#endif + +/*------------------------------------------------------------------------- + * ivas_param_mc_dec() + * + * Parametric MC decoding process + *------------------------------------------------------------------------*/ +#ifdef JBM_TSM_ON_TCS +void ivas_param_mc_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + float *output_f[] /* i/o: synthesized core-coder transport channels/DirAC output */ +) +{ + PARAM_MC_DEC_HANDLE hParamMC; + float Cldfb_RealBuffer_in[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_NSLOTS * CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_in[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_NSLOTS * CLDFB_NO_CHANNELS_MAX]; + uint16_t nSamplesAsked, nSamplesAvailable, nSamplesRendered; + + hParamMC = st_ivas->hParamMC; + assert( hParamMC ); + push_wmops( "param_mc_dec" ); + + /* set some handle pointers to the stack buffers */ + hParamMC->Cldfb_RealBuffer_tc = Cldfb_RealBuffer_in; + hParamMC->Cldfb_ImagBuffer_tc = Cldfb_ImagBuffer_in; + + nSamplesAsked = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ); + ivas_param_mc_dec_digest_tc( st_ivas, DEFAULT_JBM_CLDFB_TIMESLOTS, output_f ); + ivas_param_mc_dec_render( st_ivas, nSamplesAsked, &nSamplesRendered, &nSamplesAvailable, output_f ); +#ifdef DEBUGGING + assert( nSamplesRendered == nSamplesAsked ); + assert( nSamplesAvailable == 0 ); +#endif + + /* set handle pointers back to NULL */ + hParamMC->Cldfb_RealBuffer_tc = NULL; + hParamMC->Cldfb_ImagBuffer_tc = NULL; + + pop_wmops(); + return; +} +#else void ivas_param_mc_dec( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels/DirAC output */ @@ -1352,7 +1880,8 @@ void ivas_param_mc_dec( { PARAM_MC_DEC_HANDLE hParamMC; int16_t i, ch; - int16_t subframe_idx, num_subframes; + int16_t subframe_idx; + int16_t nb_subframes; int16_t slot_idx, param_band_idx, slot_idx_start; int16_t nchan_transport, nchan_out_transport, nchan_out_cldfb; int16_t nchan_out_cov; @@ -1499,12 +2028,13 @@ void ivas_param_mc_dec( ivas_param_mc_get_mixing_matrices( hParamMC, hSynthesisOutputSetup, cx, mixing_matrix, mixing_matrix_res, nchan_out_transport, hParamMC->synthesis_conf, nchan_transport, nchan_out_cov ); } + /*** split here... ***/ + /* subframe loop for synthesis*/ - num_subframes = CLDFB_NO_COL_MAX / hParamMC->subframe_nbslots; - for ( subframe_idx = 0; subframe_idx < num_subframes; subframe_idx++ ) + nb_subframes = CLDFB_NO_COL_MAX / hParamMC->subframe_nbslots; + for ( subframe_idx = 0; subframe_idx < nb_subframes; subframe_idx++ ) { slot_idx_start = subframe_idx * hParamMC->subframe_nbslots; - for ( slot_idx = 0; slot_idx < hParamMC->subframe_nbslots; slot_idx++ ) { @@ -1643,7 +2173,6 @@ void ivas_param_mc_dec( ImagBuffer[i] = Cldfb_ImagBuffer[ch][i]; } } - cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][slot_idx_start * hParamMC->num_freq_bands] ), hParamMC->num_freq_bands * hParamMC->subframe_nbslots, st_ivas->cldfbSynDec[ch] ); } @@ -1666,6 +2195,7 @@ void ivas_param_mc_dec( return; } +#endif /*------------------------------------------------------------------------- @@ -1740,12 +2270,19 @@ static void ivas_param_mc_dec_init( *------------------------------------------------------------------------*/ static void param_mc_protoSignalComputation( +#ifdef JBM_TSM_ON_TCS + float *RealBuffer, /* i : CLDFB samples of the transport channels (real part) */ + float *ImagBuffer, /* i : CLDFB samples of the transport channels (imaginary part) */ +#else float RealBuffer[PARAM_MC_MAX_TRANSPORT_CHANS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : CLDFB samples of the transport channels (real part) */ float ImagBuffer[PARAM_MC_MAX_TRANSPORT_CHANS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], /* i : CLDFB samples of the transport channels (imaginary part) */ - float *proto_frame_f, /* o : interleaved complex prototype CLDFB samples */ - const PARAM_MC_DIFF_PROTO_INFO *diff_proto_info, /* i : prototype generation information */ - const int16_t slot_index, /* i : current slot index */ - const int16_t num_freq_bands /* i : number of frequency bands for the prototypes */ +#endif + float *proto_frame_f, /* o : interleaved complex prototype CLDFB samples */ + const PARAM_MC_DIFF_PROTO_INFO *diff_proto_info, /* i : prototype generation information */ +#ifndef JBM_TSM_ON_TCS + const int16_t slot_index, /* i : current slot index */ +#endif + const int16_t num_freq_bands /* i : number of frequency bands for the prototypes */ ) { int16_t band; @@ -1766,8 +2303,13 @@ static void param_mc_protoSignalComputation( int16_t source_ch_idx = diff_proto_info->source_chan_idx[proto_ch_idx][source_ch_cnt]; p_proto_frame = &proto_frame_f[proto_ch_idx * num_freq_bands * 2]; +#ifdef JBM_TSM_ON_TCS + p_real_buffer = &RealBuffer[source_ch_idx * num_freq_bands]; + p_imag_buffer = &ImagBuffer[source_ch_idx * num_freq_bands]; +#else p_real_buffer = &RealBuffer[source_ch_idx][slot_index][0]; p_imag_buffer = &ImagBuffer[source_ch_idx][slot_index][0]; +#endif for ( band = 0; band < num_freq_bands; band++ ) { @@ -1939,15 +2481,18 @@ static int16_t ivas_param_mc_range_decoder_LC( * * compute the interpolator used in the final synthesis *------------------------------------------------------------------------*/ - -static void param_mc_compute_interpolator( +static void ivas_param_mc_dec_compute_interpolator( const uint16_t bAttackPresent, /* i : flag indicating if we have a transient in the current frame */ const uint16_t attackPos, /* i : position of the transient */ const uint16_t interp_length, /* i : number of interpolation values to be calculated */ float *interpolator /* o : interpolator */ ) { +#ifdef JBM_TSM_ON_TCS + int16_t idx; +#else uint16_t idx; +#endif if ( bAttackPresent ) { @@ -1962,10 +2507,14 @@ static void param_mc_compute_interpolator( } else { +#ifdef JBM_TSM_ON_TCS + ivas_jbm_dec_get_adapted_linear_interpolator( DEFAULT_JBM_CLDFB_TIMESLOTS, interp_length, interpolator ); +#else for ( idx = 1; idx <= interp_length; ++idx ) { interpolator[idx - 1] = (float) idx / (float) interp_length; } +#endif } return; @@ -2025,12 +2574,17 @@ static void ivas_param_mc_get_mixing_matrices( PARAM_MC_DEC_HANDLE hParamMC, /* i : Parametric MC handle */ IVAS_OUTPUT_SETUP *hSynthesisOutputSetup, float Cx_in[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], /* i : input covariance for all parameter bands */ - float mixing_matrix[PARAM_MC_MAX_PARAMETER_BANDS][MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS], /* o : direct mixing matrices for all parameter bands */ - float mixing_matrix_res[PARAM_MC_MAX_PARAMETER_BANDS_RES][MAX_CICP_CHANNELS * MAX_CICP_CHANNELS], /* o : residual mixing matrices for all parameter bands */ - const int16_t nY_intern, /* i : number of channels in the transported format */ - const PARAM_MC_SYNTHESIS_CONF synth_config, /* i : Parametric MC synthesis config */ - const int16_t nX, /* i : number of transport channels */ - const int16_t nY_cov /* i : number of covariance synthesis output channels */ +#ifdef JBM_TSM_ON_TCS + float *mixing_matrix[], /* o : direct mixing matrices for all parameter bands */ + float *mixing_matrix_res[], /* o : residual mixing matrices for all parameter bands */ +#else + float mixing_matrix[PARAM_MC_MAX_PARAMETER_BANDS][MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS], /* o : direct mixing matrices for all parameter bands */ + float mixing_matrix_res[PARAM_MC_MAX_PARAMETER_BANDS_RES][MAX_CICP_CHANNELS * MAX_CICP_CHANNELS], /* o : residual mixing matrices for all parameter bands */ +#endif + const int16_t nY_intern, /* i : number of channels in the transported format */ + const PARAM_MC_SYNTHESIS_CONF synth_config, /* i : Parametric MC synthesis config */ + const int16_t nX, /* i : number of transport channels */ + const int16_t nY_cov /* i : number of covariance synthesis output channels */ ) { int16_t param_band_idx; @@ -2279,11 +2833,16 @@ static void ivas_param_mc_get_mixing_matrices( static void ivas_param_mc_get_mono_stereo_mixing_matrices( PARAM_MC_DEC_HANDLE hParamMC, /* i : Parametric MC handle */ float Cx_in[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], /* i : transport channel covariance for all parameter bands */ - float mixing_matrix[PARAM_MC_MAX_PARAMETER_BANDS][MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS], /* o : direct mixing matrix */ - float mixing_matrix_res[PARAM_MC_MAX_PARAMETER_BANDS_RES][MAX_CICP_CHANNELS * MAX_CICP_CHANNELS], /* o : residual mixing matrix (set to zero) */ - const int16_t nY_intern, /* i : number of channels of the transport format */ - const int16_t nX, /* i : number of transport channels */ - const int16_t nY_cov ) /* i : number of output channels */ +#ifdef JBM_TSM_ON_TCS + float *mixing_matrix[], /* o : direct mixing matrices for all parameter bands */ + float *mixing_matrix_res[], /* o : residual mixing matrices for all parameter bands */ +#else + float mixing_matrix[PARAM_MC_MAX_PARAMETER_BANDS][MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS], /* o : direct mixing matrix */ + float mixing_matrix_res[PARAM_MC_MAX_PARAMETER_BANDS_RES][MAX_CICP_CHANNELS * MAX_CICP_CHANNELS], /* o : residual mixing matrix (set to zero) */ +#endif + const int16_t nY_intern, /* i : number of channels of the transport format */ + const int16_t nX, /* i : number of transport channels */ + const int16_t nY_cov ) /* i : number of output channels */ { int16_t param_band_idx; float Cx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; @@ -2398,17 +2957,21 @@ static void ivas_param_mc_get_mono_stereo_mixing_matrices( *------------------------------------------------------------------------*/ static void param_mc_update_mixing_matrices( - PARAM_MC_DEC_HANDLE hParamMC, /* i/o: Parametric MC handle */ + PARAM_MC_DEC_HANDLE hParamMC, /* i/o: Parametric MC handle */ +#ifdef JBM_TSM_ON_TCS + float *mixing_matrix[], /* i : direct mixing matrices for the frame just processed */ + float *mixing_matrix_res[], /* i : residual mixing matrices for the frame just processed */ +#else float mixing_matrix[PARAM_MC_MAX_PARAMETER_BANDS][MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS], /* i : direct mixing matrices for the frame just processed */ float mixing_matrix_res[PARAM_MC_MAX_PARAMETER_BANDS_RES][MAX_CICP_CHANNELS * MAX_CICP_CHANNELS], /* i : residual mixing matrices for the frame just processed */ - const uint16_t nX, /* i : number of transport channels */ - const uint16_t nY ) /* i : number of synthesis channels */ +#endif + const uint16_t nX, /* i : number of transport channels */ + const uint16_t nY ) /* i : number of synthesis channels */ { uint16_t param_band_idx; for ( param_band_idx = 0; param_band_idx < hParamMC->hMetadataPMC->nbands_coded; param_band_idx++ ) { - /* final mixing */ int16_t brange[2]; brange[0] = hParamMC->band_grouping[param_band_idx]; diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index a4beb49d94d021ce1b5945c16228900aa955ea60..0dd2552c0f161ac455ac746f48d179993dea6eac 100755 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -54,8 +54,11 @@ * Local function prototypes *-----------------------------------------------------------------------*/ +#ifdef JBM_TSM_ON_TCS +static ivas_error ivas_mc_dec_reconfig( Decoder_Struct *st_ivas, uint16_t *nSamplesRendered, int16_t *data ); +#else static ivas_error ivas_mc_dec_reconfig( Decoder_Struct *st_ivas ); - +#endif /*--------------------------------------------------------------------------* * ivas_mct_dec() @@ -630,6 +633,11 @@ void ivas_mct_dec_close( ivas_error ivas_mc_dec_config( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const int16_t idx /* i : LS config. index */ +#ifdef JBM_TSM_ON_TCS + , + uint16_t *nSamplesRendered, /* o : samples flushed from last frame (JBM) */ + int16_t *data /* o : flushed samples (JBM) */ +#endif ) { AUDIO_CONFIG signaled_config; @@ -659,7 +667,11 @@ ivas_error ivas_mc_dec_config( { if ( st_ivas->hDecoderConfig->last_ivas_total_brate != st_ivas->hDecoderConfig->ivas_total_brate || st_ivas->transport_config != signaled_config || last_mc_mode != st_ivas->mc_mode ) { +#ifdef JBM_TSM_ON_TCS + ivas_mc_dec_reconfig( st_ivas, nSamplesRendered, data ); +#else ivas_mc_dec_reconfig( st_ivas ); +#endif } } @@ -678,6 +690,11 @@ ivas_error ivas_mc_dec_config( static ivas_error ivas_mc_dec_reconfig( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +#ifdef JBM_TSM_ON_TCS + , + uint16_t *nSamplesRendered, /* o : number of samples flushed from the last frame (JBM) */ + int16_t *data /* o : flushed samples (JBM) */ +#endif ) { int16_t nchan_transport_old, nSCE_old, nCPE_old, sba_dirac_stereo_flag_old, nchan_hp20_old; @@ -687,6 +704,14 @@ static ivas_error ivas_mc_dec_reconfig( Decoder_State *st; ivas_error error; MC_MODE mc_mode, last_mc_mode; +#ifdef JBM_TSM_ON_TCS + TC_BUFFER_MODE tc_buffer_mode_new; + int16_t tc_nchan_tc_new; + int16_t tc_nchan_allocate_new; + int16_t tc_granularity_new; + AUDIO_CONFIG intern_config_old; + IVAS_OUTPUT_SETUP hIntSetupOld; +#endif error = IVAS_ERR_OK; @@ -717,13 +742,63 @@ static ivas_error ivas_mc_dec_reconfig( } st_ivas->sba_dirac_stereo_flag = ivas_get_sba_dirac_stereo_flag( st_ivas ); +#ifdef JBM_TSM_ON_TCS + /* save old IntSetup, might be needed for JBM flushing...*/ + intern_config_old = st_ivas->intern_config; + hIntSetupOld = st_ivas->hIntSetup; + tc_granularity_new = 1; +#endif + /* renderer might have changed, reselect */ renderer_type_old = st_ivas->renderer_type; ivas_renderer_select( st_ivas ); + /* side effect of the renderer selection can be a changed internal config */ ivas_output_init( &( st_ivas->hIntSetup ), st_ivas->intern_config ); +#ifdef JBM_TSM_ON_TCS + if ( st_ivas->hDecoderConfig->voip_active ) + { + /* transfer subframe info from DirAC or ParamMC to central tc buffer */ + if ( last_mc_mode == MC_MODE_PARAMMC ) + { + st_ivas->hTcBuffer->nb_subframes = st_ivas->hParamMC->nb_subframes; + st_ivas->hTcBuffer->subframes_rendered = st_ivas->hParamMC->subframes_rendered; + st_ivas->hTcBuffer->num_slots = st_ivas->hParamMC->num_slots; + st_ivas->hTcBuffer->slots_rendered = st_ivas->hParamMC->slots_rendered; + mvs2s( st_ivas->hParamMC->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); + } + else if ( last_mc_mode == MC_MODE_MCMASA && st_ivas->hDirAC != NULL ) + { + st_ivas->hTcBuffer->nb_subframes = st_ivas->hDirAC->nb_subframes; + st_ivas->hTcBuffer->subframes_rendered = st_ivas->hDirAC->subframes_rendered; + st_ivas->hTcBuffer->num_slots = st_ivas->hDirAC->num_slots; + st_ivas->hTcBuffer->slots_rendered = st_ivas->hDirAC->slots_rendered; + mvs2s( st_ivas->hDirAC->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); + } + /* JBM: when granularity goes down (e.g. MCT with CREND -> ParamMC with binaural fastconv + render what still fits in the new granularity */ + tc_granularity_new = ivas_jbm_dec_get_render_granularity( st_ivas->renderer_type, st_ivas->hDecoderConfig->output_Fs ); + if ( tc_granularity_new < st_ivas->hTcBuffer->n_samples_granularity ) + { + if ( ( error = ivas_jbm_dec_flush_renderer( st_ivas, tc_granularity_new, renderer_type_old, intern_config_old, &hIntSetupOld, last_mc_mode, ISM_MODE_NONE, nSamplesRendered, data ) ) != IVAS_ERR_OK ) + { + return error; + } + } + /* JBM: when granularity goes up set samples to discard at the beginning of the frame */ + else if ( tc_granularity_new > st_ivas->hTcBuffer->n_samples_granularity ) + { + if ( ( error = ivas_jbm_dec_set_discard_samples( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } +#endif + + if ( st_ivas->mc_mode == MC_MODE_MCT ) { st_ivas->nchan_transport = ivas_mc_ls_setup_get_num_channels( ivas_mc_map_output_config_to_mc_ls_setup( st_ivas->transport_config ) ); @@ -747,6 +822,14 @@ static ivas_error ivas_mc_dec_reconfig( ivas_masa_dec_close( &( st_ivas->hMasa ) ); ivas_qmetadata_close( &st_ivas->hQMetaData ); +#ifdef JBM_TSM_ON_TCS + if ( st_ivas->hDirAC != NULL ) + { + ivas_dirac_dec_close( &st_ivas->hDirAC ); + vbap_free_data( &( st_ivas->hVBAPdata ) ); + } +#endif + /* init LS conversion if the renderer type asks for it */ if ( st_ivas->renderer_type == RENDERER_MC && st_ivas->hLsSetUpConversion == NULL ) { @@ -826,6 +909,16 @@ static ivas_error ivas_mc_dec_reconfig( ivas_masa_dec_close( &( st_ivas->hMasa ) ); ivas_qmetadata_close( &st_ivas->hQMetaData ); +#ifdef JBM_TSM_ON_TCS + if ( st_ivas->hDirAC != NULL ) + { + ivas_dirac_dec_close( &st_ivas->hDirAC ); + + vbap_free_data( &( st_ivas->hVBAPdata ) ); + } +#endif + + if ( last_mc_mode == MC_MODE_MCT ) { if ( st_ivas->hMCT != NULL && st_ivas->nchan_transport <= CPE_CHANNELS ) @@ -1072,6 +1165,10 @@ static ivas_error ivas_mc_dec_reconfig( else if ( st_ivas->renderer_type == RENDERER_DISABLE && st_ivas->hDirAC != NULL ) { ivas_dirac_dec_close( &( st_ivas->hDirAC ) ); + +#ifdef JBM_TSM_ON_TCS + vbap_free_data( &( st_ivas->hVBAPdata ) ); +#endif } } @@ -1221,5 +1318,57 @@ static ivas_error ivas_mc_dec_reconfig( } #endif +#ifdef JBM_TSM_ON_TCS + /*-----------------------------------------------------------------* + * Reconfigure TC buffer + *-----------------------------------------------------------------*/ + if ( st_ivas->hDecoderConfig->voip_active == 1 ) + { + int16_t tc_nchan_full_new; + DECODER_TC_BUFFER_HANDLE hTcBuffer; + + hTcBuffer = st_ivas->hTcBuffer; + tc_buffer_mode_new = ivas_jbm_dec_get_tc_buffer_mode( st_ivas ); + tc_nchan_tc_new = ivas_jbm_dec_get_num_tc_channels( st_ivas ); + tc_nchan_allocate_new = tc_nchan_tc_new; + tc_nchan_full_new = tc_nchan_tc_new; + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + tc_nchan_allocate_new = 2 * BINAURAL_CHANNELS; + tc_nchan_full_new = tc_nchan_allocate_new; + } + if ( st_ivas->mc_mode == MC_MODE_PARAMMC && st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_MONO && st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_STEREO ) + { + tc_nchan_full_new = 0; + } + /* reconfigure buffer */ + if ( hTcBuffer->tc_buffer_mode != tc_buffer_mode_new || hTcBuffer->nchan_transport_jbm != tc_nchan_tc_new || + hTcBuffer->nchan_buffer_full != tc_nchan_full_new || hTcBuffer->nchan_transport_internal != tc_nchan_allocate_new || + tc_granularity_new != hTcBuffer->n_samples_granularity ) + { + if ( ( error = ivas_jbm_dec_tc_buffer_reconfigure( st_ivas, tc_buffer_mode_new, tc_nchan_tc_new, tc_nchan_allocate_new, tc_nchan_full_new, tc_granularity_new ) ) != IVAS_ERR_OK ) + { + return error; + } + } + /* transfer subframe info from central tc buffer to ParamMC or McMASA (DirAC) */ + if ( st_ivas->hDirAC != NULL ) + { + st_ivas->hDirAC->nb_subframes = st_ivas->hTcBuffer->nb_subframes; + st_ivas->hDirAC->subframes_rendered = st_ivas->hTcBuffer->subframes_rendered; + st_ivas->hDirAC->num_slots = st_ivas->hTcBuffer->num_slots; + st_ivas->hDirAC->slots_rendered = st_ivas->hTcBuffer->slots_rendered; + mvs2s( st_ivas->hTcBuffer->subframe_nbslots, st_ivas->hDirAC->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); + } + else if ( st_ivas->hParamMC != NULL ) + { + st_ivas->hParamMC->nb_subframes = st_ivas->hTcBuffer->nb_subframes; + st_ivas->hParamMC->subframes_rendered = st_ivas->hTcBuffer->subframes_rendered; + st_ivas->hParamMC->num_slots = st_ivas->hTcBuffer->num_slots; + st_ivas->hParamMC->slots_rendered = st_ivas->hTcBuffer->slots_rendered; + mvs2s( st_ivas->hTcBuffer->subframe_nbslots, st_ivas->hParamMC->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); + } + } +#endif return error; } diff --git a/lib_dec/ivas_objectRenderer_internal.c b/lib_dec/ivas_objectRenderer_internal.c index f1c1fc04f207070edf6ba1652ee35d1fa5fe3c77..873c75938a8866752dc2bb2a01ba7998a9f6e475 100644 --- a/lib_dec/ivas_objectRenderer_internal.c +++ b/lib_dec/ivas_objectRenderer_internal.c @@ -66,9 +66,13 @@ ivas_error ivas_td_binaural_open( *---------------------------------------------------------------------*/ ivas_error ivas_td_binaural_renderer( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ +#ifdef JBM_TSM_ON_TCS + float *output[], /* i/o: SCE channels / Binaural synthesis */ +#else float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ - const int16_t output_frame /* i : output frame length */ +#endif + const int16_t output_frame /* i : output frame length */ ) { return ivas_td_binaural_renderer_unwrap( @@ -78,3 +82,89 @@ ivas_error ivas_td_binaural_renderer( st_ivas->hIsmMetaData, st_ivas->hDecoderConfig->Opt_Headrotation, ( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->Quaternions : NULL, ( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->Pos : NULL, output, output_frame ); } + +#ifdef JBM_TSM_ON_TCS +/*---------------------------------------------------------------------* + * ObjRenderIVASFrame() + * + * Receives the current frames for the object streams, updates metadata + * and renders the current frame. + *---------------------------------------------------------------------*/ + +void ObjRenderIVASSubframe( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float *output[], /* i/o: SCE channels / Binaural synthesis */ + const int16_t n_samples_asked ) +{ + int16_t first_sf, last_sf, subframe_idx; + float reverb_signal[BINAURAL_CHANNELS][L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; + float *p_reverb_signal[BINAURAL_CHANNELS]; + float *output_f_local[BINAURAL_CHANNELS]; + float *tc_local[MAX_TRANSPORT_CHANNELS]; + int16_t ch, slot_size, slots_to_render, output_frame; + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + p_reverb_signal[ch] = reverb_signal[ch]; + } + for ( ch = 0; ch < st_ivas->hTcBuffer->nchan_transport_internal; ch++ ) + { + tc_local[ch] = st_ivas->hTcBuffer->tc[ch] + st_ivas->hTcBuffer->n_samples_rendered; + } + for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) + { + output_f_local[ch] = output[ch]; + } + slot_size = st_ivas->hTcBuffer->n_samples_granularity; + /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ + slots_to_render = min( st_ivas->hTcBuffer->num_slots - st_ivas->hTcBuffer->slots_rendered, n_samples_asked / slot_size ); + first_sf = st_ivas->hTcBuffer->subframes_rendered; + last_sf = first_sf; + st_ivas->hTcBuffer->slots_rendered += slots_to_render; + while ( slots_to_render > 0 ) + { + slots_to_render -= st_ivas->hTcBuffer->subframe_nbslots[last_sf]; + last_sf++; + } + + for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + { + output_frame = st_ivas->hTcBuffer->subframe_nbslots[subframe_idx] * st_ivas->hTcBuffer->n_samples_granularity; + /* Update object position(s) */ + TDREND_Update_object_positions( st_ivas->hBinRendererTd, st_ivas->nchan_transport, LFE_CHANNEL, st_ivas->ivas_format, st_ivas->hIsmMetaData, tc_local ); + + /* Update the listener's location/orientation */ + TDREND_Update_listener_orientation( st_ivas->hBinRendererTd, + st_ivas->hDecoderConfig->Opt_Headrotation, + ( st_ivas->hHeadTrackData != NULL ) ? &st_ivas->hHeadTrackData->Quaternions[0] : NULL, + ( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->Pos : NULL ); + + if ( ( st_ivas->hRenderConfig != NULL ) && ( st_ivas->hRenderConfig->roomAcoustics.late_reverb_on ) ) + { + ivas_reverb_process( st_ivas->hReverb, st_ivas->transport_config, 0, tc_local, p_reverb_signal, 0 ); + } + + /* Render subframe */ + TDREND_GetMix( st_ivas->hBinRendererTd, output_f_local, output_frame, 0 ); + + if ( st_ivas->hRenderConfig != NULL ) /* Renderer Configuration not enabled in TD standalone renderer */ + { + if ( st_ivas->hRenderConfig->roomAcoustics.late_reverb_on ) + { + /* add reverb to rendered signals */ + v_add( reverb_signal[0], output_f_local[0], output_f_local[0], output_frame ); + v_add( reverb_signal[1], output_f_local[1], output_f_local[1], output_frame ); + } + } + for ( ch = 0; ch < st_ivas->hTcBuffer->nchan_transport_internal; ch++ ) + { + tc_local[ch] += output_frame; + } + for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) + { + output_f_local[ch] += output_frame; + } + } + st_ivas->hTcBuffer->subframes_rendered = last_sf; + return; +} +#endif diff --git a/lib_dec/ivas_out_setup_conversion.c b/lib_dec/ivas_out_setup_conversion.c index c4cb10ff859a5a479ca280538093652b4343084c..3f95113f604f8249e1034492dfe1c92fb926645c 100644 --- a/lib_dec/ivas_out_setup_conversion.c +++ b/lib_dec/ivas_out_setup_conversion.c @@ -510,7 +510,12 @@ void ivas_ls_setup_conversion( const int16_t input_chans, /* i : number of input channels to the renderer */ #endif const int16_t output_frame, /* i : frame length */ - float output[][L_FRAME48k] /* i/o: LS input/output synthesis signal */ +#ifdef JBM_TSM_ON_TCS + float *input[], /* i : LS input/output synthesis signal */ + float *output[] /* i/o: LS input/output synthesis signal */ +#else + float output[][L_FRAME48k] /* i/o: LS input/output synthesis signal */ +#endif ) { int16_t chInIdx, chOutIdx, idx; @@ -541,14 +546,22 @@ void ivas_ls_setup_conversion( { for ( idx = 0; idx < output_frame; idx++ ) { +#ifdef JBM_TSM_ON_TCS + output_tmp[chOutIdx][idx] += input[chInIdx][idx]; +#else output_tmp[chOutIdx][idx] += output[chInIdx][idx]; +#endif } } else { for ( idx = 0; idx < output_frame; idx++ ) { +#ifdef JBM_TSM_ON_TCS + tmpVal = dmxCoeff * input[chInIdx][idx]; +#else tmpVal = dmxCoeff * output[chInIdx][idx]; +#endif output_tmp[chOutIdx][idx] += tmpVal; } } @@ -1146,7 +1159,10 @@ void ivas_ls_setup_conversion_process_mdct_param_mc( *-------------------------------------------------------------------------*/ void ivas_lssetupconversion_process_param_mc( - Decoder_Struct *st_ivas, /* i/o: LS setup conversion renderer handle */ + Decoder_Struct *st_ivas, /* i/o: LS setup conversion renderer handle */ +#ifdef JBM_TSM_ON_TCS + int16_t num_timeslots, +#endif float Cldfb_RealBuffer_InOut[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals */ float Cldfb_ImagBuffer_InOut[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals */ int16_t channel_active[MAX_CICP_CHANNELS] /* i : bitmap indicating which output channels are active */ @@ -1173,8 +1189,12 @@ void ivas_lssetupconversion_process_param_mc( set_s( channel_active, 0, outChannels ); - /* Loop over each time slots and compute dmx for each time slot */ +/* Loop over each time slots and compute dmx for each time slot */ +#ifdef JBM_TSM_ON_TCS + for ( slotIdx = 0; slotIdx < num_timeslots; slotIdx++ ) +#else for ( slotIdx = 0; slotIdx < st_ivas->hParamMC->subframe_nbslots; slotIdx++ ) +#endif { /* copy buffers */ for ( chInIdx = 0; chInIdx < inChannels; chInIdx++ ) diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index 0b5cce1ca5e4f6ae2b981a3d11e5877618e52137..471916d12c556f38d07f274bdea2deaa7f6a02f5 100755 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -114,6 +114,7 @@ ivas_error ivas_sba_dec_reconfigure( #endif RENDERER_TYPE old_renderer_type; + DECODER_CONFIG_HANDLE hDecoderConfig; ivas_error error; error = IVAS_ERR_OK; @@ -129,7 +130,6 @@ ivas_error ivas_sba_dec_reconfigure( * Set SBA high-level parameters * Save old SBA high-level parameters *-----------------------------------------------------------------*/ - ivas_init_dec_get_num_cldfb_instances( st_ivas, &numCldfbAnalyses_old, &numCldfbSyntheses_old ); nchan_hp20_old = getNumChanSynthesis( st_ivas ); nSCE_old = st_ivas->nSCE; @@ -138,6 +138,26 @@ ivas_error ivas_sba_dec_reconfigure( sba_dirac_stereo_flag_old = st_ivas->sba_dirac_stereo_flag; st_ivas->sba_analysis_order = ivas_sba_get_analysis_order( ivas_total_brate, st_ivas->sba_order ); +#ifdef JBM_TSM_ON_TCS + /* save old */ + if ( st_ivas->hDirAC == NULL && st_ivas->hSpar != NULL ) + { + st_ivas->hTcBuffer->num_slots = st_ivas->hSpar->num_slots; + st_ivas->hTcBuffer->nb_subframes = st_ivas->hSpar->nb_subframes; + st_ivas->hTcBuffer->slots_rendered = st_ivas->hSpar->slots_rendered; + st_ivas->hTcBuffer->subframes_rendered = st_ivas->hSpar->subframes_rendered; + mvs2s( st_ivas->hSpar->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); + } + else if ( st_ivas->hDirAC != NULL ) + { + st_ivas->hTcBuffer->num_slots = st_ivas->hDirAC->num_slots; + st_ivas->hTcBuffer->nb_subframes = st_ivas->hDirAC->nb_subframes; + st_ivas->hTcBuffer->slots_rendered = st_ivas->hDirAC->slots_rendered; + st_ivas->hTcBuffer->subframes_rendered = st_ivas->hDirAC->subframes_rendered; + mvs2s( st_ivas->hDirAC->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); + } +#endif + /*-----------------------------------------------------------------* * Allocate, initialize, and configure SBA handles *-----------------------------------------------------------------*/ @@ -182,6 +202,14 @@ ivas_error ivas_sba_dec_reconfigure( hSpar = st_ivas->hSpar; st_ivas->sba_dirac_stereo_flag = ivas_get_sba_dirac_stereo_flag( st_ivas ); +#ifdef JBM_TSM_ON_TCS + /* synchronize subframe info */ + st_ivas->hSpar->num_slots = st_ivas->hTcBuffer->num_slots; + st_ivas->hSpar->nb_subframes = st_ivas->hTcBuffer->nb_subframes; + st_ivas->hSpar->slots_rendered = st_ivas->hTcBuffer->slots_rendered; + st_ivas->hSpar->subframes_rendered = st_ivas->hTcBuffer->subframes_rendered; + mvs2s( st_ivas->hTcBuffer->subframe_nbslots, st_ivas->hSpar->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); +#endif if ( st_ivas->nchan_transport == 1 ) { st_ivas->element_mode_init = IVAS_SCE; @@ -264,6 +292,14 @@ ivas_error ivas_sba_dec_reconfigure( { return error; } +#ifdef JBM_TSM_ON_TCS + /* synchronize subframe info */ + st_ivas->hDirAC->num_slots = st_ivas->hTcBuffer->num_slots; + st_ivas->hDirAC->nb_subframes = st_ivas->hTcBuffer->nb_subframes; + st_ivas->hDirAC->slots_rendered = st_ivas->hTcBuffer->slots_rendered; + st_ivas->hDirAC->subframes_rendered = st_ivas->hTcBuffer->subframes_rendered; + mvs2s( st_ivas->hTcBuffer->subframe_nbslots, st_ivas->hDirAC->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); +#endif } if ( ( error = ivas_dirac_sba_config( st_ivas->hQMetaData, @@ -337,5 +373,183 @@ ivas_error ivas_sba_dec_reconfigure( return error; } +#ifdef JBM_TSM_ON_TCS + /*-----------------------------------------------------------------* + * TC buffer + *-----------------------------------------------------------------*/ + if ( st_ivas->hDecoderConfig->voip_active == 1 ) + { + int16_t tc_nchan_to_allocate; + int16_t tc_nchan_tc; + TC_BUFFER_MODE tc_buffer_mode; + + tc_buffer_mode = TC_BUFFER_MODE_RENDERER; + tc_nchan_tc = ivas_jbm_dec_get_num_tc_channels( st_ivas ); + tc_nchan_to_allocate = tc_nchan_tc; + if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO || st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_MONO ) + { + tc_buffer_mode = TC_BUFFER_MODE_BUFFER; + tc_nchan_tc = st_ivas->hDecoderConfig->nchan_out; + tc_nchan_to_allocate = tc_nchan_tc; + } + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + tc_nchan_to_allocate = 2 * BINAURAL_CHANNELS; + } + else if ( st_ivas->sba_mode == SBA_MODE_SPAR ) + { + tc_nchan_to_allocate = ivas_sba_get_nchan_metadata( st_ivas->sba_analysis_order +#ifdef SPAR_TUNING + , + st_ivas->hDecoderConfig->ivas_total_brate +#endif + ); + } + else + { + if ( st_ivas->nchan_transport == 1 && ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) || ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) ) + { + tc_nchan_to_allocate++; /* we need a channel for the CNG in this case*/ + } + } + + if ( tc_nchan_tc != st_ivas->hTcBuffer->nchan_transport_jbm || tc_nchan_to_allocate != st_ivas->hTcBuffer->nchan_transport_internal || tc_buffer_mode != st_ivas->hTcBuffer->tc_buffer_mode ) + { + if ( ( error = ivas_jbm_dec_tc_buffer_reconfigure( st_ivas, tc_buffer_mode, tc_nchan_tc, tc_nchan_to_allocate, tc_nchan_to_allocate, NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } +#endif + return error; +} + +#ifdef JBM_TSM_ON_TCS +ivas_error ivas_sba_dec_digest_tc( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const int16_t nCldfbSlots, /* i : number of CLDFB slots */ + const int16_t nSamplesForRendering /* i : number of samples provided */ +) +{ + + int16_t ch_idx; + ivas_error error; + + error = IVAS_ERR_OK; + + /* set the md map */ + if ( st_ivas->hDirAC && !( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC && st_ivas->sba_mode == SBA_MODE_DIRAC ) ) + { + ivas_dirac_dec_set_md_map( st_ivas, nCldfbSlots ); + } + if ( st_ivas->sba_mode == SBA_MODE_SPAR ) + { + ivas_spar_dec_digest_tc( st_ivas, st_ivas->nchan_transport, nCldfbSlots, nSamplesForRendering ); + } + if ( st_ivas->hDiracDecBin != NULL && ( st_ivas->hDiracDecBin->useTdDecorr ) ) + { + int16_t nSamplesLeftForTD, default_frame; + float *decorr_signal[BINAURAL_CHANNELS]; + float *p_tc[2 * BINAURAL_CHANNELS]; + default_frame = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ); + nSamplesLeftForTD = nSamplesForRendering; + for ( ch_idx = 0; ch_idx < BINAURAL_CHANNELS; ch_idx++ ) + { + decorr_signal[ch_idx] = st_ivas->hTcBuffer->tc[ch_idx + BINAURAL_CHANNELS]; + p_tc[ch_idx] = st_ivas->hTcBuffer->tc[ch_idx]; + } + while ( nSamplesLeftForTD ) + { + int16_t nSamplesToDecorr = min( nSamplesLeftForTD, default_frame ); + ivas_td_decorr_process( st_ivas->hDiracDecBin->hTdDecorr, p_tc, decorr_signal, nSamplesToDecorr ); + for ( ch_idx = 0; ch_idx < BINAURAL_CHANNELS; ch_idx++ ) + { + decorr_signal[ch_idx] += nSamplesToDecorr; + p_tc[ch_idx] += nSamplesToDecorr; + } + nSamplesLeftForTD -= nSamplesToDecorr; + } + } + /* if we have a late CNG generation, do it here */ + if ( st_ivas->nchan_transport == 1 && st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->sba_mode != SBA_MODE_SPAR ) + { + Decoder_State *st = st_ivas->hSCE[0]->hCoreCoder[0]; + generate_masking_noise_lb_dirac( st->hFdCngDec->hFdCngCom, st_ivas->hTcBuffer->tc[1], nCldfbSlots, st->cna_dirac_flag && st->flag_cna ); + } return error; } + +void ivas_sba_dec_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ + uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ + uint16_t *nSamplesAvailable, /* o : number of CLDFB slots still to render */ + float *output_f[] /* o : rendered time signal */ +) +{ + int16_t slots_to_render, first_sf, last_sf, subframe_idx; + uint16_t slot_size, ch; + uint16_t nchan_internal, nchan_out; + SPAR_DEC_HANDLE hSpar; + float *output_f_local[MAX_OUTPUT_CHANNELS]; + + hSpar = st_ivas->hSpar; + nchan_internal = ivas_sba_get_nchan_metadata( st_ivas->sba_analysis_order +#ifdef SPAR_TUNING + , + st_ivas->hDecoderConfig->ivas_total_brate +#endif + ); + nchan_out = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; +#ifdef DEBUGGING + assert( hSpar ); +#endif + for ( ch = 0; ch < nchan_out; ch++ ) + { + output_f_local[ch] = output_f[ch]; + } + slot_size = NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); + /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ + slots_to_render = min( hSpar->num_slots - hSpar->slots_rendered, nSamplesAsked / slot_size ); + *nSamplesRendered = slots_to_render * slot_size; + first_sf = hSpar->subframes_rendered; + last_sf = first_sf; + while ( slots_to_render > 0 ) + { + slots_to_render -= hSpar->subframe_nbslots[last_sf]; + last_sf++; + } +#ifdef DEBUGGING + assert( slots_to_render == 0 ); +#endif + for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + { + int16_t n_samples_sf = slot_size * hSpar->subframe_nbslots[subframe_idx]; + ivas_spar_dec_upmixer_sf( st_ivas, output_f_local, nchan_internal ); + for ( ch = 0; ch < nchan_out; ch++ ) + { + output_f_local[ch] += n_samples_sf; + } + } + + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC ) + { + ivas_sba_linear_renderer( output_f, *nSamplesRendered, st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hDecoderConfig->output_config, st_ivas->hOutSetup, st_ivas->hoa_dec_mtx ); + } + if ( st_ivas->hDirAC != NULL && hSpar->slots_rendered == hSpar->num_slots ) + { + if ( st_ivas->hDirAC->hConfig->dec_param_estim == 1 ) + { + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_CLDFB_TIMESLOTS ) % st_ivas->hDirAC->dirac_md_buffer_length; + } + else + { + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % st_ivas->hDirAC->dirac_md_buffer_length; + } + } + *nSamplesAvailable = ( hSpar->num_slots - hSpar->slots_rendered ) * slot_size; + + return; +} +#endif diff --git a/lib_dec/ivas_sba_rendering_internal.c b/lib_dec/ivas_sba_rendering_internal.c index 6947efa8682f16566b894bc93f7c37db98ad38b0..426348c7fece6d4f02430ac5a330ca6b41b925b5 100644 --- a/lib_dec/ivas_sba_rendering_internal.c +++ b/lib_dec/ivas_sba_rendering_internal.c @@ -65,7 +65,10 @@ void ivas_sba2mc_cldfb( float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: cldfb imag part */ const int16_t nb_channels_out, /* i : nb of output channels */ const int16_t nb_bands, /* i : nb of CLDFB bands to process */ - const float *hoa_dec_mtx /* i : HOA decoding mtx */ +#ifdef JBM_TSM_ON_TCS + const int16_t nb_timeslots, /* i : number of time slots to process */ +#endif + const float *hoa_dec_mtx /* i : HOA decoding mtx */ ) { int16_t iBlock, iBand, n, m; @@ -89,7 +92,11 @@ void ivas_sba2mc_cldfb( g = hoa_dec_mtx[SBA_NHARM_HOA3 * n + m]; p_realOut = realOut[n]; p_imagOut = imagOut[n]; +#ifdef JBM_TSM_ON_TCS + for ( iBlock = 0; iBlock < nb_timeslots; iBlock++ ) +#else for ( iBlock = 0; iBlock < MAX_PARAM_SPATIAL_SUBFRAMES; iBlock++ ) +#endif { p_real = RealBuffer[m][iBlock]; p_imag = ImagBuffer[m][iBlock]; @@ -108,7 +115,11 @@ void ivas_sba2mc_cldfb( { p_realOut = realOut[n]; p_imagOut = imagOut[n]; +#ifdef JBM_TSM_ON_TCS + for ( iBlock = 0; iBlock < nb_timeslots; iBlock++ ) +#else for ( iBlock = 0; iBlock < MAX_PARAM_SPATIAL_SUBFRAMES; iBlock++ ) +#endif { p_real = RealBuffer[n][iBlock]; p_imag = ImagBuffer[n][iBlock]; @@ -133,11 +144,16 @@ void ivas_sba2mc_cldfb( *-------------------------------------------------------------------------*/ void ivas_mc2sba( - IVAS_OUTPUT_SETUP hIntSetup, /* i : Format of decoder output */ + IVAS_OUTPUT_SETUP hIntSetup, /* i : Format of decoder output */ +#ifdef JBM_TSM_ON_TCS + float *in_buffer_td[], /* i : MC signals (on input) and the HOA3 (on output) */ + float *buffer_td[], /* i/o: MC signals (on input) and the HOA3 (on output) */ +#else float buffer_td[][L_FRAME48k], /* i/o: MC signals (on input) and the HOA3 (on output) */ - const int16_t output_frame, /* i : output frame length per channel */ - const int16_t sba_order, /* i : Ambisonic (SBA) order */ - const float gain_lfe /* i : gain for LFE, 0 = ignore LFE */ +#endif + const int16_t output_frame, /* i : output frame length per channel */ + const int16_t sba_order, /* i : Ambisonic (SBA) order */ + const float gain_lfe /* i : gain for LFE, 0 = ignore LFE */ ) { int16_t i, j, k; @@ -168,7 +184,11 @@ void ivas_mc2sba( /* Add LFE to omni W with gain*/ for ( k = 0; k < output_frame; k++ ) { +#ifdef JBM_TSM_ON_TCS + buffer_tmp[0][k] += gain_lfe * in_buffer_td[i][k]; +#else buffer_tmp[0][k] += gain_lfe * buffer_td[i][k]; +#endif } } @@ -194,7 +214,11 @@ void ivas_mc2sba( { for ( k = 0; k < output_frame; k++ ) { +#ifdef JBM_TSM_ON_TCS + buffer_tmp[j][k] += gains[j] * in_buffer_td[i][k]; +#else buffer_tmp[j][k] += gains[j] * buffer_td[i][k]; +#endif } } } @@ -279,7 +303,11 @@ int16_t ivas_sba_remapTCs( *-------------------------------------------------------------------------*/ void ivas_ism2sba( - float buffer_td[][L_FRAME48k], /* i/o: TD signal buffers */ +#ifdef JBM_TSM_ON_TCS + float *buffer_td[], /* i/o: TD signal buffers */ +#else + float buffer_td[][L_FRAME48k], /* i/o: TD signal buffers */ +#endif ISM_RENDERER_HANDLE hIsmRendererData, /* i/o: renderer data */ const ISM_METADATA_HANDLE hIsmMetaData[], /* i : object metadata */ const int16_t nchan_ism, /* i : number of objects */ @@ -335,6 +363,59 @@ void ivas_ism2sba( return; } +#ifdef JBM_TSM_ON_TCS +/*-------------------------------------------------------------------------* + * ivas_ism2sba() + * + * ISM transformed into SBA in TD domain. + *-------------------------------------------------------------------------*/ + +void ivas_ism2sba_sf( + float *buffer_in[], /* i : TC buffer */ + float *buffer_out[], /* o : TD signal buffers */ + ISM_RENDERER_HANDLE hIsmRendererData, /* i/o: renderer data */ + const int16_t num_objects, /* i : number of objects */ + const int16_t n_samples_to_render, /* i : output frame length per channel */ + const int16_t offset, /* i : offset for the interpolatr */ + const int16_t sba_order /* i : Ambisonic (SBA) order */ +) +{ + int16_t i, j, k; + float g1, *g2, *tc, *out, gain, prev_gain; + int16_t sba_num_chans; + + assert( ( sba_order <= 3 ) && "Only order up to 3 is supported!" ); + assert( hIsmRendererData != NULL && "hIsmRendererData not allocated!" ); + + + /* Init*/ + sba_num_chans = ( sba_order + 1 ) * ( sba_order + 1 ); + for ( j = 0; j < sba_num_chans; j++ ) + { + set_zero( buffer_out[j], n_samples_to_render ); + } + + for ( i = 0; i < num_objects; i++ ) + { + for ( j = 0; j < sba_num_chans; j++ ) + { + g2 = hIsmRendererData->interpolator + offset; + g1 = 1 - *g2; + tc = buffer_in[i] + offset; + out = buffer_out[j]; + gain = hIsmRendererData->gains[i][j]; + prev_gain = hIsmRendererData->prev_gains[i][j]; + for ( k = 0; k < n_samples_to_render; k++ ) + { + *( out++ ) += ( ( *( g2++ ) ) * gain + g1 * prev_gain ) * ( *( tc++ ) ); + g1 = 1.0f - *g2; + } + } + } + + return; +} +#endif /*-------------------------------------------------------------------* * ivas_sba_upmixer_renderer() @@ -348,8 +429,12 @@ void ivas_sba_upmixer_renderer( const int16_t output_frame /* i : output frame length */ ) { - int16_t i, nchan_internal; + + int16_t nchan_internal; +#ifndef JBM_TSM_ON_TCS + int16_t i; float temp; +#endif push_wmops( "ivas_sba_upmixer_renderer" ); @@ -360,6 +445,7 @@ void ivas_sba_upmixer_renderer( #endif ); +#ifndef JBM_TSM_ON_TCS if ( st_ivas->nchan_transport >= 3 ) { /*convert WYZX downmix to WYXZ*/ @@ -370,15 +456,25 @@ void ivas_sba_upmixer_renderer( output[3][i] = temp; } } +#endif /* Upmixer + Renderer */ ivas_spar_dec_upmixer( st_ivas, output, nchan_internal, output_frame ); if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC ) { +#ifdef JBM_TSM_ON_TCS + float *output_f[MAX_OUTPUT_CHANNELS]; + int16_t ch; + for ( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ ) + { + output_f[ch] = output[ch]; + } + ivas_sba_linear_renderer( output_f, output_frame, st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hDecoderConfig->output_config, st_ivas->hOutSetup, st_ivas->hoa_dec_mtx ); +#else ivas_sba_linear_renderer( output, output_frame, st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hDecoderConfig->output_config, st_ivas->hOutSetup, st_ivas->hoa_dec_mtx ); +#endif } - pop_wmops(); return; @@ -392,7 +488,11 @@ void ivas_sba_upmixer_renderer( *-------------------------------------------------------------------*/ static void ivas_sba_mtx_mult( - float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ +#ifdef JBM_TSM_ON_TCS + float *output_f[], /* i/o: synthesized core-corder transport channels/DirAC output */ +#else + float output_f[][L_FRAME48k], /* i/o: synthesized core-corder transport channels/DirAC output */ +#endif const int16_t output_frame, /* i : output frame length per channel */ const int16_t nchan_in, /* i : Number of ambisonic channels */ const IVAS_OUTPUT_SETUP output_setup, /* i : Output configuration */ @@ -452,7 +552,11 @@ static void ivas_sba_mtx_mult( *-------------------------------------------------------------------*/ ivas_error ivas_sba_linear_renderer( - float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ +#ifdef JBM_TSM_ON_TCS + float *output_f[], /* i/o: synthesized core-coder transport channels/DirAC output */ +#else + float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ +#endif const int16_t output_frame, /* i : output frame length per channel */ const int16_t nchan_in, /* i : number of input ambisonics channels */ const AUDIO_CONFIG output_config, /* i : output audio configuration */ diff --git a/lib_dec/ivas_spar_decoder.c b/lib_dec/ivas_spar_decoder.c index 154d8c41f811272478dbf948f151c026d118b2a5..22d38997ddeb09b82337e2ec4dbee906448efa46 100755 --- a/lib_dec/ivas_spar_decoder.c +++ b/lib_dec/ivas_spar_decoder.c @@ -206,6 +206,49 @@ ivas_error ivas_spar_dec_open( ivas_output_init( &( st_ivas->hTransSetup ), st_ivas->transport_config ); +#ifdef JBM_TSM_ON_TCS + set_s( hSpar->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set_s( hSpar->subframe_nbslots, JBM_CLDFB_SLOTS_IN_SUBFRAME, DEFAULT_JBM_SUBFRAMES_5MS ); + hSpar->nb_subframes = DEFAULT_JBM_SUBFRAMES_5MS; + hSpar->subframes_rendered = 0; + hSpar->slots_rendered = 0; + hSpar->num_slots = DEFAULT_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME; + /* init render timeslot mapping */ + { + int16_t map_idx; + set_s( hSpar->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); + for ( map_idx = 0; map_idx < DEFAULT_JBM_CLDFB_TIMESLOTS; map_idx++ ) + { + hSpar->render_to_md_map[map_idx] = map_idx; + } + } + /* allocate transport channels*/ + if ( st_ivas->hDecoderConfig->voip_active == 1 && st_ivas->hTcBuffer == NULL ) + { + int16_t nchan_to_allocate; + int16_t nchan_tc; + TC_BUFFER_MODE buffer_mode; + + buffer_mode = TC_BUFFER_MODE_RENDERER; + nchan_tc = ivas_jbm_dec_get_num_tc_channels( st_ivas ); + nchan_to_allocate = num_channels_internal; + if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO || st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_MONO ) + { + buffer_mode = TC_BUFFER_MODE_BUFFER; + nchan_tc = st_ivas->hDecoderConfig->nchan_out; + nchan_to_allocate = nchan_tc; + } + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + nchan_to_allocate = 2 * BINAURAL_CHANNELS; + } + if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, buffer_mode, nchan_tc, nchan_to_allocate, nchan_to_allocate, NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif + st_ivas->hSpar = hSpar; return error; @@ -1072,42 +1115,363 @@ static void ivas_spar_calc_smooth_facs( return; } +#ifdef JBM_TSM_ON_TCS +void ivas_spar_dec_agc_pca( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + float output[][L_FRAME48k], /* i/o: input/output audio channels */ + const int16_t output_frame /* i : output frame length */ +) +{ + + int16_t nchan_transport; + int16_t num_in_ingest; + DECODER_CONFIG_HANDLE hDecoderConfig; + SPAR_DEC_HANDLE hSpar; + + push_wmops( "ivas_spar_dec_agc_pca" ); + hSpar = st_ivas->hSpar; + hDecoderConfig = st_ivas->hDecoderConfig; + nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; + + if ( st_ivas->nchan_transport >= 3 ) + { + float temp; + int16_t i; + /*convert WYZX downmix to WYXZ*/ + for ( i = 0; i < output_frame; i++ ) + { + temp = output[2][i]; + output[2][i] = output[3][i]; + output[3][i] = temp; + } + } + + if ( hSpar->hMdDec->td_decorr_flag ) + { + num_in_ingest = ivas_sba_get_nchan_metadata( st_ivas->sba_analysis_order +#ifdef SPAR_TUNING + , + st_ivas->hDecoderConfig->ivas_total_brate +#endif + ); + } + else + { + num_in_ingest = nchan_transport; + } + /*---------------------------------------------------------------------* + * AGC + *---------------------------------------------------------------------*/ + + ivas_agc_dec_process( hSpar->hAgcDec, output, output, nchan_transport, output_frame ); +#ifdef DEBUG_SBA_AUDIO_DUMP + /* Dump audio signal after ivas_agc_dec_process */ + ivas_spar_dump_signal_wav( output_frame, NULL, output, st_ivas->nchan_transport, spar_foa_dec_wav[1], "ivas_agc_dec_process()" ); +#endif + + if ( hSpar->hPCA != NULL ) + { + ivas_pca_dec( hSpar->hPCA, output_frame, num_in_ingest, hDecoderConfig->ivas_total_brate, hDecoderConfig->last_ivas_total_brate, st_ivas->bfi, output ); +#ifdef DEBUG_SBA_AUDIO_DUMP + /* Dump audio signal after ivas_pca_dec */ + ivas_spar_dump_signal_wav( output_frame, NULL, output, num_in_ingest, spar_foa_dec_wav[2], "ivas_pca_dec()" ); +#endif + } + pop_wmops(); + return; +} + +void ivas_spar_dec_set_render_map( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + int16_t nCldfbTs ) +{ + SPAR_DEC_HANDLE hSpar; + + hSpar = st_ivas->hSpar; +#ifdef DEBUGGING + assert( hSpar ); +#endif + + /* adapt subframes */ + hSpar->num_slots = nCldfbTs; + hSpar->slots_rendered = 0; + hSpar->subframes_rendered = 0; + set_s( hSpar->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); + ivas_jbm_dec_get_adapted_subframes( nCldfbTs, hSpar->subframe_nbslots, &hSpar->nb_subframes ); + ivas_jbm_dec_get_md_map( DEFAULT_JBM_CLDFB_TIMESLOTS, nCldfbTs, 1, 0, DEFAULT_JBM_CLDFB_TIMESLOTS, hSpar->render_to_md_map ); + + return; +} /*-------------------------------------------------------------------* * ivas_spar_dec_upmixer() * * IVAS SPAR upmixer *-------------------------------------------------------------------*/ +void ivas_spar_dec_set_render_params( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const int16_t n_cldfb_slots /* i : number of cldfb slots in this frame */ +) +{ + SPAR_DEC_HANDLE hSpar; + int16_t nchan_transport; + int16_t num_bands_out; + + hSpar = st_ivas->hSpar; + /*---------------------------------------------------------------------* + * Gen umx mat + *---------------------------------------------------------------------*/ + nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; + num_bands_out = hSpar->hFbMixer->pFb->filterbank_num_bands; + ivas_spar_dec_gen_umx_mat( hSpar->hMdDec, nchan_transport, num_bands_out, st_ivas->bfi +#ifdef SPAR_TUNING + , + ivas_get_spar_dec_md_num_subframes( st_ivas->sba_order, st_ivas->hDecoderConfig->ivas_total_brate ) +#endif + ); + + ivas_spar_dec_set_render_map( st_ivas, n_cldfb_slots ); + + return; +} + +void ivas_spar_dec_digest_tc( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const int16_t nchan_transport, /* i : number of transport channels */ + const int16_t nCldfbSlots, /* i : number of CLDFB slots */ + const int16_t nSamplesForRendering /* i : number of samples provided */ +) +{ + SPAR_DEC_HANDLE hSpar; + + hSpar = st_ivas->hSpar; + if ( hSpar->hMdDec->td_decorr_flag && !( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + float Pcm_tmp[MAX_SPAR_INTERNAL_CHANNELS][L_FRAME48k]; + float *pPcm_tmp[MAX_SPAR_INTERNAL_CHANNELS]; + float *p_tc[MAX_SPAR_INTERNAL_CHANNELS]; + int16_t nchan_internal, ch; + int16_t nSamplesLeftForTD, default_frame; + /* TD decorrelator */ + default_frame = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ); + nSamplesLeftForTD = nSamplesForRendering; + nchan_internal = ivas_sba_get_nchan_metadata( st_ivas->sba_analysis_order +#ifdef SPAR_TUNING + , + st_ivas->hDecoderConfig->ivas_total_brate +#endif + ); + for ( ch = 0; ch < nchan_internal; ch++ ) + { + pPcm_tmp[ch] = Pcm_tmp[ch]; + p_tc[ch] = st_ivas->hTcBuffer->tc[ch]; + } + + while ( nSamplesLeftForTD ) + { + int16_t nSamplesToDecorr = min( nSamplesLeftForTD, default_frame ); + ivas_td_decorr_process( hSpar->hTdDecorr, p_tc, pPcm_tmp, nSamplesToDecorr ); +#ifdef SPAR_TUNING + if ( hSpar->hTdDecorr->num_apd_outputs >= ( nchan_internal - nchan_transport ) ) + { + for ( ch = 0; ch < nchan_internal - nchan_transport; ch++ ) + { + mvr2r( pPcm_tmp[hSpar->hTdDecorr->num_apd_outputs - 1 - ch], p_tc[nchan_internal - 1 - ch], nSamplesToDecorr ); + } + } + else + { + for ( ch = 0; ch < nchan_internal - nchan_transport; ch++ ) + { + set_zero( p_tc[nchan_internal - 1 - ch], nSamplesToDecorr ); + } + for ( ch = 0; ch < hSpar->hTdDecorr->num_apd_outputs; ch++ ) + { + mvr2r( pPcm_tmp[hSpar->hTdDecorr->num_apd_outputs - 1 - ch], p_tc[nchan_internal - 1 - ch], nSamplesToDecorr ); + } + } +#else + for ( ch = 0; ch < nchan_internal - nchan_transport; ch++ ) + { + mvr2r( pPcm_tmp[hSpar->hTdDecorr->num_apd_outputs - 1 - ch], p_tc[nchan_internal - 1 - ch], nSamplesToDecorr ); + } +#endif + for ( ch = 0; ch < nchan_internal; ch++ ) + { + p_tc[ch] += nSamplesToDecorr; + } + nSamplesLeftForTD -= nSamplesToDecorr; + } + } + + ivas_spar_dec_set_render_params( st_ivas, nCldfbSlots ); + + + return; +} + +void ivas_spar_dec_upmixer( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + float output[][L_FRAME48k], /* i/o: input/output audio channels */ + const int16_t nchan_internal, /* i : number of internal channels */ + const int16_t output_frame /* i : output frame length */ +) +{ + SPAR_DEC_HANDLE hSpar; + int16_t nchan_transport, nchan_out; + int16_t subframe_idx, n, i; + int16_t n_samples_sf; + float *output_f_local[MAX_OUTPUT_CHANNELS]; + float Pcm_tmp[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + float *pPcm_tmp[MAX_OUTPUT_CHANNELS]; + + hSpar = st_ivas->hSpar; + nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; + nchan_out = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; + n_samples_sf = JBM_CLDFB_SLOTS_IN_SUBFRAME * NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); + for ( n = 0; n < MAX_OUTPUT_CHANNELS; n++ ) + { + output_f_local[n] = &output[n][0]; + } + for ( n = 0; n < nchan_internal; n++ ) + { + st_ivas->hTcBuffer->tc[n] = output[n]; + } + + /*---------------------------------------------------------------------* + * TD decorrelation + *---------------------------------------------------------------------*/ + for ( i = 0; i < nchan_internal; i++ ) + { + pPcm_tmp[i] = Pcm_tmp[i]; + } + if ( hSpar->hMdDec->td_decorr_flag ) + { + ivas_td_decorr_process( hSpar->hTdDecorr, st_ivas->hTcBuffer->tc, pPcm_tmp, output_frame ); +#ifdef SPAR_TUNING + if ( hSpar->hTdDecorr->num_apd_outputs >= ( nchan_internal - nchan_transport ) ) + { + for ( i = 0; i < nchan_internal - nchan_transport; i++ ) + { + mvr2r( pPcm_tmp[hSpar->hTdDecorr->num_apd_outputs - 1 - i], st_ivas->hTcBuffer->tc[nchan_internal - 1 - i], output_frame ); + } + } + else + { + for ( i = 0; i < nchan_internal - nchan_transport; i++ ) + { + set_zero( st_ivas->hTcBuffer->tc[nchan_internal - 1 - i], output_frame ); + } + for ( i = 0; i < hSpar->hTdDecorr->num_apd_outputs; i++ ) + { + mvr2r( pPcm_tmp[hSpar->hTdDecorr->num_apd_outputs - 1 - i], st_ivas->hTcBuffer->tc[nchan_internal - 1 - i], output_frame ); + } + } +#else + for ( i = 0; i < nchan_internal - nchan_transport; i++ ) + { + mvr2r( pPcm_tmp[hSpar->hTdDecorr->num_apd_outputs - 1 - i], st_ivas->hTcBuffer->tc[nchan_internal - 1 - i], output_frame ); + } +#endif + } + + + ivas_spar_dec_set_render_params( st_ivas, DEFAULT_JBM_CLDFB_TIMESLOTS ); + + if ( st_ivas->hDirAC != 0 ) + { + ivas_dirac_dec_set_md_map( st_ivas, DEFAULT_JBM_CLDFB_TIMESLOTS ); + } + + for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ ) + { + ivas_spar_dec_upmixer_sf( st_ivas, output_f_local, nchan_internal ); + for ( n = 0; n < nchan_out; n++ ) + { + output_f_local[n] += n_samples_sf; + } + } + for ( n = 0; n < nchan_internal; n++ ) + { + st_ivas->hTcBuffer->tc[n] = NULL; + } + if ( st_ivas->hDirAC != 0 ) + { + if ( st_ivas->hDirAC->hConfig->dec_param_estim == 1 ) + { + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_CLDFB_TIMESLOTS ) % st_ivas->hDirAC->dirac_md_buffer_length; + } + else + { + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % st_ivas->hDirAC->dirac_md_buffer_length; + } + } + return; +} +#endif + + +#ifdef JBM_TSM_ON_TCS +/*-------------------------------------------------------------------* + * ivas_spar_dec_upmixer_sf() + * + * IVAS SPAR upmixer + *-------------------------------------------------------------------*/ +void ivas_spar_dec_upmixer_sf( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + float *output[], /* o : output audio channels */ + const int16_t nchan_internal /* i : number of internal channels */ +) +#else void ivas_spar_dec_upmixer( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ float output[][L_FRAME48k], /* i/o: input/output audio channels */ const int16_t nchan_internal, /* i : number of internal channels */ const int16_t output_frame /* i : output frame length */ ) +#endif { int16_t cldfb_band, num_cldfb_bands, numch_in, numch_out; float *cldfb_in_ts_re[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX]; float *cldfb_in_ts_im[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX]; int16_t i, b, ts, out_ch, in_ch; int16_t num_spar_bands, spar_band, nchan_transport; - int16_t num_in_ingest, num_bands_out, split_band; + int16_t num_in_ingest, split_band; +#ifdef JBM_TSM_ON_TCS + int16_t slot_size, slot_idx_start; + float *p_tc[MAX_OUTPUT_CHANNELS]; + int16_t md_idx; +#endif float Pcm_tmp[MAX_OUTPUT_CHANNELS][L_FRAME48k]; int16_t numch_out_dirac; +#ifndef JBM_TSM_ON_TCS float *pPcm_tmp[MAX_OUTPUT_CHANNELS]; + int16_t num_bands_out; +#endif float mixer_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS]; int16_t b_skip_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; DECODER_CONFIG_HANDLE hDecoderConfig; SPAR_DEC_HANDLE hSpar; #ifdef SPAR_TUNING - int16_t num_md_sub_frames, md_sf_idx; + int16_t num_md_sub_frames; +#ifndef JBM_TSM_ON_TCS + int16_t md_sf_idx; +#endif #endif +#ifdef JBM_TSM_ON_TCS + push_wmops( "ivas_spar_dec_upmixer_sf" ); +#else push_wmops( "ivas_spar_dec_upmixer" ); +#endif hSpar = st_ivas->hSpar; hDecoderConfig = st_ivas->hDecoderConfig; +#ifndef JBM_TSM_ON_TCS num_bands_out = hSpar->hFbMixer->pFb->filterbank_num_bands; +#endif nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; num_cldfb_bands = hSpar->hFbMixer->pFb->fb_bin_to_band.num_cldfb_bands; @@ -1118,6 +1482,15 @@ void ivas_spar_dec_upmixer( num_md_sub_frames = ivas_get_spar_dec_md_num_subframes( st_ivas->sba_order, hDecoderConfig->ivas_total_brate ); #endif +#ifdef JBM_TSM_ON_TCS + slot_size = NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); + slot_idx_start = hSpar->slots_rendered; + for ( i = 0; i < nchan_internal; i++ ) + { + p_tc[i] = st_ivas->hTcBuffer->tc[i] + slot_idx_start * slot_size; + } +#endif + #ifdef DEBUG_SPAR_BYPASS_EVS_CODEC /* by-pass core-coder */ /*write the core coder output to a file for debugging*/ @@ -1155,17 +1528,19 @@ void ivas_spar_dec_upmixer( } #endif +#ifndef JBM_TSM_ON_TCS /*---------------------------------------------------------------------* * AGC *---------------------------------------------------------------------*/ ivas_agc_dec_process( hSpar->hAgcDec, output, output, nchan_transport, output_frame ); + #ifdef DEBUG_SBA_AUDIO_DUMP /* Dump audio signal after ivas_agc_dec_process */ ivas_spar_dump_signal_wav( output_frame, NULL, output, st_ivas->nchan_transport, spar_foa_dec_wav[1], "ivas_agc_dec_process()" ); #endif - +#endif /*---------------------------------------------------------------------* * TD Decorr and pcm ingest *---------------------------------------------------------------------*/ @@ -1179,11 +1554,12 @@ void ivas_spar_dec_upmixer( num_in_ingest = nchan_transport; } +#ifndef JBM_TSM_ON_TCS for ( i = 0; i < nchan_internal; i++ ) { pPcm_tmp[i] = Pcm_tmp[i]; } - +#endif /*---------------------------------------------------------------------* * PCA decoder *---------------------------------------------------------------------*/ @@ -1191,6 +1567,7 @@ void ivas_spar_dec_upmixer( hSpar->pca_ingest_channels = num_in_ingest; #endif +#ifndef JBM_TSM_ON_TCS /* will already happen in the TC decoding */ if ( hSpar->hPCA != NULL ) { ivas_pca_dec( hSpar->hPCA, output_frame, num_in_ingest, hDecoderConfig->ivas_total_brate, hDecoderConfig->last_ivas_total_brate, st_ivas->bfi, output ); @@ -1199,8 +1576,9 @@ void ivas_spar_dec_upmixer( ivas_spar_dump_signal_wav( output_frame, NULL, output, num_in_ingest, spar_foa_dec_wav[2], "ivas_pca_dec()" ); #endif } +#endif - +#ifndef JBM_TSM_ON_TCS /*---------------------------------------------------------------------* * TD decorrelation *---------------------------------------------------------------------*/ @@ -1235,7 +1613,7 @@ void ivas_spar_dec_upmixer( } #endif } - +#endif hSpar->hFbMixer->fb_cfg->num_in_chans = num_in_ingest; @@ -1268,6 +1646,7 @@ void ivas_spar_dec_upmixer( } } +#ifndef JBM_TSM_ON_TCS /*---------------------------------------------------------------------* * Gen umx mat *---------------------------------------------------------------------*/ @@ -1278,7 +1657,7 @@ void ivas_spar_dec_upmixer( num_md_sub_frames #endif ); - +#endif /*---------------------------------------------------------------------* * CLDFB Processing and Synthesis @@ -1297,15 +1676,34 @@ void ivas_spar_dec_upmixer( numch_out_dirac = hDecoderConfig->nchan_out; +#ifdef DEBUG_SBA_AUDIO_DUMP + /* Dump audio signal after ivas_agc_dec_process */ +#ifdef JBM_TSM_ON_TCS + ivas_spar_dump_signal_wav( output_frame, p_tc, NULL, numch_in, spar_foa_dec_wav[4], "ivas_spar_upmixer()" ); +#else + ivas_spar_dump_signal_wav( output_frame, NULL, output, numch_in, spar_foa_dec_wav[4], "ivas_spar_upmixer()" ); +#endif +#endif + +#ifndef JBM_TSM_ON_TCS for ( int16_t i_sf = 0; i_sf < MAX_PARAM_SPATIAL_SUBFRAMES; i_sf++ ) { +#endif /* CLDFB analysis of incoming frame */ for ( in_ch = 0; in_ch < numch_in; in_ch++ ) { - for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) +#ifdef JBM_TSM_ON_TCS + for ( ts = 0; ts < hSpar->subframe_nbslots[hSpar->subframes_rendered]; ts++ ) +#else + for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) +#endif { cldfbAnalysis_ts( - &output[in_ch][( ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES ) * num_cldfb_bands], +#ifdef JBM_TSM_ON_TCS + &p_tc[in_ch][ts * num_cldfb_bands], +#else + &output[in_ch][( ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES ) * num_cldfb_bands], +#endif cldfb_in_ts_re[in_ch][ts], cldfb_in_ts_im[in_ch][ts], num_cldfb_bands, @@ -1318,18 +1716,26 @@ void ivas_spar_dec_upmixer( #ifdef LBR_ADAP_SMOOTHING_OPT ivas_spar_calc_smooth_facs( cldfb_in_ts_re[0], cldfb_in_ts_im[0], num_spar_bands, &hSpar->hFbMixer->pFb->fb_bin_to_band, hSpar->hMdDec->smooth_fac, hSpar->hMdDec->smooth_buf ); #else - for ( in_ch = 0; in_ch < numch_in; in_ch++ ) - { - ivas_spar_calc_smooth_facs( cldfb_in_ts_re[in_ch], cldfb_in_ts_im[in_ch], num_spar_bands, &hSpar->hFbMixer->pFb->fb_bin_to_band, hSpar->hMdDec->smooth_fac[in_ch], hSpar->hMdDec->smooth_buf[in_ch] ); - } + for ( in_ch = 0; in_ch < numch_in; in_ch++ ) + { + ivas_spar_calc_smooth_facs( cldfb_in_ts_re[in_ch], cldfb_in_ts_im[in_ch], num_spar_bands, &hSpar->hFbMixer->pFb->fb_bin_to_band, hSpar->hMdDec->smooth_fac[in_ch], hSpar->hMdDec->smooth_buf[in_ch] ); + } #endif } - for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) +#ifdef JBM_TSM_ON_TCS + for ( ts = 0; ts < hSpar->subframe_nbslots[hSpar->subframes_rendered]; ts++ ) +#else + for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) +#endif { - /* determine SPAR parameters for this time slots */ - ivas_spar_get_parameters( hSpar, hDecoderConfig, ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES, numch_out, numch_in, num_spar_bands, mixer_mat ); - +#ifdef JBM_TSM_ON_TCS + md_idx = hSpar->render_to_md_map[ts + slot_idx_start]; + ivas_spar_get_parameters( hSpar, hDecoderConfig, md_idx, numch_out, numch_in, num_spar_bands, mixer_mat ); +#else + /* determine SPAR parameters for this time slots */ + ivas_spar_get_parameters( hSpar, hDecoderConfig, ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES, numch_out, numch_in, num_spar_bands, mixer_mat ); +#endif if ( ( hDecoderConfig->ivas_total_brate < IVAS_24k4 ) && ( ( hDecoderConfig->output_config == AUDIO_CONFIG_HOA2 ) || ( hDecoderConfig->output_config == AUDIO_CONFIG_HOA3 ) ) ) { for ( spar_band = 0; spar_band < num_spar_bands; spar_band++ ) @@ -1341,7 +1747,7 @@ void ivas_spar_dec_upmixer( #ifdef LBR_ADAP_SMOOTHING_OPT mixer_mat[out_ch][in_ch][spar_band] = ( 1 - hSpar->hMdDec->smooth_fac[spar_band] ) * mixer_mat[out_ch][in_ch][spar_band] + hSpar->hMdDec->smooth_fac[spar_band] * hSpar->hMdDec->mixer_mat_prev2[out_ch][in_ch][spar_band]; #else - mixer_mat[out_ch][in_ch][spar_band] = ( 1 - hSpar->hMdDec->smooth_fac[in_ch][spar_band] ) * mixer_mat[out_ch][in_ch][spar_band] + hSpar->hMdDec->smooth_fac[in_ch][spar_band] * hSpar->hMdDec->mixer_mat_prev2[out_ch][in_ch][spar_band]; + mixer_mat[out_ch][in_ch][spar_band] = ( 1 - hSpar->hMdDec->smooth_fac[in_ch][spar_band] ) * mixer_mat[out_ch][in_ch][spar_band] + hSpar->hMdDec->smooth_fac[in_ch][spar_band] * hSpar->hMdDec->mixer_mat_prev2[out_ch][in_ch][spar_band]; #endif hSpar->hMdDec->mixer_mat_prev2[out_ch][in_ch][spar_band] = mixer_mat[out_ch][in_ch][spar_band]; } @@ -1387,28 +1793,28 @@ void ivas_spar_dec_upmixer( } #else - if ( b_skip_mat[out_ch][in_ch] ) - { - continue; - } - else if ( cldfb_band < CLDFB_PAR_WEIGHT_START_BAND ) /* tuning parameter, depends on how much SPAR Filters overlap for the CLDFB bands */ - { - spar_band = bin2band->p_cldfb_map_to_spar_band[cldfb_band]; - cldfb_par = mixer_mat[out_ch][in_ch][spar_band]; - } - else + if ( b_skip_mat[out_ch][in_ch] ) + { + continue; + } + else if ( cldfb_band < CLDFB_PAR_WEIGHT_START_BAND ) /* tuning parameter, depends on how much SPAR Filters overlap for the CLDFB bands */ + { + spar_band = bin2band->p_cldfb_map_to_spar_band[cldfb_band]; + cldfb_par = mixer_mat[out_ch][in_ch][spar_band]; + } + else + { + cldfb_par = 0.0f; + for ( spar_band = bin2band->p_spar_start_bands[cldfb_band]; spar_band < num_spar_bands; spar_band++ ) { - cldfb_par = 0.0f; - for ( spar_band = bin2band->p_spar_start_bands[cldfb_band]; spar_band < num_spar_bands; spar_band++ ) - { - /* accumulate contributions from all SPAR bands */ - cldfb_par += mixer_mat[out_ch][in_ch][spar_band] * bin2band->pp_cldfb_weights_per_spar_band[cldfb_band][spar_band]; - } + /* accumulate contributions from all SPAR bands */ + cldfb_par += mixer_mat[out_ch][in_ch][spar_band] * bin2band->pp_cldfb_weights_per_spar_band[cldfb_band][spar_band]; } - - out_re[out_ch] += cldfb_in_ts_re[in_ch][ts][cldfb_band] * cldfb_par; - out_im[out_ch] += cldfb_in_ts_im[in_ch][ts][cldfb_band] * cldfb_par; } + + out_re[out_ch] += cldfb_in_ts_re[in_ch][ts][cldfb_band] * cldfb_par; + out_im[out_ch] += cldfb_in_ts_im[in_ch][ts][cldfb_band] * cldfb_par; + } #endif } @@ -1419,11 +1825,46 @@ void ivas_spar_dec_upmixer( cldfb_in_ts_im[out_ch][ts][cldfb_band] = out_im[out_ch]; } } +#ifdef JBM_TSM_ON_TCS + if ( ( ( slot_idx_start + ts + 1 ) == hSpar->num_slots ) || ( ( md_idx / JBM_CLDFB_SLOTS_IN_SUBFRAME ) != ( hSpar->render_to_md_map[ts + slot_idx_start + 1] / JBM_CLDFB_SLOTS_IN_SUBFRAME ) ) ) + { + /* we have crossed an unadapted parameter sf border, update previous mixing matrices */ + int16_t md_sf = md_idx / JBM_CLDFB_SLOTS_IN_SUBFRAME; + split_band = SPAR_DIRAC_SPLIT_START_BAND; +#ifdef SPAR_TUNING + md_sf = ( num_md_sub_frames == MAX_PARAM_SPATIAL_SUBFRAMES ) ? md_sf : 0; +#endif + if ( split_band < IVAS_MAX_NUM_BANDS ) + { + mvr2r( hSpar->hMdDec->mixer_mat_prev[1][0][0], hSpar->hMdDec->mixer_mat_prev[0][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[2][0][0], hSpar->hMdDec->mixer_mat_prev[1][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[3][0][0], hSpar->hMdDec->mixer_mat_prev[2][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[4][0][0], hSpar->hMdDec->mixer_mat_prev[3][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + + for ( out_ch = 0; out_ch < numch_out; out_ch++ ) + { + for ( in_ch = 0; in_ch < numch_in; in_ch++ ) + { + for ( b = 0; b < num_spar_bands; b++ ) + { + hSpar->hMdDec->mixer_mat_prev[4][out_ch][in_ch][b] = hSpar->hMdDec->mixer_mat[out_ch][in_ch][b + md_sf * IVAS_MAX_NUM_BANDS]; + } + } + } + hSpar->i_subframe++; + hSpar->i_subframe = min( hSpar->i_subframe, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } +#endif } if ( hDecoderConfig->output_config != AUDIO_CONFIG_FOA && hDecoderConfig->output_config != AUDIO_CONFIG_STEREO && hDecoderConfig->output_config != AUDIO_CONFIG_MONO ) { - ivas_dirac_dec( st_ivas, output, nchan_internal, cldfb_in_ts_re, cldfb_in_ts_im, i_sf ); +#ifdef JBM_TSM_ON_TCS + ivas_dirac_dec_render_sf( st_ivas, output, nchan_internal, cldfb_in_ts_re, cldfb_in_ts_im ); +#else + ivas_dirac_dec( st_ivas, output, nchan_internal, cldfb_in_ts_re, cldfb_in_ts_im, i_sf ); +#endif } if ( st_ivas->hDirAC != NULL ) @@ -1437,8 +1878,11 @@ void ivas_spar_dec_upmixer( { if ( ( st_ivas->hOutSetup.num_lfe > 0 ) && ( st_ivas->hOutSetup.index_lfe[idx_lfe] == ch ) ) { - set_zero( &( output[ch][i_sf * MAX_PARAM_SPATIAL_SUBFRAMES * num_cldfb_bands] ), MAX_PARAM_SPATIAL_SUBFRAMES * num_cldfb_bands ); - +#ifdef JBM_TSM_ON_TCS + set_zero( output[ch], hSpar->subframe_nbslots[hSpar->subframes_rendered] * num_cldfb_bands ); +#else + set_zero( &( output[ch][i_sf * MAX_PARAM_SPATIAL_SUBFRAMES * num_cldfb_bands] ), MAX_PARAM_SPATIAL_SUBFRAMES * num_cldfb_bands ); +#endif if ( idx_lfe < ( st_ivas->hDirAC->hOutSetup.num_lfe - 1 ) ) { idx_lfe++; @@ -1448,12 +1892,20 @@ void ivas_spar_dec_upmixer( { if ( hDecoderConfig->output_config == AUDIO_CONFIG_FOA || !( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL || st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL_ROOM ) ) { - for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) +#ifdef JBM_TSM_ON_TCS + for ( ts = 0; ts < hSpar->subframe_nbslots[hSpar->subframes_rendered]; ts++ ) +#else + for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) +#endif { cldfbSynthesis( &cldfb_in_ts_re[idx_in][ts], &cldfb_in_ts_im[idx_in][ts], - &output[ch][( ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES ) * num_cldfb_bands], +#ifdef JBM_TSM_ON_TCS + &output[ch][ts * num_cldfb_bands], +#else + &output[ch][( ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES ) * num_cldfb_bands], +#endif num_cldfb_bands, st_ivas->cldfbSynDec[idx_in] ); } @@ -1470,12 +1922,20 @@ void ivas_spar_dec_upmixer( /* CLDFB to time synthesis (overwrite mixer output) */ for ( out_ch = 0; out_ch < numch_out_dirac; out_ch++ ) { - for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) +#ifdef JBM_TSM_ON_TCS + for ( ts = 0; ts < hSpar->subframe_nbslots[hSpar->subframes_rendered]; ts++ ) +#else + for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) +#endif { cldfbSynthesis( &cldfb_in_ts_re[out_ch][ts], &cldfb_in_ts_im[out_ch][ts], - &output[out_ch][( ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES ) * num_cldfb_bands], +#ifdef JBM_TSM_ON_TCS + &output[out_ch][ts * num_cldfb_bands], +#else + &output[out_ch][( ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES ) * num_cldfb_bands], +#endif num_cldfb_bands, st_ivas->cldfbSynDec[out_ch] ); } @@ -1488,10 +1948,12 @@ void ivas_spar_dec_upmixer( /* Dump audio signal after cldfbSynthesis */ ivas_spar_dump_signal_wav( output_frame, NULL, output, hSpar->numOutChannels, spar_foa_dec_wav[3], "cldfbSynthesis()" ); #endif + + +#ifndef JBM_TSM_ON_TCS #ifdef SPAR_TUNING md_sf_idx = ( num_md_sub_frames == MAX_PARAM_SPATIAL_SUBFRAMES ) ? i_sf : 0; #endif - split_band = SPAR_DIRAC_SPLIT_START_BAND; if ( split_band < IVAS_MAX_NUM_BANDS ) { @@ -1517,8 +1979,14 @@ void ivas_spar_dec_upmixer( } } } +#endif +#ifndef JBM_TSM_ON_TCS } - +#endif +#ifdef JBM_TSM_ON_TCS + hSpar->slots_rendered += hSpar->subframe_nbslots[hSpar->subframes_rendered]; + hSpar->subframes_rendered++; +#endif pop_wmops(); return; diff --git a/lib_dec/ivas_spar_md_dec.c b/lib_dec/ivas_spar_md_dec.c index 69f3754e5cafcc691af023f1408fbfc6ff0632b7..6b9f1457d4a3cb3aeba1c9fd9ae99a8bfcd17472 100755 --- a/lib_dec/ivas_spar_md_dec.c +++ b/lib_dec/ivas_spar_md_dec.c @@ -3165,7 +3165,11 @@ void ivas_spar_to_dirac( qmf_band_start = band_grouping[band]; qmf_band_end = band_grouping[band + 1]; +#ifdef JBM_TSM_ON_TCS + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) +#else for ( block = 0; block < hDirAC->nb_subframes; block++ ) +#endif { int16_t ts_start, ts_end, ts; @@ -3187,6 +3191,7 @@ void ivas_spar_to_dirac( hDirAC->energy_ratio1[block][b] = en_ratio; tmp_write_idx_band = tmp_write_idx_param_band; + if ( hDirAC->hConfig->dec_param_estim == FALSE ) { hDirAC->elevation[tmp_write_idx_band][b] = ele_dith; diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index 3a0259c1c3bad85a6c0344822b88426f409d77b7..cc7e31f9a6f0b989faa4024bcae16733674d0f6a 100755 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -435,7 +435,11 @@ typedef struct param_ism_rendering float *proto_matrix; float *interpolator; float mixing_matrix_lin_old[CLDFB_NO_CHANNELS_MAX][PARAM_ISM_MAX_CHAN * PARAM_ISM_MAX_DMX]; - +#ifdef JBM_TSM_ON_TCS + float mixing_matrix_lin[CLDFB_NO_CHANNELS_MAX][PARAM_ISM_MAX_CHAN * PARAM_ISM_MAX_DMX]; + float *Cldfb_RealBuffer_tc; + float *Cldfb_ImagBuffer_tc; +#endif } PARAM_ISM_RENDERING_DATA, *PARAM_ISM_RENDERING_HANDLE; @@ -571,6 +575,10 @@ typedef struct dirac_output_synthesis_cov_state_structure float *cy_old[CLDFB_NO_CHANNELS_MAX]; float *mixing_matrix_old[CLDFB_NO_CHANNELS_MAX]; float *mixing_matrix_res_old[CLDFB_NO_CHANNELS_MAX]; +#ifdef JBM_TSM_ON_TCS + float *mixing_matrix[CLDFB_NO_CHANNELS_MAX]; + float *mixing_matrix_res[CLDFB_NO_CHANNELS_MAX]; +#endif } DIRAC_OUTPUT_SYNTHESIS_COV_STATE; @@ -611,9 +619,15 @@ typedef struct /* Diffuse sound directional distribution data structure */ typedef struct ivas_diffuse_distribution_data_structure { +#ifdef JBM_TSM_ON_TCS + float diffuseRatioX[CLDFB_NO_CHANNELS_MAX]; + float diffuseRatioY[CLDFB_NO_CHANNELS_MAX]; + float diffuseRatioZ[CLDFB_NO_CHANNELS_MAX]; +#else float diffuseRatioX[MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; float diffuseRatioY[MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; float diffuseRatioZ[MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; +#endif } DIFFUSE_DISTRIBUTION_DATA, *DIFFUSE_DISTRIBUTION_HANDLE; @@ -625,7 +639,15 @@ typedef struct ivas_dirac_dec_data_structure IVAS_OUTPUT_SETUP hOutSetup; int16_t slot_size; +#ifdef JBM_TSM_ON_TCS + int16_t subframe_nbslots[MAX_JBM_SUBFRAMES_5MS]; + int16_t subframes_rendered; + int16_t slots_rendered; + int16_t num_slots; + int16_t render_to_md_map[MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME]; +#else int16_t subframe_nbslots; +#endif int16_t nb_subframes; int16_t num_freq_bands; @@ -736,7 +758,17 @@ typedef struct ivas_param_mc_dec_data_structure { int16_t slot_size; +#ifdef JBM_TSM_ON_TCS + float *Cldfb_RealBuffer_tc; + float *Cldfb_ImagBuffer_tc; + int16_t subframe_nbslots[MAX_JBM_SUBFRAMES_5MS]; + int16_t nb_subframes; + int16_t subframes_rendered; + int16_t slots_rendered; + int16_t num_slots; +#else int16_t subframe_nbslots; +#endif int16_t num_freq_bands; int16_t num_param_bands_synth; @@ -892,6 +924,14 @@ typedef struct ivas_spar_dec_lib_t int16_t numOutChannels; int16_t pca_ingest_channels; #endif +#ifdef JBM_TSM_ON_TCS + int16_t subframe_nbslots[MAX_JBM_SUBFRAMES_5MS]; + int16_t render_to_md_map[MAX_JBM_CLDFB_TIMESLOTS]; + int16_t nb_subframes; + int16_t subframes_rendered; + int16_t slots_rendered; + int16_t num_slots; +#endif } SPAR_DEC_DATA, *SPAR_DEC_HANDLE; @@ -1061,7 +1101,12 @@ typedef struct vbap_data_structure typedef struct renderer_struct { float prev_gains[MAX_CICP_CHANNELS - 1][MAX_OUTPUT_CHANNELS]; +#ifdef JBM_TSM_ON_TCS + float *interpolator; + float gains[MAX_CICP_CHANNELS - 1][MAX_OUTPUT_CHANNELS]; +#else float interpolator[L_FRAME48k]; +#endif } ISM_RENDERER_DATA, *ISM_RENDERER_HANDLE; @@ -1187,9 +1232,35 @@ typedef struct decoder_config_structure #ifdef DEBUGGING int16_t force_rend; /* forced TD/CLDFB binaural renderer (for ISM and MC) */ #endif +#ifdef JBM_TSM_ON_TCS + int16_t voip_active; +#endif } DECODER_CONFIG, *DECODER_CONFIG_HANDLE; + +#ifdef JBM_TSM_ON_TCS +typedef struct decoder_tc_buffer_structure +{ + float *tc_buffer; /* the buffer itself */ + float *tc[MAX_TRANSPORT_CHANNELS]; /* pointers into the buffer to the beginning of each tc */ + TC_BUFFER_MODE tc_buffer_mode; /* mode of the buffer (no buffering, render buffering, out buffering) */ + int16_t nchan_transport_jbm; /* number of TCs after TC decoding */ + int16_t nchan_transport_internal; /* total number of TC buffer channels, can include e.g. TD decorr data */ + int16_t nchan_buffer_full; /* number of channels to be fully buffered */ + int16_t n_samples_available; /* samples still available for rendering in the current frame */ + int16_t n_samples_buffered; /* full number of samples in the buffer (including spill to next frame) */ + int16_t n_samples_rendered; /* samples already rendered in the current frame */ + int16_t n_samples_granularity; /* render granularity */ + int16_t n_samples_flushed; + int16_t subframe_nbslots[MAX_JBM_SUBFRAMES_5MS]; + int16_t nb_subframes; + int16_t subframes_rendered; + int16_t slots_rendered; + int16_t num_slots; + int16_t n_samples_discard; /* number of samples to discard from the beginning of the output */ +} DECODER_TC_BUFFER, *DECODER_TC_BUFFER_HANDLE; +#endif /*----------------------------------------------------------------------------------* * * Main IVAS decoder structure @@ -1286,6 +1357,10 @@ typedef struct Decoder_Struct int16_t ism_extmeta_active; /* Extended metadata active in decoder */ int16_t ism_extmeta_cnt; /* Change frame counter for extended metadata */ + +#ifdef JBM_TSM_ON_TCS + DECODER_TC_BUFFER_HANDLE hTcBuffer; +#endif } Decoder_Struct; /* clang-format on */ diff --git a/lib_dec/jbm_jb4sb.h b/lib_dec/jbm_jb4sb.h index 54b873b006b1c9532794cae661a7f3c2aea031ad..7954358595a32c3dceff516f4a04a87c73b09648 100644 --- a/lib_dec/jbm_jb4sb.h +++ b/lib_dec/jbm_jb4sb.h @@ -78,6 +78,14 @@ struct JB4_DATAUNIT int16_t nextCoderType; }; +#ifdef JBM_TSM_ON_TCS +typedef enum +{ + JBM_RENDERER_NONE, + JBM_RENDERER_IVAS, +} JBM_RENDERER_TYPE; +#endif + typedef struct JB4_DATAUNIT *JB4_DATAUNIT_HANDLE; diff --git a/lib_dec/jbm_pcmdsp_apa.c b/lib_dec/jbm_pcmdsp_apa.c index c816a9d9c8b4fadbea3da7e1ccb7061dbc4cd677..713c2327a0e0ed0d1a9026408a4b8e25989262d7 100644 --- a/lib_dec/jbm_pcmdsp_apa.c +++ b/lib_dec/jbm_pcmdsp_apa.c @@ -66,7 +66,12 @@ struct apa_state_t { /* output buffer */ +#ifdef JBM_TSM_ON_TCS + bool evs_compat_mode; + float *buf_out; +#else int16_t *buf_out; +#endif uint16_t buf_out_capacity; uint16_t l_buf_out; @@ -86,6 +91,14 @@ struct apa_state_t /* total number of processed input samples since apa_reset() */ uint32_t l_in_total; +#ifdef JBM_TSM_ON_TCS + /* time resolution in samples of the IVAS renderer*/ + uint16_t l_ts; + + /* samples already available in the renderer buffer */ + uint16_t l_r_buf; +#endif + /* sum of inserted/removed samples since last apa_set_scale() */ int32_t diffSinceSetScale; /* number of input frames since last apa_set_scale() */ @@ -123,6 +136,17 @@ static float apa_corrEnergy2dB( float energy, uint16_t corr_len ); static float apa_getQualityIncreaseForLowEnergy( float energydB ); +#ifdef JBM_TSM_ON_TCS +static bool logarithmic_search( const apa_state_t *ps, const float *signal, int16_t s_start, uint16_t inlen, uint16_t offset, uint16_t fixed_pos, uint16_t corr_len, uint16_t wss, uint16_t css, int16_t *synchpos ); + +static bool find_synch( apa_state_t *ps, const float *in, uint16_t l_in, int16_t s_start, uint16_t s_len, int16_t fixed_pos, uint16_t corr_len, uint16_t offset, float *energy, float *quality, int16_t *synch_pos ); + +static bool copy_frm( apa_state_t *ps, const float frm_in[], float frm_out[], uint16_t *l_frm_out ); + +static bool shrink_frm( apa_state_t *ps, const float frm_in[], uint16_t maxScaling, float frm_out[], uint16_t *l_frm_out ); + +static bool extend_frm( apa_state_t *ps, const float frm_in[], float frm_out[], uint16_t *l_frm_out ); +#else static bool logarithmic_search( const apa_state_t *ps, const int16_t *signal, int16_t s_start, uint16_t inlen, uint16_t offset, uint16_t fixed_pos, uint16_t corr_len, uint16_t wss, uint16_t css, int16_t *synchpos ); static bool find_synch( apa_state_t *ps, const int16_t *in, uint16_t l_in, int16_t s_start, uint16_t s_len, int16_t fixed_pos, uint16_t corr_len, uint16_t offset, float *energy, float *quality, int16_t *synch_pos ); @@ -132,7 +156,7 @@ static bool copy_frm( apa_state_t *ps, const int16_t frm_in[], int16_t frm_out[] static bool shrink_frm( apa_state_t *ps, const int16_t frm_in[], uint16_t maxScaling, int16_t frm_out[], uint16_t *l_frm_out ); static bool extend_frm( apa_state_t *ps, const int16_t frm_in[], int16_t frm_out[], uint16_t *l_frm_out ); - +#endif /*---------------------------------------------------------------------* * Public functions @@ -164,6 +188,10 @@ ivas_error apa_init( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) ); } +#ifdef JBM_TSM_ON_TCS + ps->evs_compat_mode = false; +#endif + apa_reset( ps ); *pps = ps; @@ -196,9 +224,58 @@ void apa_reset( ps->bad_frame_count = 0; ps->good_frame_count = 0; +#ifdef JBM_TSM_ON_TCS + ps->l_ts = 1; + ps->l_r_buf = 0; +#endif return; } +#ifdef JBM_TSM_ON_TCS +uint8_t apa_reconfigure( + apa_state_t *ps, + uint16_t num_channels, + uint16_t l_ts ) +{ + + /* realloc buffer */ + free( ps->buf_out ); + ps->num_channels = (uint16_t) num_channels; + ps->buf_out_capacity = (uint16_t) ( APA_BUF_PER_CHANNEL * num_channels ); + ps->buf_out = (float *) malloc( sizeof( float ) * ps->buf_out_capacity ); + if ( !ps->buf_out ) + { + return 2; + } + ps->l_buf_out = 0; + ps->l_in_total = 0; + ps->l_ts = ps->num_channels * l_ts; + + /* set everything else dependent on the number of channels */ + /* set segment size */ + /* in the order of a pitch, set to 160 samples at 16 kHz */ + /* used for windowing and as the correlation length, i.e., */ + /* the size of the template segment. */ + ps->l_seg = ( ps->rate / 100 ) * ps->num_channels; + + /* set frame size */ + /* set to 320 samples at 16 kHz */ + ps->l_frm = ( ps->rate / FRAMES_PER_SEC ) * ps->num_channels; + + /* set minimum pitch */ + /* set to 40 samples at 16 kHz */ + /* (defines min change in number of samples, i.e., abs(l_in-l_out) >= p_min) */ + ps->p_min = ( ps->rate / 400 ) * ps->num_channels; + + /* set search length */ + /* must cover one pitch, set to 200 samples at 16 kHz */ + /* (the resulting maximum pitch is then p_min+l_search = 240 samples at 16 kHz) */ + ps->l_search = ( ps->rate / 80 ) * ps->num_channels; + + return 0; +} + +#endif /* Sets the audio configuration. */ bool apa_set_rate( @@ -302,6 +379,52 @@ bool apa_set_scale( return 0; } +#ifdef JBM_TSM_ON_TCS +bool apa_set_renderer_granularity( + apa_state_t *ps, + uint16_t l_ts ) +{ + /* make sure pointer is valid */ + if ( ps == NULL ) + { + return 1; + } + + + /* copy to state struct */ + ps->l_ts = l_ts * ps->num_channels; + return 0; +} + +bool apa_set_renderer_residual_samples( + apa_state_t *ps, + uint16_t l_r_buf ) +{ + /* make sure pointer is valid */ + if ( ps == NULL ) + { + return 1; + } + + + /* copy to state struct */ + ps->l_r_buf = l_r_buf * ps->num_channels; + return 0; +} + +bool apa_set_evs_compat_mode( apa_state_t *ps, bool mode ) +{ + /* make sure pointer is valid */ + if ( ps == NULL ) + { + return 1; + } + + ps->evs_compat_mode = mode; + + return 0; +} +#endif /* ******************************************************************************** @@ -454,16 +577,28 @@ bool apa_exit( ******************************************************************************** */ uint8_t apa_exec( - apa_state_t *ps, /* i/o: state struct */ - const int16_t a_in[], /* i : input samples */ - uint16_t l_in, /* i : number of input samples */ - uint16_t maxScaling, /* i : allowed number of inserted/removed samples */ - int16_t a_out[], /* o : output samples */ - uint16_t *l_out /* o : number of output samples */ + apa_state_t *ps, /* i/o: state struct */ +#ifdef JBM_TSM_ON_TCS + const float a_in[], /* i : input samples */ +#else + const int16_t a_in[], /* i : input samples */ +#endif + uint16_t l_in, /* i : number of input samples */ + uint16_t maxScaling, /* i : allowed number of inserted/removed samples */ +#ifdef JBM_TSM_ON_TCS + float a_out[], /* o : output samples */ +#else + int16_t a_out[], /* o : output samples */ +#endif + uint16_t *l_out /* o : number of output samples */ ) { uint16_t i; +#ifdef JBM_TSM_ON_TCS + float frm_in[APA_BUF]; /* TODO(mcjbm): this buffer could be smaller - always allocates space for 16 channels */ +#else int16_t frm_in[APA_BUF]; /* TODO(mcjbm): this buffer could be smaller - always allocates space for 16 channels */ +#endif uint16_t l_frm_out; int16_t l_rem; int32_t dl_scaled, dl_copied, l_frm_out_target; @@ -525,8 +660,13 @@ uint8_t apa_exec( } else { +#ifdef JBM_TSM_ON_TCS + float *buf_out_ptr = &( ps->buf_out[ps->l_buf_out - ps->l_frm] ); + float *frm_in_ptr = &( frm_in[ps->l_frm] ); +#else int16_t *buf_out_ptr = &( ps->buf_out[ps->l_buf_out - ps->l_frm] ); int16_t *frm_in_ptr = &( frm_in[ps->l_frm] ); +#endif /* fill input frame */ /* 1st input frame: previous output samples */ @@ -581,8 +721,13 @@ uint8_t apa_exec( /* discard old samples; always keep at least most recent l_frm samples */ if ( ( ps->l_buf_out + l_frm_out ) > ps->buf_out_capacity ) { +#ifdef JBM_TSM_ON_TCS + float *buf_out_ptr1 = ps->buf_out; + float *buf_out_ptr2; +#else int16_t *buf_out_ptr1 = ps->buf_out; int16_t *buf_out_ptr2; +#endif l_rem = ( ps->l_frm - l_frm_out ); if ( l_rem < 0 ) @@ -602,7 +747,11 @@ uint8_t apa_exec( return 5; } { +#ifdef JBM_TSM_ON_TCS + float *buf_out_ptr = &( ps->buf_out[ps->l_buf_out] ); +#else int16_t *buf_out_ptr = &( ps->buf_out[ps->l_buf_out] ); +#endif for ( i = 0; i < l_frm_out; i++ ) { buf_out_ptr[i] = a_out[i]; @@ -660,7 +809,11 @@ uint8_t apa_exec( */ static void get_scaling_quality( const apa_state_t *ps, +#ifdef JBM_TSM_ON_TCS + const float *signal, +#else const int16_t *signal, +#endif uint16_t s_len, uint16_t offset, uint16_t corr_len, @@ -813,7 +966,11 @@ static float apa_getQualityIncreaseForLowEnergy( */ static bool logarithmic_search( const apa_state_t *ps, +#ifdef JBM_TSM_ON_TCS + const float *signal, +#else const int16_t *signal, +#endif int16_t s_start, uint16_t inlen, uint16_t offset, @@ -926,7 +1083,11 @@ static bool logarithmic_search( */ static bool find_synch( apa_state_t *ps, +#ifdef JBM_TSM_ON_TCS + const float *in, +#else const int16_t *in, +#endif uint16_t l_in, int16_t s_start, uint16_t s_len, @@ -981,8 +1142,13 @@ static bool find_synch( */ static bool copy_frm( apa_state_t *ps, +#ifdef JBM_TSM_ON_TCS + const float frm_in[], + float frm_out[], +#else const int16_t frm_in[], int16_t frm_out[], +#endif uint16_t *l_frm_out ) { uint16_t i; @@ -1029,9 +1195,17 @@ static bool copy_frm( */ static bool shrink_frm( apa_state_t *ps, +#ifdef JBM_TSM_ON_TCS + const float frm_in[], +#else const int16_t frm_in[], +#endif uint16_t maxScaling, +#ifdef JBM_TSM_ON_TCS + float frm_out[], +#else int16_t frm_out[], +#endif uint16_t *l_frm_out ) { bool findSynchResult = 0; @@ -1062,6 +1236,22 @@ static bool shrink_frm( /* maximum scaling */ energy = -65; quality = 5; +#ifdef JBM_TSM_ON_TCS + xtract = maxScaling; + /* take samples already in the renderer buf into account */ + xtract += ps->l_r_buf; + /* snap to renderer time slot borders */ + xtract -= ( ps->l_ts - ( l_frm - xtract + ps->l_r_buf ) % ps->l_ts ); + while ( xtract < 0 ) + { + xtract += ps->l_ts; + } + while ( xtract > ( s_end - ps->num_channels ) ) + { + /* exceeded the possible shrinking, go back one renderer ts*/ + xtract -= ps->l_ts; + } +#else if ( maxScaling != 0U && s_end > maxScaling + 1 ) { xtract = maxScaling; @@ -1071,6 +1261,7 @@ static bool shrink_frm( /* set to last valid element (i.e. element[len - 1] but note for stereo last element is last pair of samples) */ xtract = s_end - ps->num_channels; } +#endif } else { @@ -1118,7 +1309,18 @@ static bool shrink_frm( { return 1; } - overlapAdd( frm_in, frm_in + xtract, frm_out, l_seg, ps->num_channels, ps->win + ps->l_halfwin, ps->win ); +#ifdef JBM_TSM_ON_TCS + if ( ps->evs_compat_mode == true ) + { + overlapAddEvs( frm_in, frm_in + xtract, frm_out, l_seg, ps->num_channels, ps->win + ps->l_halfwin, ps->win ); + } + else + { +#endif + overlapAdd( frm_in, frm_in + xtract, frm_out, l_seg, ps->num_channels, ps->win + ps->l_halfwin, ps->win ); +#ifdef JBM_TSM_ON_TCS + } +#endif } else { @@ -1165,8 +1367,13 @@ static bool shrink_frm( */ static bool extend_frm( apa_state_t *ps, +#ifdef JBM_TSM_ON_TCS + const float frm_in[], + float frm_out[], +#else const int16_t frm_in[], int16_t frm_out[], +#endif uint16_t *l_frm_out ) { bool findSynchResult = 0; @@ -1180,8 +1387,14 @@ static bool extend_frm( int16_t s_start = 0; float energy, quality = 0.0f; uint16_t l_frm, l_seg; +#ifdef JBM_TSM_ON_TCS + const float *fadeOut, *fadeIn; + float *out; +#else const int16_t *fadeOut, *fadeIn; int16_t *out; +#endif + l_frm = ps->l_frm; l_seg = ps->l_seg; @@ -1271,6 +1484,12 @@ static bool extend_frm( energy = -65; quality = 5; xtract[n] = s_start + ps->num_channels; +#ifdef JBM_TSM_ON_TCS + /* take renderer buffer samples into accout */ + xtract[n] += ps->l_r_buf; + /* snap to next renderer time slot border to resynchronize */ + xtract[n] -= ( ( N - 1 ) * l_seg - xtract[n] + ps->l_r_buf ) % ps->l_ts; +#endif } else { @@ -1327,13 +1546,29 @@ static bool extend_frm( fadeOut = frm_in + l_frm + xtract[n - 1] + l_seg; fadeIn = frm_in + l_frm + xtract[n]; out = frm_out + ( n - 2 ) * l_seg; - overlapAdd( fadeOut, fadeIn, out, l_seg, ps->num_channels, ps->win + ps->l_halfwin, ps->win ); +#ifdef JBM_TSM_ON_TCS + if ( ps->evs_compat_mode == true ) + { + overlapAddEvs( fadeOut, fadeIn, out, l_seg, ps->num_channels, ps->win + ps->l_halfwin, ps->win ); + } + else + { +#endif + overlapAdd( fadeOut, fadeIn, out, l_seg, ps->num_channels, ps->win + ps->l_halfwin, ps->win ); +#ifdef JBM_TSM_ON_TCS + } +#endif } else { /* just copy down 1st half of current segment (= 2nd half of previous segment) */ +#ifdef JBM_TSM_ON_TCS + float *frm_out_ptr; + const float *frm_in_ptr; +#else int16_t *frm_out_ptr; const int16_t *frm_in_ptr; +#endif frm_out_ptr = &( frm_out[( n - 2 ) * l_seg] ); frm_in_ptr = &( frm_in[l_frm + xtract[n]] ); for ( i = 0; i < l_seg; i++ ) diff --git a/lib_dec/jbm_pcmdsp_apa.h b/lib_dec/jbm_pcmdsp_apa.h index 543042f53b4301789af0eabe9fddee082254c8fa..a5e7cb7d61ab0810bf36913fd761bc39946a8a00 100644 --- a/lib_dec/jbm_pcmdsp_apa.h +++ b/lib_dec/jbm_pcmdsp_apa.h @@ -114,12 +114,26 @@ bool apa_set_rate( apa_state_t *ps, const int32_t output_Fs ); * @return 0 on success, 1 on failure */ bool apa_set_scale( apa_state_t *s, uint16_t scale ); +#ifdef JBM_TSM_ON_TCS +bool apa_set_renderer_granularity( apa_state_t *ps, uint16_t l_ts ); + +bool apa_set_renderer_residual_samples( apa_state_t *ps, uint16_t l_r_buf ); + +bool apa_set_evs_compat_mode( apa_state_t *ps, bool mode ); + +uint8_t apa_reconfigure( apa_state_t *ps, uint16_t num_channels, uint16_t l_ts ); +#endif + bool apa_set_complexity_options( apa_state_t *s, uint16_t wss, uint16_t css ); bool apa_set_quality( apa_state_t *s, float quality, uint16_t qualityred, uint16_t qualityrise ); bool apa_exit( apa_state_t **s ); +#ifdef JBM_TSM_ON_TCS +uint8_t apa_exec( apa_state_t *s, const float a_in[], uint16_t l_in, uint16_t maxScaling, float a_out[], uint16_t *l_out ); +#else uint8_t apa_exec( apa_state_t *s, const int16_t a_in[], uint16_t l_in, uint16_t maxScaling, int16_t a_out[], uint16_t *l_out ); +#endif #endif /* JBM_PCMDSP_APA_H */ diff --git a/lib_dec/jbm_pcmdsp_fifo.c b/lib_dec/jbm_pcmdsp_fifo.c index 81e833e5e56fc3860b7045c6b97405e52b71ae15..fd0df04ca8efac158aade1d4d66085cd601da55c 100644 --- a/lib_dec/jbm_pcmdsp_fifo.c +++ b/lib_dec/jbm_pcmdsp_fifo.c @@ -116,6 +116,15 @@ ivas_error pcmdsp_fifo_init( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) ); } +#ifdef DEBUGGING + { + uint32_t i; + for ( i = 0; i < nDataBytes; i++ ) + { + h->dataBegin[i] = 0; + } + } +#endif h->dataEnd = h->dataBegin + nDataBytes; h->dataWriteIterator = h->dataBegin; h->dataReadIterator = h->dataBegin; @@ -166,6 +175,49 @@ int16_t pcmdsp_fifo_write( return 0; } +#ifdef JBM_TSM_ON_TCS +/* Writes the given audio data to the FIFO. */ +int16_t pcmdsp_fifo_write_zero( + PCMDSP_FIFO_HANDLE h, + uint16_t nSamplesPerChannel ) +{ + uint16_t nBytesToWrite; + + /* check for empty input buffer */ + if ( nSamplesPerChannel == 0U ) + { + return 0; + } + + /* check, if enough space left */ + if ( nSamplesPerChannel > h->capacity - h->size ) + { + return -1; + } + + nBytesToWrite = nSamplesPerChannel * h->nBytesPerSampleSet; + if ( h->dataWriteIterator + nBytesToWrite > h->dataEnd ) + { + /* wrap around: writing two parts */ + uint16_t bytesOfFirstPart, secondSize; + bytesOfFirstPart = (uint16_t) ( h->dataEnd - h->dataWriteIterator ); + secondSize = nBytesToWrite - bytesOfFirstPart; + set_c( (int8_t *) h->dataWriteIterator, 0, bytesOfFirstPart ); + set_c( (int8_t *) h->dataBegin, 0, secondSize ); + h->dataWriteIterator = h->dataBegin + secondSize; + } + else + { + /* no wrap around: simple write */ + set_c( (int8_t *) h->dataWriteIterator, 0, nBytesToWrite ); + h->dataWriteIterator += nBytesToWrite; + } + h->size += nSamplesPerChannel; + + return 0; +} +#endif + /* Reads the given number of audio samples from the FIFO. */ int16_t pcmdsp_fifo_read( PCMDSP_FIFO_HANDLE h, diff --git a/lib_dec/jbm_pcmdsp_fifo.h b/lib_dec/jbm_pcmdsp_fifo.h index 13ffd146f871fb1b4d7c227b965a1931ba2f1e11..e6c64dc9e8e7b5cbeaa1c51f3f1ecda1cdc1f434 100644 --- a/lib_dec/jbm_pcmdsp_fifo.h +++ b/lib_dec/jbm_pcmdsp_fifo.h @@ -73,6 +73,9 @@ void pcmdsp_fifo_destroy( PCMDSP_FIFO_HANDLE *ph ); ivas_error pcmdsp_fifo_init( PCMDSP_FIFO_HANDLE h, uint16_t nSamplesPerChannel, uint16_t nChannels, uint16_t nBytesPerSample ); int16_t pcmdsp_fifo_write( PCMDSP_FIFO_HANDLE h, const uint8_t *samples, uint16_t nSamplesPerChannel ); +#ifdef JBM_TSM_ON_TCS +int16_t pcmdsp_fifo_write_zero( PCMDSP_FIFO_HANDLE h, uint16_t nSamplesPerChannel ); +#endif int16_t pcmdsp_fifo_read( PCMDSP_FIFO_HANDLE h, uint16_t nSamplesPerChannel, uint8_t *samples ); diff --git a/lib_dec/jbm_pcmdsp_similarityestimation.c b/lib_dec/jbm_pcmdsp_similarityestimation.c index f575acc7ad337f77ac81495ec36340ce1ce2ef49..e83d1f7c3769ff944fd751760a0b61bc1b301f70 100644 --- a/lib_dec/jbm_pcmdsp_similarityestimation.c +++ b/lib_dec/jbm_pcmdsp_similarityestimation.c @@ -52,7 +52,11 @@ /* Calculates cross correlation coefficient for template segment. */ float cross_correlation_self( +#ifdef JBM_TSM_ON_TCS + const float *signal, +#else const int16_t *signal, +#endif uint16_t x, uint16_t y, uint16_t corr_len ) @@ -63,7 +67,11 @@ float cross_correlation_self( c_c = 0.0f; for ( j = 0; j < corr_len; j++ ) { +#ifdef JBM_TSM_ON_TCS + c_c += ( signal[j + x] * signal[j + y] ); +#else c_c += ( (float) signal[j + x] * (float) signal[j + y] ); +#endif } return c_c; @@ -71,7 +79,11 @@ float cross_correlation_self( /* Calculates cross correlation coefficient for template segment. */ float cross_correlation_subsampled_self( +#ifdef JBM_TSM_ON_TCS + const float *signal, +#else const int16_t *signal, +#endif uint16_t x, uint16_t y, uint16_t corr_len, @@ -83,7 +95,11 @@ float cross_correlation_subsampled_self( c_c = 0.0f; for ( j = 0; j < corr_len; j += subsampling ) { +#ifdef JBM_TSM_ON_TCS + c_c += ( signal[j + x] * signal[j + y] ); +#else c_c += ( (float) signal[j + x] * (float) signal[j + y] ); +#endif } return c_c; @@ -92,7 +108,11 @@ float cross_correlation_subsampled_self( /* Calculates normalized cross correlation coefficient for template segment. */ float normalized_cross_correlation_self( +#ifdef JBM_TSM_ON_TCS + const float *signal, +#else const int16_t *signal, +#endif uint16_t x, uint16_t y, uint16_t corr_len, @@ -102,7 +122,11 @@ float normalized_cross_correlation_self( float c_c; float energy_xy, energy_x, energy_y; uint16_t j; +#ifdef JBM_TSM_ON_TCS + const float *signal_a, *signal_b; +#else const int16_t *signal_a, *signal_b; +#endif c_c = 0.0f; energy_x = 0.0f; @@ -111,11 +135,21 @@ float normalized_cross_correlation_self( signal_b = &signal[y]; for ( j = 0; j < corr_len; j += subsampling ) { +#ifdef JBM_TSM_ON_TCS + c_c += ( signal_a[j] * signal_b[j] ); + energy_x += ( signal_a[j] ) * ( signal_a[j] ); + energy_y += ( signal_b[j] ) * ( signal_b[j] ); +#else c_c += ( (float) signal_a[j] * (float) signal_b[j] ); energy_x += ( (float) signal_a[j] ) * ( (float) signal_a[j] ); energy_y += ( (float) signal_b[j] ) * ( (float) signal_b[j] ); +#endif } +#ifdef JBM_TSM_ON_TCS + energy_xy = sqrtf( energy_x * energy_y ); +#else energy_xy = (float) sqrt( (float) energy_x * (float) energy_y ); +#endif if ( energy_xy < 1.0f ) { energy_xy = 1.0f; /* conceal silent frames */ @@ -130,7 +164,11 @@ float normalized_cross_correlation_self( /* Splits the signal into segments and checks if all of them have very low energy. */ bool isSilence( +#ifdef JBM_TSM_ON_TCS + const float *signal, +#else const int16_t *signal, +#endif uint32_t len, uint32_t segments ) { @@ -145,7 +183,11 @@ bool isSilence( if ( ( i != 0U && i % samplesPerSegment == 0U ) || i + 1 == len ) { /* check energy of current segment */ +#ifdef JBM_TSM_ON_TCS + energy = 10 * log10f( energy / (float) samplesPerSegment ); +#else energy = 10 * (float) log10( energy / samplesPerSegment ); +#endif if ( energy > -65 ) { return false; diff --git a/lib_dec/jbm_pcmdsp_similarityestimation.h b/lib_dec/jbm_pcmdsp_similarityestimation.h index 4dc92f27b7cff9320280124d17733c6d6f7feabc..44b4fd246a4d9881550107196c374923284a15c7 100644 --- a/lib_dec/jbm_pcmdsp_similarityestimation.h +++ b/lib_dec/jbm_pcmdsp_similarityestimation.h @@ -67,7 +67,15 @@ * ******************************************************************************** */ -float cross_correlation_self( const int16_t *signal, uint16_t x, uint16_t y, uint16_t corr_len ); +float cross_correlation_self( +#ifdef JBM_TSM_ON_TCS + const float *signal, +#else + const int16_t *signal, +#endif + uint16_t x, + uint16_t y, + uint16_t corr_len ); /* ******************************************************************************** @@ -94,7 +102,16 @@ float cross_correlation_self( const int16_t *signal, uint16_t x, uint16_t y, uin * ******************************************************************************** */ -float cross_correlation_subsampled_self( const int16_t *signal, uint16_t x, uint16_t y, uint16_t corr_len, uint16_t subsampling ); +float cross_correlation_subsampled_self( +#ifdef JBM_TSM_ON_TCS + const float *signal, +#else + const int16_t *signal, +#endif + uint16_t x, + uint16_t y, + uint16_t corr_len, + uint16_t subsampling ); /* ******************************************************************************** @@ -132,9 +149,26 @@ float cross_correlation_subsampled_self( const int16_t *signal, uint16_t x, uint * ******************************************************************************** */ -float normalized_cross_correlation_self( const int16_t *signal, uint16_t x, uint16_t y, uint16_t corr_len, uint16_t subsampling, float *energy ); +float normalized_cross_correlation_self( +#ifdef JBM_TSM_ON_TCS + const float *signal, +#else + const int16_t *signal, +#endif + uint16_t x, + uint16_t y, + uint16_t corr_len, + uint16_t subsampling, + float *energy ); /* Splits the signal into segments and checks if all of them have very low energy. */ -bool isSilence( const int16_t *signal, uint32_t len, uint32_t segments ); +bool isSilence( +#ifdef JBM_TSM_ON_TCS + const float *signal, +#else + const int16_t *signal, +#endif + uint32_t len, + uint32_t segments ); #endif /* JBM_PCMDSP_SIMILARITYESTIMATION_H */ diff --git a/lib_dec/jbm_pcmdsp_window.c b/lib_dec/jbm_pcmdsp_window.c index f9f71ac802093d4a0b8dbfcab05d43895dae989d..a31d368c9119d1d35361c9657998fba14d24dff5 100644 --- a/lib_dec/jbm_pcmdsp_window.c +++ b/lib_dec/jbm_pcmdsp_window.c @@ -80,9 +80,15 @@ void hannWindow( *-----------------------------------------------------------------------*/ void overlapAdd( +#ifdef JBM_TSM_ON_TCS + const float *fadeOut, + const float *fadeIn, + float *out, +#else const int16_t *fadeOut, const int16_t *fadeIn, int16_t *out, +#endif uint16_t n, uint16_t nChannels, const float *fadeOutWin, @@ -90,7 +96,11 @@ void overlapAdd( { float fdOutVal, fdInVal; int16_t i, j, hannIter; +#ifdef JBM_TSM_ON_TCS + float combinedVal; +#else int32_t combinedVal; +#endif for ( j = 0; j < nChannels; j++ ) { @@ -101,8 +111,11 @@ void overlapAdd( fdOutVal = fadeOut[i] * fadeOutWin[hannIter]; fdInVal = fadeIn[i] * fadeInWin[hannIter]; /* round combinedVal value (taking care of sign) */ +#ifdef JBM_TSM_ON_TCS + combinedVal = fdInVal + fdOutVal; + out[i] = combinedVal; +#else combinedVal = (int32_t) ( ( fdInVal + fdOutVal ) + 0.5 ); - if ( fdInVal + fdOutVal < 0.0 ) { combinedVal = (int32_t) ( ( fdInVal + fdOutVal ) - 0.5 ); @@ -117,7 +130,57 @@ void overlapAdd( { combinedVal = MIN16B; } + out[i] = (int16_t) combinedVal; +#endif + hannIter++; + } + } + + return; +} + +void overlapAddEvs( + const float *fadeOut, + const float *fadeIn, + float *out, + uint16_t n, + uint16_t nChannels, + const float *fadeOutWin, + const float *fadeInWin ) +{ + float fdOutVal, fdInVal; + int16_t i, j, hannIter; + float combinedVal; + + for ( j = 0; j < nChannels; j++ ) + { + /* reset Hann window iterator to beginning (both channels use same window) */ + hannIter = 0; + for ( i = j; i < n; i += nChannels ) + { + fdOutVal = fadeOut[i] * fadeOutWin[hannIter]; + fdInVal = fadeIn[i] * fadeInWin[hannIter]; + /* round combinedVal value (taking care of sign) */ + + combinedVal = floorf( ( fdInVal + fdOutVal ) + 0.5f ); + if ( fdInVal + fdOutVal < 0.0 ) + { + combinedVal = ceilf( ( fdInVal + fdOutVal ) - 0.5f ); + } + + /* saturate value */ + if ( combinedVal > MAX16B_FLT ) + { + combinedVal = MAX16B_FLT; + } + else if ( combinedVal < MIN16B_FLT ) + { + combinedVal = MIN16B_FLT; + } + + out[i] = combinedVal; + hannIter++; } } diff --git a/lib_dec/jbm_pcmdsp_window.h b/lib_dec/jbm_pcmdsp_window.h index 67759e97384d759c2666f260eb2fd0754afe1326..8c1823867a8fa5d614b1d73c64a0ff6cb4c06cca 100644 --- a/lib_dec/jbm_pcmdsp_window.h +++ b/lib_dec/jbm_pcmdsp_window.h @@ -61,6 +61,10 @@ void hannWindow( uint16_t n, float *w ); * @param[in] nChannels number of channels * @param[in] fadeOutWin window for fade out * @param[in] fadeInWin window for fade in */ +#ifdef JBM_TSM_ON_TCS +void overlapAdd( const float *fadeOut, const float *fadeIn, float *out, uint16_t n, uint16_t nChannels, const float *fadeOutWin, const float *fadeInWin ); +void overlapAddEvs( const float *fadeOut, const float *fadeIn, float *out, uint16_t n, uint16_t nChannels, const float *fadeOutWin, const float *fadeInWin ); +#else void overlapAdd( const int16_t *fadeOut, const int16_t *fadeIn, int16_t *out, uint16_t n, uint16_t nChannels, const float *fadeOutWin, const float *fadeInWin ); - +#endif #endif /* JBM_PCMDSP_WINDOW_H */ diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 2209e118deece567ce23a22bb1cc9f4575a529c6..17c718bb48291022b3cd71862a3c2399c5c1f239 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -54,11 +54,27 @@ struct IVAS_DEC_VOIP uint16_t nSamplesFrame; /* Total number of samples in a frame (includes number of channels) */ JB4_HANDLE hJBM; PCMDSP_APA_HANDLE hTimeScaler; - PCMDSP_FIFO_HANDLE hFifoAfterTimeScaler; uint16_t lastDecodedWasActive; - int16_t *apaExecBuffer; /* Buffer for APA scaling */ +#ifdef JBM_TSM_ON_TCS + float *apaExecBuffer; /* Buffer for APA scaling */ +#else + int16_t *apaExecBuffer; /* Buffer for APA scaling */ +#endif JB4_DATAUNIT_HANDLE hCurrentDataUnit; /* Points to the currently processed data unit */ uint16_t *bs_conversion_buf; /* Buffer for bitstream conversion from packed to serial */ +#ifdef VARIABLE_SPEED_DECODING + uint8_t mode; + uint16_t speedFac; + bool needNewFrame; +#endif +#ifdef JBM_TSM_ON_TCS + JBM_RENDERER_TYPE rendererType; + PCMDSP_FIFO_HANDLE hFifoOut; + uint8_t nTransportChannelsOld; + uint16_t nSamplesAvailableNext; +#else + PCMDSP_FIFO_HANDLE hFifoAfterTimeScaler; +#endif #ifdef SUPPORT_JBM_TRACEFILE IVAS_JBM_TRACE_DATA JbmTraceData; #endif @@ -93,14 +109,26 @@ static void IVAS_DEC_Close_VoIP( IVAS_DEC_VOIP *hVoIP ); #ifdef SUPPORT_JBM_TRACEFILE static void store_JbmData( IVAS_DEC_VOIP *hVoIP, JB4_DATAUNIT_HANDLE dataUnit, const uint32_t systemTimestamp_ms, const uint16_t extBufferedSamples, const int32_t output_Fs ); #endif +#ifdef JBM_TSM_ON_TCS +static ivas_error evs_dec_main( Decoder_Struct *st_ivas, const int16_t nOutSamples, float *floatBuf, int16_t *pcmBuf ); +#else static ivas_error evs_dec_main( Decoder_Struct *st_ivas, const int16_t nOutSamples, int16_t *pcmBuf ); +#endif static ivas_error input_format_API_to_internal( IVAS_DEC_INPUT_FORMAT input_format, int16_t *bitstream_format_internal, int16_t *sdp_hf_only, const bool is_voip_enabled ); #ifdef NON_DIEGETIC_PAN static void init_decoder_config( DECODER_CONFIG_HANDLE hDecoderConfig, const int16_t orientation_tracking ); #else static void init_decoder_config( DECODER_CONFIG_HANDLE hDecoderConfig, const int16_t orientation_tracking, const float non_diegetic_pan ); #endif - +#ifdef JBM_TSM_ON_TCS +static int16_t IVAS_DEC_VoIP_GetRenderGranularity( Decoder_Struct *st_ivas ); +static JBM_RENDERER_TYPE IVAS_DEC_VoIP_GetRendererConfig( IVAS_DEC_HANDLE hIvasDec ); +static ivas_error IVAS_DEC_VoIP_reconfigure( IVAS_DEC_HANDLE hIvasDec, const uint16_t nTransportChannels, const uint16_t l_ts ); +static ivas_error IVAS_DEC_Setup( IVAS_DEC_HANDLE hIvasDec, uint16_t *nTcBufferGranularity, uint8_t *nTransportChannels, uint8_t *nOutChannels, uint16_t *nSamplesRendered, int16_t *data ); +static ivas_error IVAS_DEC_GetTcSamples( IVAS_DEC_HANDLE hIvasDec, float *pcmBuf, int16_t *nOutSamples ); +static ivas_error IVAS_DEC_RendererFeedTcSamples( IVAS_DEC_HANDLE hIvasDec, const int16_t nSamplesForRendering, int16_t *nSamplesResidual, float *pcmBuf ); +static ivas_error IVAS_DEC_GetRenderedSamples( IVAS_DEC_HANDLE hIvasDec, const uint16_t nSamplesForRendering, uint16_t *nSamplesRendered, uint16_t *nSamplesAvailableNext, int16_t *pcmBuf ); +#endif /*---------------------------------------------------------------------* * IVAS_DEC_Open() @@ -248,6 +276,9 @@ static void init_decoder_config( hDecoderConfig->no_diegetic_pan = no_diegetic_pan; #endif +#ifdef JBM_TSM_ON_TCS + hDecoderConfig->voip_active = 0; +#endif return; } @@ -502,7 +533,11 @@ ivas_error IVAS_DEC_Configure( *---------------------------------------------------------------------*/ ivas_error IVAS_DEC_EnableVoIP( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ +#ifdef VARIABLE_SPEED_DECODING + const IVAS_DEC_VOIP_MODE voipMode, /* i : VoIP or varable speed */ + const uint16_t speedFac, /* i : speed factor for varable speed */ +#endif const int16_t jbmSafetyMargin, /* i : allowed delay reserve for JBM, in milliseconds */ const IVAS_DEC_INPUT_FORMAT inputFormat /* i : format of the input bitstream */ ) @@ -512,8 +547,10 @@ ivas_error IVAS_DEC_EnableVoIP( error = IVAS_ERR_OK; +#ifndef JBM_TSM_ON_TCS /* initialize time scaler and FIFO after time scaler */ uint16_t wss, css; +#endif if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) { @@ -525,8 +562,30 @@ ivas_error IVAS_DEC_EnableVoIP( hIvasDec->Opt_VOIP = 1; - hDecoderConfig->nchan_out = audioCfg2channels( hDecoderConfig->output_config ); +#ifdef JBM_TSM_ON_TCS + hDecoderConfig->voip_active = 1; +#endif + +#ifdef JBM_TSM_ON_TCS + if ( hDecoderConfig->output_config != AUDIO_CONFIG_EXTERNAL ) + { +#endif + hDecoderConfig->nchan_out = audioCfg2channels( hDecoderConfig->output_config ); + +#ifdef JBM_TSM_ON_TCS + } +#ifdef VARIABLE_SPEED_DECODING + else + { + hDecoderConfig->nchan_out = 1; + } +#endif +#endif + + +#ifndef JBM_TSM_ON_TCS assert( hDecoderConfig->nchan_out > 0 && "EXT output not yet supported in VoIP mode" ); +#endif if ( ( error = input_format_API_to_internal( inputFormat, &hIvasDec->bitstreamformat, &hIvasDec->sdp_hf_only, true ) ) != IVAS_ERR_OK ) { @@ -540,13 +599,31 @@ ivas_error IVAS_DEC_EnableVoIP( hIvasDec->hVoIP->lastDecodedWasActive = 0; hIvasDec->hVoIP->hCurrentDataUnit = NULL; +#ifdef VARIABLE_SPEED_DECODING + hIvasDec->hVoIP->mode = voipMode; + hIvasDec->hVoIP->speedFac = speedFac; + hIvasDec->hVoIP->needNewFrame = false; +#endif +#ifdef JBM_TSM_ON_TCS + hIvasDec->hVoIP->nSamplesFrame = (uint16_t) ( hDecoderConfig->output_Fs / FRAMES_PER_SEC ); + hIvasDec->hVoIP->nSamplesAvailableNext = 0; + hIvasDec->hVoIP->rendererType = JBM_RENDERER_NONE; + hIvasDec->hVoIP->hFifoOut = NULL; +#else hIvasDec->hVoIP->nSamplesFrame = (uint16_t) ( hDecoderConfig->output_Fs * hDecoderConfig->nchan_out / FRAMES_PER_SEC ); +#endif +#ifdef JBM_TSM_ON_TCS + /* postpone init of the buffers until we know the real number of TCs*/ + hIvasDec->hVoIP->apaExecBuffer = NULL; + hIvasDec->hVoIP->nTransportChannelsOld = 0; +#else hIvasDec->hVoIP->apaExecBuffer = malloc( sizeof( int16_t ) * APA_BUF_PER_CHANNEL * hDecoderConfig->nchan_out ); if ( hIvasDec->hVoIP->apaExecBuffer == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate VoIP handle" ); } +#endif #define WMC_TOOL_SKIP /* Bitstream conversion is not counted towards complexity and memory usage */ @@ -559,15 +636,23 @@ ivas_error IVAS_DEC_EnableVoIP( } /* initialize JBM */ - if ( ( error = JB4_Create( &hIvasDec->hVoIP->hJBM ) != IVAS_ERR_OK ) != IVAS_ERR_OK ) - { - return error; - } - if ( ( error = JB4_Init( hIvasDec->hVoIP->hJBM, jbmSafetyMargin ) ) != IVAS_ERR_OK ) +#ifdef VARIABLE_SPEED_DECODING + hIvasDec->hVoIP->hJBM = NULL; + if ( hIvasDec->hVoIP->mode == IVAS_DEC_VOIP_MODE_VOIP ) { - return error; +#endif + if ( ( error = JB4_Create( &hIvasDec->hVoIP->hJBM ) != IVAS_ERR_OK ) != IVAS_ERR_OK ) + { + return error; + } + if ( JB4_Init( hIvasDec->hVoIP->hJBM, jbmSafetyMargin ) != 0 ) + { + return IVAS_ERR_FAILED_ALLOC; + } +#ifdef VARIABLE_SPEED_DECODING } - +#endif +#ifndef JBM_TSM_ON_TCS if ( hDecoderConfig->output_Fs == 8000 ) { wss = 1; @@ -592,8 +677,40 @@ ivas_error IVAS_DEC_EnableVoIP( { return IVAS_ERR_INIT_ERROR; } +#endif - if ( apa_init( &hIvasDec->hVoIP->hTimeScaler, hDecoderConfig->nchan_out ) != IVAS_ERR_OK || +#ifdef JBM_TSM_ON_TCS + + /* postpone init of time scaler until we know the real number of TCs */ + hIvasDec->hVoIP->hTimeScaler = NULL; + /* create output pcm fifo*/ + /* :TODO: also provide CLDFB output FIFO if things work out */ +#ifdef VARIABLE_SPEED_DECODING + if ( hIvasDec->hVoIP->mode == IVAS_DEC_VOIP_MODE_VARIABLE_SPEED ) + { + hIvasDec->hVoIP->needNewFrame = true; + } +#endif +#else +#ifdef VARIABLE_SPEED_DECODING + { + float startQuality = hIvasDec->hVoIP->mode == IVAS_DEC_VOIP_MODE_VARIABLE_SPEED ? -2.0f : 1.0f; + if ( apa_init( &hIvasDec->hVoIP->hTimeScaler, + hDecoderConfig->nchan_out ) != IVAS_ERR_OK || + apa_set_rate( hIvasDec->hVoIP->hTimeScaler, hDecoderConfig->output_Fs ) != 0 || + apa_set_complexity_options( hIvasDec->hVoIP->hTimeScaler, wss, css ) != 0 || + apa_set_quality( hIvasDec->hVoIP->hTimeScaler, startQuality, 4, 4 ) != 0 || + pcmdsp_fifo_create( &hIvasDec->hVoIP->hFifoAfterTimeScaler ) != 0 || + pcmdsp_fifo_init( hIvasDec->hVoIP->hFifoAfterTimeScaler, (uint16_t) ( hDecoderConfig->output_Fs * 4 / FRAMES_PER_SEC ) /* 4 frames */, hDecoderConfig->nchan_out, sizeof( int16_t ) ) != 0 ) + { + return IVAS_ERR_INIT_ERROR; + } + /* we instantly need a new frame */ + hIvasDec->hVoIP->needNewFrame = true; + } +#else + if ( apa_init( &hIvasDec->hVoIP->hTimeScaler, + hDecoderConfig->nchan_out ) != IVAS_ERR_OK || apa_set_rate( hIvasDec->hVoIP->hTimeScaler, hDecoderConfig->output_Fs ) != 0 || apa_set_complexity_options( hIvasDec->hVoIP->hTimeScaler, wss, css ) != 0 || apa_set_quality( hIvasDec->hVoIP->hTimeScaler, 1, 4, 4 ) != 0 || @@ -602,6 +719,8 @@ ivas_error IVAS_DEC_EnableVoIP( { return IVAS_ERR_INIT_ERROR; } +#endif +#endif return error; } @@ -690,6 +809,13 @@ ivas_error IVAS_DEC_FeedFrame_Serial( st->use_partial_copy = 1; } +#ifdef VARIABLE_SPEED_DECODING + if ( hIvasDec->hVoIP != NULL && hIvasDec->hVoIP->mode == IVAS_DEC_VOIP_MODE_VARIABLE_SPEED ) + { + hIvasDec->hVoIP->needNewFrame = false; + } +#endif + return error; } @@ -722,7 +848,11 @@ ivas_error IVAS_DEC_GetSamples( if ( hIvasDec->mode == IVAS_DEC_MODE_EVS ) { +#ifdef JBM_TSM_ON_TCS + if ( ( error = evs_dec_main( st_ivas, *nOutSamples, NULL, pcmBuf ) ) != IVAS_ERR_OK ) +#else if ( ( error = evs_dec_main( st_ivas, *nOutSamples, pcmBuf ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -747,6 +877,187 @@ ivas_error IVAS_DEC_GetSamples( } +#ifdef JBM_TSM_ON_TCS +/*---------------------------------------------------------------------* + * IVAS_DEC_Setup( ) + * + * Main function to decode to PCM data of the transport channels + *---------------------------------------------------------------------*/ + +static ivas_error IVAS_DEC_Setup( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + uint16_t *nTcBufferGranularity, /* o : granularity of the TC Buffer */ + uint8_t *nTransportChannels, /* o : number of decoded transport PCM channels */ + uint8_t *nOutChannels, /* o : number of decoded out channels (PCM or CLDFB) */ + uint16_t *nSamplesRendered, /* o : number of samples flushed from the last frame */ + int16_t *data /* o : flushed samples */ +) +{ + ivas_error error; + + error = IVAS_ERR_OK; + + *nSamplesRendered = 0; + + if ( hIvasDec->mode == IVAS_DEC_MODE_EVS ) + { + *nTransportChannels = 1; + *nOutChannels = 1; + } + else + { + Decoder_Struct *st_ivas; + + st_ivas = hIvasDec->st_ivas; + /*----------------------------------------------------------------* + * IVAS decoder setup + * - read IVAS format signaling + * - read IVAS format specific signaling + * - initialize decoder in the first frame based on IVAS format and number of transport channels + * - reconfigure the decoder when the number of TC or IVAS total bitrate change + *----------------------------------------------------------------*/ + + if ( st_ivas->bfi == 0 ) + { + if ( ( error = ivas_dec_setup( st_ivas, nSamplesRendered, data ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + *nTransportChannels = (uint8_t) st_ivas->hTcBuffer->nchan_transport_jbm; + *nTcBufferGranularity = (uint16_t) st_ivas->hTcBuffer->n_samples_granularity; + *nOutChannels = (uint8_t) st_ivas->hDecoderConfig->nchan_out; + } + + return error; +} + +/*---------------------------------------------------------------------* + * IVAS_DEC_GetTcSamples( ) + * + * Main function to decode to PCM data of the transport channels + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_GetTcSamples( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + float *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 */ + int16_t *nOutSamples /* o : number of samples per channel written to output buffer */ +) +{ + Decoder_Struct *st_ivas; + ivas_error error; + + error = IVAS_ERR_OK; + + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + st_ivas = hIvasDec->st_ivas; + + *nOutSamples = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ); + + if ( hIvasDec->mode == IVAS_DEC_MODE_EVS ) + { + if ( ( error = evs_dec_main( st_ivas, *nOutSamples, pcmBuf, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( hIvasDec->mode == IVAS_DEC_MODE_IVAS ) + { + /* run the main IVAS decoding routine */ + if ( ( error = ivas_jbm_dec_tc( st_ivas, pcmBuf ) ) != IVAS_ERR_OK ) + { + return error; + } + + hIvasDec->isInitialized = true; /* Initialization done in ivas_dec() */ + } + + if ( hIvasDec->hasBeenFedFirstGoodFrame ) + { + hIvasDec->hasDecodedFirstGoodFrame = true; + } + + return error; +} + +/*---------------------------------------------------------------------* + * IVAS_DEC_Rendered_FeedTcSamples( ) + * + * Main function to decode to PCM data of the transport channels + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_RendererFeedTcSamples( + IVAS_DEC_HANDLE hIvasDec, /* i/o : IVAS decoder handle */ + const int16_t nSamplesForRendering, /* i: : number of TC samples wanted from the renderer */ + int16_t *nSamplesResidual, /* o: : number of samples not fitting into the renderer grid and buffer for the next call*/ + float *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 */ +) +{ + Decoder_Struct *st_ivas; + + ivas_error error; + + error = IVAS_ERR_OK; + + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + st_ivas = hIvasDec->st_ivas; + + /* feed the TCs to the IVAS renderer */ + if ( ( error = ivas_jbm_dec_feed_tc_to_renderer( st_ivas, nSamplesForRendering, nSamplesResidual, pcmBuf ) ) != IVAS_ERR_OK ) + { + return error; + } + + return error; +} + +/*---------------------------------------------------------------------* + * IVAS_DEC_GetRenderedSamples( ) + * + * Main function to decode to PCM data of the transport channels + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_GetRenderedSamples( + IVAS_DEC_HANDLE hIvasDec, /* i/o : IVAS decoder handle */ + const uint16_t nSamplesForRendering, /* i: : number of TC samples wanted from the renderer */ + uint16_t *nSamplesRendered, /* o : number of samples rendered */ + uint16_t *nSamplesAvailableNext, /* o : number of samples still available in the renerer pipeline */ + int16_t *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 */ +) +{ + Decoder_Struct *st_ivas; + ivas_error error; + + error = IVAS_ERR_OK; + + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + st_ivas = hIvasDec->st_ivas; + + /* run the main IVAS decoding routine */ + if ( ( error = ivas_jbm_dec_render( st_ivas, nSamplesForRendering, nSamplesRendered, nSamplesAvailableNext, pcmBuf ) ) != IVAS_ERR_OK ) + { + return error; + } + + + return error; +} +#endif + + /*---------------------------------------------------------------------* * IVAS_DEC_GetNumObjects( ) * @@ -1474,6 +1785,27 @@ ivas_error IVAS_DEC_VoIP_FeedFrame( return IVAS_ERR_OK; } +#ifdef VARIABLE_SPEED_DECODING +/*---------------------------------------------------------------------* + * IVAS_DEC_VoIP_SetScale( ) + * + * Set the TSM scale + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_VoIP_SetScale( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const int16_t scale /* i : TSM scale to set */ +) +{ + ivas_error error; + + error = IVAS_ERR_OK; + + hIvasDec->hVoIP->speedFac = scale; + + return error; +} +#endif /*---------------------------------------------------------------------* * IVAS_DEC_VoIP_GetSamples( ) @@ -1486,11 +1818,16 @@ ivas_error IVAS_DEC_VoIP_GetSamples( uint16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ int16_t *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 */ const uint32_t systemTimestamp_ms /* i : current system timestamp */ +#if defined( JBM_TSM_ON_TCS ) || defined( VARIABLE_SPEED_DECODING ) + , + uint16_t *sampleAvailableNext /* o : samples available for the next call */ +#endif #ifdef SUPPORT_JBM_TRACEFILE , JbmTraceFileWriterFn jbmWriterFn, void *jbmWriter #endif + ) { Decoder_Struct *st_ivas; @@ -1504,6 +1841,12 @@ ivas_error IVAS_DEC_VoIP_GetSamples( int16_t timeScalingDone; int16_t result; ivas_error error; +#ifdef JBM_TSM_ON_TCS + int16_t nSamplesRendered; + uint16_t nSamplesTcsScaled; + uint8_t nTransportChannels; + uint8_t nOutChannels; +#endif error = IVAS_ERR_OK; @@ -1512,133 +1855,472 @@ ivas_error IVAS_DEC_VoIP_GetSamples( hVoIP = hIvasDec->hVoIP; timeScalingDone = 0; +#ifdef JBM_TSM_ON_TCS + nOutChannels = (uint8_t) st_ivas->hDecoderConfig->nchan_out; + nTransportChannels = 0; + nSamplesTcsScaled = hVoIP->nSamplesFrame; + nSamplesRendered = 0; +#endif +#ifdef VARIABLE_SPEED_DECODING + scale = hVoIP->speedFac; + maxScaling = hVoIP->speedFac; +#endif + /* TODO(mcjbm): ringbuffer capacity should be configurable by user */ +#ifdef JBM_TSM_ON_TCS + if ( ( hVoIP->hFifoOut != NULL && nSamplesPerChannel > hVoIP->hFifoOut->capacity ) || nSamplesPerChannel == 0 ) +#else if ( nSamplesPerChannel > hVoIP->hFifoAfterTimeScaler->capacity || nSamplesPerChannel == 0 ) +#endif { return IVAS_ERR_WRONG_PARAMS; } /* make sure that the FIFO after decoder/scaler contains at least one sound card frame (i.e. 20ms) */ +#ifdef JBM_TSM_ON_TCS + while ( ( hVoIP->hFifoOut != NULL && pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoOut ) < nSamplesPerChannel ) || ( hVoIP->hFifoOut == NULL && nSamplesRendered < nSamplesPerChannel ) ) +#else while ( pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoAfterTimeScaler ) < nSamplesPerChannel ) +#endif { - extBufferedSamples = pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoAfterTimeScaler ); - extBufferedTime_ms = extBufferedSamples * 1000 / hDecoderConfig->output_Fs; - dataUnit = NULL; - /* pop one access unit from the jitter buffer */ - result = JB4_PopDataUnit( hVoIP->hJBM, systemTimestamp_ms, extBufferedTime_ms, &dataUnit, &scale, &maxScaling ); - if ( result != 0 ) +#ifdef VARIABLE_SPEED_DECODING + if ( hVoIP->mode == IVAS_DEC_VOIP_MODE_VARIABLE_SPEED && hVoIP->needNewFrame ) { - return IVAS_ERR_UNKNOWN; + /* we need another bs frame fed into the decoder...*/ + *sampleAvailableNext = 0; + return IVAS_ERR_VS_FRAME_NEEDED; } - - maxScaling = maxScaling * hDecoderConfig->output_Fs / 1000; - /* avoid time scaling multiple times in one sound card slot */ - if ( scale != 100U ) +#endif +#ifdef JBM_TSM_ON_TCS + if ( hVoIP->nSamplesAvailableNext == 0 ) { - if ( timeScalingDone ) + if ( hVoIP->hFifoOut ) { - scale = 100; + extBufferedSamples = pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoOut ); + nSamplesRendered = extBufferedSamples; } else { - timeScalingDone = 1; + extBufferedSamples = nSamplesRendered; /* TODO: JBM use renderer residual samples here */ } - } - - /* copy bitstream into decoder state */ - if ( dataUnit ) - { - hIvasDec->hVoIP->hCurrentDataUnit = dataUnit; - - bsCompactToSerial( dataUnit->data, hIvasDec->hVoIP->bs_conversion_buf, dataUnit->dataSize ); - IVAS_DEC_FeedFrame_Serial( hIvasDec, hIvasDec->hVoIP->bs_conversion_buf, dataUnit->dataSize, 0 ); - } - else if ( hIvasDec->hasDecodedFirstGoodFrame ) - { - /* Decoder has been initialized with first good frame - do PLC */ - IVAS_DEC_FeedFrame_Serial( hIvasDec, hIvasDec->hVoIP->bs_conversion_buf, 0, 1 ); - } - - /* decode */ - if ( !hIvasDec->hasBeenFedFirstGoodFrame ) - { - /* codec mode to use not known yet - simply output silence */ - set_s( hVoIP->apaExecBuffer, 0, hVoIP->nSamplesFrame ); /* TODO(mcjbm): Could be optimized: just write directly to output buffer */ - } - else - { +#else + extBufferedSamples = pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoAfterTimeScaler ); +#endif + extBufferedTime_ms = extBufferedSamples * 1000 / hDecoderConfig->output_Fs; - if ( ( error = IVAS_DEC_GetSamples( hIvasDec, hVoIP->apaExecBuffer, &nOutSamplesElse ) ) != IVAS_ERR_OK ) + dataUnit = NULL; +#ifdef VARIABLE_SPEED_DECODING + if ( hVoIP->mode == IVAS_DEC_VOIP_MODE_VOIP ) { - return error; +#endif + /* pop one access unit from the jitter buffer */ + result = JB4_PopDataUnit( hVoIP->hJBM, systemTimestamp_ms, extBufferedTime_ms, &dataUnit, &scale, &maxScaling ); + if ( result != 0 ) + { + return IVAS_ERR_UNKNOWN; + } +#ifdef VARIABLE_SPEED_DECODING } - } - - if ( dataUnit ) - { - if ( dataUnit->partial_frame != 0 ) + else if ( hVoIP->mode == IVAS_DEC_VOIP_MODE_VARIABLE_SPEED ) { - hVoIP->lastDecodedWasActive = 1; + scale = hVoIP->speedFac; + maxScaling = hVoIP->speedFac; } +#ifdef DEBUGGING else { - hVoIP->lastDecodedWasActive = !dataUnit->silenceIndicator; + assert( "Wrong VoIP mode!\n" && 0 ); } - /* data unit memory is no longer used */ - JB4_FreeDataUnit( hVoIP->hJBM, dataUnit ); - } +#endif +#endif - /* limit scale to range supported by time scaler */ - if ( scale < APA_MIN_SCALE ) - { - scale = APA_MIN_SCALE; - } - else if ( scale > APA_MAX_SCALE ) - { - scale = APA_MAX_SCALE; - } + maxScaling = maxScaling * hDecoderConfig->output_Fs / 1000; + /* avoid time scaling multiple times in one sound card slot */ + if ( scale != 100U ) + { + if ( timeScalingDone ) + { + scale = 100; + } + else + { + timeScalingDone = 1; + } + } - /* apply time scaling on decoded/concealed samples */ - if ( apa_set_scale( hVoIP->hTimeScaler, (uint16_t) scale ) != 0 ) - { - return IVAS_ERR_UNKNOWN; - } +#ifdef VARIABLE_SPEED_DECODING + if ( hVoIP->mode == IVAS_DEC_VOIP_MODE_VOIP ) + { +#endif + /* copy bitstream into decoder state */ + if ( dataUnit ) + { + hIvasDec->hVoIP->hCurrentDataUnit = dataUnit; + + bsCompactToSerial( dataUnit->data, hIvasDec->hVoIP->bs_conversion_buf, dataUnit->dataSize ); + IVAS_DEC_FeedFrame_Serial( hIvasDec, hIvasDec->hVoIP->bs_conversion_buf, dataUnit->dataSize, 0 ); + } + else if ( hIvasDec->hasDecodedFirstGoodFrame ) + { + /* Decoder has been initialized with first good frame - do PLC */ + IVAS_DEC_FeedFrame_Serial( hIvasDec, hIvasDec->hVoIP->bs_conversion_buf, 0, 1 ); + } +#ifdef VARIABLE_SPEED_DECODING + } +#endif + /* decode */ + if ( !hIvasDec->hasBeenFedFirstGoodFrame ) + { + /* codec mode to use not known yet - simply output silence */ +#ifdef JBM_TSM_ON_TCS + nSamplesTcsScaled = hVoIP->nSamplesFrame; + if ( hVoIP->hFifoOut != NULL ) + { + /* feed zeros to FIFO */ + if ( pcmdsp_fifo_write_zero( hVoIP->hFifoOut, nSamplesTcsScaled ) != 0 ) + { + return IVAS_ERR_UNKNOWN; + } + } + else + { + /* directly set output zero */ + set_s( pcmBuf, 0, nSamplesPerChannel * nOutChannels ); + } + nSamplesRendered = nSamplesTcsScaled; +#else + set_s( hVoIP->apaExecBuffer, 0, hVoIP->nSamplesFrame ); /* TODO(mcjbm): Could be optimized: just write directly to output buffer */ +#endif + } + else + { + +#ifdef JBM_TSM_ON_TCS + uint16_t l_ts = 1; + uint16_t nSamplesRendered_loop; + /* setup ivas decoder and get the number of TCs */ + /* might render some remaining samples from the previous frame too if the renderer granularity changed */ + if ( hVoIP->hFifoOut ) + { + int16_t rendererPcmBuf[( MAX_OUTPUT_CHANNELS * L_FRAME_MAX * APA_MAX_SCALE ) / 100]; + if ( ( error = IVAS_DEC_Setup( hIvasDec, &l_ts, &nTransportChannels, &nOutChannels, &nSamplesRendered_loop, rendererPcmBuf ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( pcmdsp_fifo_write( hVoIP->hFifoOut, (uint8_t *) rendererPcmBuf, nSamplesRendered_loop ) != 0 ) + { + return IVAS_ERR_UNKNOWN; + } + } + else + { + if ( ( error = IVAS_DEC_Setup( hIvasDec, &l_ts, &nTransportChannels, &nOutChannels, &nSamplesRendered_loop, pcmBuf + nSamplesRendered * nOutChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + } + nSamplesRendered += nSamplesRendered_loop; + if ( nTransportChannels != hVoIP->nTransportChannelsOld ) + { + IVAS_DEC_VoIP_reconfigure( hIvasDec, nTransportChannels, l_ts ); + } + /* decode TCs only */ + if ( ( error = IVAS_DEC_GetTcSamples( hIvasDec, hVoIP->apaExecBuffer, &nOutSamplesElse ) ) != IVAS_ERR_OK ) + { + return error; + } + +#else + if ( ( error = IVAS_DEC_GetSamples( hIvasDec, hVoIP->apaExecBuffer, &nOutSamplesElse ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif + } + +#ifdef VARIABLE_SPEED_DECODING + if ( hVoIP->mode == IVAS_DEC_VOIP_MODE_VOIP ) + { +#endif + if ( dataUnit ) + { + if ( dataUnit->partial_frame != 0 ) + { + hVoIP->lastDecodedWasActive = 1; + } + else + { + hVoIP->lastDecodedWasActive = !dataUnit->silenceIndicator; + } + /* data unit memory is no longer used */ + JB4_FreeDataUnit( hVoIP->hJBM, dataUnit ); + } +#ifdef VARIABLE_SPEED_DECODING + } + else + { + hVoIP->lastDecodedWasActive = 1; + } +#endif + /* limit scale to range supported by time scaler */ + if ( scale < APA_MIN_SCALE ) + { + scale = APA_MIN_SCALE; + } + else if ( scale > APA_MAX_SCALE ) + { + scale = APA_MAX_SCALE; + } + + /* apply time scaling on decoded/concealed samples */ +#ifdef JBM_TSM_ON_TCS + if ( hIvasDec->hasBeenFedFirstGoodFrame ) + { +#endif + if ( apa_set_scale( hVoIP->hTimeScaler, (uint16_t) scale ) != 0 ) + { + return IVAS_ERR_UNKNOWN; + } +#ifdef JBM_TSM_ON_TCS + result = apa_exec( hVoIP->hTimeScaler, hVoIP->apaExecBuffer, hVoIP->nSamplesFrame * nTransportChannels, (uint16_t) maxScaling, hVoIP->apaExecBuffer, &nTimeScalerOutSamples ); +#else result = apa_exec( hVoIP->hTimeScaler, hVoIP->apaExecBuffer, hVoIP->nSamplesFrame, (uint16_t) maxScaling, hVoIP->apaExecBuffer, &nTimeScalerOutSamples ); - if ( result != 0 ) - { - return IVAS_ERR_UNKNOWN; - } - assert( nTimeScalerOutSamples <= APA_BUF ); +#endif + if ( result != 0 ) + { + return IVAS_ERR_UNKNOWN; + } + assert( nTimeScalerOutSamples <= APA_BUF ); +#ifdef JBM_TSM_ON_TCS + nSamplesTcsScaled = nTimeScalerOutSamples / nTransportChannels; +#else /* append scaled samples to FIFO */ if ( pcmdsp_fifo_write( hVoIP->hFifoAfterTimeScaler, (uint8_t *) hVoIP->apaExecBuffer, (uint16_t) ( nTimeScalerOutSamples / hDecoderConfig->nchan_out ) ) != 0 ) { return IVAS_ERR_UNKNOWN; } +#ifdef VARIABLE_SPEED_DECODING + if ( hVoIP->mode == IVAS_DEC_VOIP_MODE_VARIABLE_SPEED ) + { + int16_t nSamplesAvailable = pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoAfterTimeScaler ); + if ( nSamplesAvailable < nSamplesPerChannel ) + { + hVoIP->needNewFrame = true; + } + } +#endif +#endif + +#ifdef JBM_TSM_ON_TCS + if ( hIvasDec->hasBeenFedFirstGoodFrame && hVoIP->rendererType != JBM_RENDERER_NONE ) + { + /* render IVAS frames */ + int16_t nResidualSamples; + if ( ( error = IVAS_DEC_RendererFeedTcSamples( hIvasDec, nSamplesTcsScaled, &nResidualSamples, hVoIP->apaExecBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + /* feed residual samples to TSM for the next call */ + if ( apa_set_renderer_residual_samples( hVoIP->hTimeScaler, (uint16_t) nResidualSamples ) != 0 ) + { + return IVAS_ERR_UNKNOWN; + } + } + else + { + /* inplace float->int16_t conversion*/ +#ifdef DEBUGGING + st_ivas->noClipping += +#endif + syn_output( hVoIP->apaExecBuffer, nTimeScalerOutSamples, (int16_t *) hVoIP->apaExecBuffer ); + if ( pcmdsp_fifo_write( hVoIP->hFifoOut, (uint8_t *) hVoIP->apaExecBuffer, nSamplesTcsScaled ) != 0 ) + { + return IVAS_ERR_UNKNOWN; + } + nSamplesRendered = nSamplesTcsScaled; + } + } +#endif #ifdef SUPPORT_JBM_TRACEFILE - /* jbmWriterFn and jbmWriter may be NULL if tracefile writing was not requested on CLI */ - if ( jbmWriterFn != NULL && jbmWriter != NULL ) + /* jbmWriterFn and jbmWriter may be NULL if tracefile writing was not requested on CLI */ + if ( jbmWriterFn != NULL && jbmWriter != NULL ) + { + /* write JBM trace data entry */ + store_JbmData( hVoIP, dataUnit, systemTimestamp_ms, extBufferedSamples, hDecoderConfig->output_Fs ); + if ( ( jbmWriterFn( &hVoIP->JbmTraceData, jbmWriter ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing JBM Trace data to file\n" ); + return IVAS_ERR_UNKNOWN; + } + } +#endif +#ifdef JBM_TSM_ON_TCS + } + if ( hIvasDec->hasBeenFedFirstGoodFrame && hVoIP->rendererType != JBM_RENDERER_NONE ) + { + uint16_t nSamplesRendered_loop; + int16_t nSamplesToRender; + if ( hVoIP->hFifoOut ) + { + int16_t rendererPcmBuf[( MAX_OUTPUT_CHANNELS * L_FRAME_MAX * APA_MAX_SCALE ) / 100]; + nSamplesToRender = nSamplesPerChannel - pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoOut ); + /* render IVAS frames */ + if ( ( error = IVAS_DEC_GetRenderedSamples( hIvasDec, nSamplesToRender, &nSamplesRendered_loop, &hVoIP->nSamplesAvailableNext, rendererPcmBuf ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( pcmdsp_fifo_write( hVoIP->hFifoOut, (uint8_t *) rendererPcmBuf, nSamplesRendered_loop ) != 0 ) + { + return IVAS_ERR_UNKNOWN; + } + } + else + { + nSamplesToRender = nSamplesPerChannel - nSamplesRendered; + /* render IVAS frames directly to the output buffer */ + if ( ( error = IVAS_DEC_GetRenderedSamples( hIvasDec, nSamplesToRender, &nSamplesRendered_loop, &hVoIP->nSamplesAvailableNext, pcmBuf + nSamplesRendered * nOutChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + } + nSamplesRendered += nSamplesRendered_loop; +#ifdef VARIABLE_SPEED_DECODING + if ( hVoIP->mode == IVAS_DEC_VOIP_MODE_VARIABLE_SPEED && hVoIP->nSamplesAvailableNext == 0 ) + { + hVoIP->needNewFrame = true; + } +#endif + } + else if ( !hIvasDec->hasBeenFedFirstGoodFrame && hVoIP->hFifoOut == NULL ) + { + hVoIP->nSamplesAvailableNext = 0; + } + else { - /* write JBM trace data entry */ - store_JbmData( hVoIP, dataUnit, systemTimestamp_ms, extBufferedSamples, hDecoderConfig->output_Fs ); - if ( ( jbmWriterFn( &hVoIP->JbmTraceData, jbmWriter ) ) != IVAS_ERR_OK ) + hVoIP->nSamplesAvailableNext = max( 0, pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoOut ) - nSamplesPerChannel ); +#ifdef VARIABLE_SPEED_DECODING + if ( hVoIP->mode == IVAS_DEC_VOIP_MODE_VARIABLE_SPEED && hVoIP->nSamplesAvailableNext < nSamplesPerChannel ) { - fprintf( stderr, "\nError writing JBM Trace data to file\n" ); - return IVAS_ERR_UNKNOWN; + hVoIP->needNewFrame = true; } +#endif + hVoIP->nSamplesAvailableNext = 0; } #endif } /* fetch a user-specified number of samples from FIFO */ +#if defined( JBM_TSM_ON_TCS ) + if ( hVoIP->hFifoOut ) + { + if ( pcmdsp_fifo_read( hVoIP->hFifoOut, nSamplesPerChannel, (uint8_t *) pcmBuf ) != 0 ) +#else if ( pcmdsp_fifo_read( hVoIP->hFifoAfterTimeScaler, nSamplesPerChannel, (uint8_t *) pcmBuf ) != 0 ) +#endif + { + return IVAS_ERR_UNKNOWN; + } +#ifdef JBM_TSM_ON_TCS + } +#endif + +#if defined( JBM_TSM_ON_TCS ) || defined( VARIABLE_SPEED_DECODING ) +#ifdef JBM_TSM_ON_TCS + *sampleAvailableNext = hVoIP->nSamplesAvailableNext; +#else + *sampleAvailableNext = max( 0, pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoAfterTimeScaler ) ); +#ifdef VARIABLE_SPEED_DECODING + if ( hVoIP->mode == IVAS_DEC_VOIP_MODE_VARIABLE_SPEED ) { - return IVAS_ERR_UNKNOWN; + if ( *sampleAvailableNext < nSamplesPerChannel ) + { + hVoIP->needNewFrame = true; + } + } +#endif +#endif +#endif + + return error; +} + +/*---------------------------------------------------------------------* + * IVAS_DEC_VoIP_Flush( ) + * + * Function to flush remaining audio in VoIP + *---------------------------------------------------------------------*/ + +#if defined( VARIABLE_SPEED_DECODING ) || defined( JBM_TSM_ON_TCS ) +ivas_error IVAS_DEC_VoIP_Flush( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const int16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ + int16_t *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 */ + uint16_t *nSamplesAvailableNext, /* o : number of samples still available */ + int16_t *nSamplesFlushed /* o : number of samples flushed */ +) +{ + ivas_error error; + IVAS_DEC_VOIP *hVoIP; +#ifdef JBM_TSM_ON_TCS + int16_t rendererPcmBuf[( MAX_OUTPUT_CHANNELS * L_FRAME_MAX * APA_MAX_SCALE ) / 100]; + uint16_t nSamplesToRender; + uint16_t nSamplesFlushedLocal; +#endif + error = IVAS_ERR_OK; + + hVoIP = hIvasDec->hVoIP; +#if defined( JBM_TSM_ON_TCS ) + *nSamplesFlushed = min( nSamplesPerChannel, hVoIP->nSamplesAvailableNext ); +#else + *nSamplesFlushed = min( nSamplesPerChannel, pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoAfterTimeScaler ) ); +#endif +#ifdef JBM_TSM_ON_TCS + if ( hVoIP->rendererType == JBM_RENDERER_NONE ) + { +#endif + /* fetch a user-specified number of samples from FIFO */ +#if defined( JBM_TSM_ON_TCS ) + if ( pcmdsp_fifo_read( hVoIP->hFifoOut, *nSamplesFlushed, (uint8_t *) pcmBuf ) != 0 ) +#else + if ( pcmdsp_fifo_read( hVoIP->hFifoAfterTimeScaler, *nSamplesFlushed, (uint8_t *) pcmBuf ) != 0 ) +#endif + { + return IVAS_ERR_UNKNOWN; + } +#if defined( JBM_TSM_ON_TCS ) + hVoIP->nSamplesAvailableNext -= *nSamplesFlushed; + *nSamplesAvailableNext = hVoIP->nSamplesAvailableNext; +#else + *nSamplesAvailableNext = pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoAfterTimeScaler ); +#endif +#ifdef JBM_TSM_ON_TCS } + else + { + nSamplesToRender = (uint16_t) *nSamplesFlushed; + /* render IVAS frames */ + if ( ( error = IVAS_DEC_GetRenderedSamples( hIvasDec, nSamplesToRender, &nSamplesFlushedLocal, &hVoIP->nSamplesAvailableNext, rendererPcmBuf ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( pcmdsp_fifo_write( hVoIP->hFifoOut, (uint8_t *) rendererPcmBuf, nSamplesFlushedLocal ) != 0 ) + { + return IVAS_ERR_UNKNOWN; + } + if ( pcmdsp_fifo_read( hVoIP->hFifoOut, nSamplesFlushedLocal, (uint8_t *) pcmBuf ) != 0 ) + { + return IVAS_ERR_UNKNOWN; + } + *nSamplesAvailableNext = hVoIP->nSamplesAvailableNext; + *nSamplesFlushed = (int16_t) nSamplesFlushedLocal; + } +#endif return error; } +#endif /*---------------------------------------------------------------------* @@ -1649,9 +2331,17 @@ ivas_error IVAS_DEC_VoIP_GetSamples( bool IVAS_DEC_VoIP_IsEmpty( IVAS_DEC_HANDLE hIvasDec /* i/o: IVAS decoder handle */ +#ifdef JBM_TSM_ON_TCS + , + int16_t nSamplesAsked +#endif ) { +#ifdef JBM_TSM_ON_TCS + return ( ( JB4_bufferedDataUnits( hIvasDec->hVoIP->hJBM ) == 0 ) && ( hIvasDec->hVoIP->nSamplesAvailableNext < nSamplesAsked ) ); +#else return JB4_bufferedDataUnits( hIvasDec->hVoIP->hJBM ) == 0; +#endif } @@ -1692,8 +2382,11 @@ static void IVAS_DEC_Close_VoIP( apa_exit( &hVoIP->hTimeScaler ); +#ifdef JBM_TSM_ON_TCS + pcmdsp_fifo_destroy( &hVoIP->hFifoOut ); +#else pcmdsp_fifo_destroy( &hVoIP->hFifoAfterTimeScaler ); - +#endif if ( hVoIP->apaExecBuffer != NULL ) { free( hVoIP->apaExecBuffer ); @@ -2166,12 +2859,19 @@ void IVAS_DEC_PrintDisclaimer( void ) static ivas_error evs_dec_main( Decoder_Struct *st_ivas, const int16_t nOutSamples, +#ifdef JBM_TSM_ON_TCS + float *floatBuf, +#endif int16_t *pcmBuf ) { DEC_CORE_HANDLE *hCoreCoder; #ifdef NON_DIEGETIC_PAN float output[MAX_OUTPUT_CHANNELS_IN_DIEGETIC_PAN][L_FRAME48k]; float mixer_left, mixer_rigth; +#ifdef JBM_TSM_ON_TCS + float *p_output[MAX_OUTPUT_CHANNELS_IN_DIEGETIC_PAN]; + int16_t ch; +#endif #else float output[L_FRAME48k]; #endif @@ -2184,6 +2884,13 @@ static ivas_error evs_dec_main( mdct_switching_dec( hCoreCoder[0] ); +#ifdef JBM_TSM_ON_TCS + for ( ch = 0; ch < MAX_OUTPUT_CHANNELS_IN_DIEGETIC_PAN; ch++ ) + { + p_output[ch] = output[ch]; + } +#endif + /* run the main EVS decoding routine */ if ( hCoreCoder[0]->codec_mode == MODE1 ) { @@ -2259,16 +2966,46 @@ static ivas_error evs_dec_main( } #endif - /* convert 'float' output data to 'short' */ +#ifdef JBM_TSM_ON_TCS + if ( floatBuf != NULL ) + { + /* BE workaround */ + int16_t pcm_buf_local[L_FRAME48k]; + + + /* convert 'float' output data to 'short' */ #ifdef DEBUGGING - st_ivas->noClipping += + st_ivas->noClipping += #endif #ifdef NON_DIEGETIC_PAN - ivas_syn_output( output, nOutSamples, st_ivas->hDecoderConfig->nchan_out, pcmBuf ); + ivas_syn_output( p_output, nOutSamples, st_ivas->hDecoderConfig->nchan_out, pcm_buf_local ); +#else + syn_output( output, nOutSamples, pcm_buf_local ); +#endif +#ifdef NON_DIEGETIC_PAN + mvs2r( pcm_buf_local, floatBuf, nOutSamples * st_ivas->hDecoderConfig->nchan_out ); +#else + mvs2r( pcm_buf_local, floatBuf, nOutSamples ); +#endif + } + else + { +#endif +#ifdef DEBUGGING + st_ivas->noClipping += +#endif +#ifdef NON_DIEGETIC_PAN +#ifdef JBM_TSM_ON_TCS + ivas_syn_output( p_output, nOutSamples, st_ivas->hDecoderConfig->nchan_out, pcmBuf ); +#else + ivas_syn_output( output, nOutSamples, st_ivas->hDecoderConfig->nchan_out, pcmBuf ); +#endif #else syn_output( output, nOutSamples, pcmBuf ); #endif - +#ifdef JBM_TSM_ON_TCS + } +#endif return error; } @@ -2459,3 +3196,141 @@ static ivas_error input_format_API_to_internal( return IVAS_ERR_OK; } + +#ifdef JBM_TSM_ON_TCS +static int16_t IVAS_DEC_VoIP_GetRenderGranularity( Decoder_Struct *st_ivas ) +{ + + return st_ivas->hTcBuffer->n_samples_granularity; +} + +static JBM_RENDERER_TYPE IVAS_DEC_VoIP_GetRendererConfig( IVAS_DEC_HANDLE hIvasDec ) +{ + JBM_RENDERER_TYPE rendererType; + rendererType = JBM_RENDERER_NONE; + + if ( hIvasDec->mode == IVAS_DEC_MODE_EVS ) + { + rendererType = JBM_RENDERER_NONE; + } + else + { + rendererType = JBM_RENDERER_IVAS; + } + + return rendererType; +} + +ivas_error IVAS_DEC_VoIP_reconfigure( IVAS_DEC_HANDLE hIvasDec, const uint16_t nTransportChannels, const uint16_t l_ts ) +{ + + IVAS_DEC_VOIP *hVoIP; + ivas_error error; + + + hVoIP = hIvasDec->hVoIP; + + if ( hIvasDec->hVoIP->hTimeScaler == NULL ) + { + + uint16_t wss, css; + float startQuality; + DECODER_CONFIG_HANDLE hDecoderConfig; + +#ifdef VARIABLE_SPEED_DECODING + startQuality = hVoIP->mode == IVAS_DEC_VOIP_MODE_VARIABLE_SPEED ? -2.0f : 1.0f; +#else + startQuality = 1.0f; +#endif + /* get current renderer type*/ + hVoIP->rendererType = IVAS_DEC_VoIP_GetRendererConfig( hIvasDec ); + hDecoderConfig = hIvasDec->st_ivas->hDecoderConfig; + if ( hDecoderConfig->output_Fs == 8000 ) + { + wss = 1; + css = 1; + } + else if ( hDecoderConfig->output_Fs == 16000 ) + { + wss = 2; + css = 1; + } + else if ( hDecoderConfig->output_Fs == 32000 ) + { + wss = 4; + css = 2; + } + else if ( hDecoderConfig->output_Fs == 48000 ) + { + wss = 6; + css = 3; + } + else + { + return IVAS_ERR_INIT_ERROR; + } + hIvasDec->hVoIP->apaExecBuffer = malloc( sizeof( float ) * APA_BUF_PER_CHANNEL * nTransportChannels ); + set_zero( hIvasDec->hVoIP->apaExecBuffer, APA_BUF_PER_CHANNEL * nTransportChannels ); + if ( hIvasDec->hVoIP->apaExecBuffer == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate VoIP handle" ); + } + if ( apa_init( &hIvasDec->hVoIP->hTimeScaler, + nTransportChannels ) != IVAS_ERR_OK || + apa_set_rate( hIvasDec->hVoIP->hTimeScaler, hDecoderConfig->output_Fs ) != 0 || + apa_set_complexity_options( hIvasDec->hVoIP->hTimeScaler, wss, css ) != 0 || + apa_set_quality( hIvasDec->hVoIP->hTimeScaler, startQuality, 4, 4 ) != 0 || + apa_set_renderer_granularity( hIvasDec->hVoIP->hTimeScaler, l_ts ) != 0 ) + { + return IVAS_ERR_INIT_ERROR; + } + if ( hVoIP->hFifoOut == NULL && hVoIP->rendererType == JBM_RENDERER_NONE ) + { + /* we still need the FIFO out buffer */ + if ( pcmdsp_fifo_create( &hIvasDec->hVoIP->hFifoOut ) != 0 || + pcmdsp_fifo_init( hIvasDec->hVoIP->hFifoOut, (uint16_t) ( hDecoderConfig->output_Fs * 4 / FRAMES_PER_SEC ) /* 4 frames */, hDecoderConfig->nchan_out, sizeof( int16_t ) ) != 0 ) + { + return IVAS_ERR_INIT_ERROR; + } + } +#ifdef VARIABLE_SPEED_DECODING + else if ( hIvasDec->hVoIP->mode == IVAS_DEC_VOIP_MODE_VARIABLE_SPEED ) + { + if ( pcmdsp_fifo_create( &hIvasDec->hVoIP->hFifoOut ) != 0 || + pcmdsp_fifo_init( hIvasDec->hVoIP->hFifoOut, (uint16_t) ( hDecoderConfig->output_Fs * 4 / FRAMES_PER_SEC ) /* 4 frames */, hDecoderConfig->nchan_out, sizeof( int16_t ) ) != 0 ) + { + return IVAS_ERR_INIT_ERROR; + } + } +#endif + if ( hIvasDec->mode == IVAS_DEC_MODE_EVS ) + { + if ( apa_set_evs_compat_mode( hIvasDec->hVoIP->hTimeScaler, true ) != 0 ) + { + return IVAS_ERR_INIT_ERROR; + } + } + } + else + { + if ( apa_reconfigure( hVoIP->hTimeScaler, nTransportChannels, l_ts ) != 0 ) + { + return IVAS_ERR_INIT_ERROR; + } + + /* realloc apa_exe_buffer */ + free( hIvasDec->hVoIP->apaExecBuffer ); + hIvasDec->hVoIP->apaExecBuffer = malloc( sizeof( float ) * APA_BUF_PER_CHANNEL * nTransportChannels ); + set_zero( hIvasDec->hVoIP->apaExecBuffer, APA_BUF_PER_CHANNEL * nTransportChannels ); + if ( hIvasDec->hVoIP->apaExecBuffer == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate VoIP handle" ); + } + } + hIvasDec->hVoIP->nTransportChannelsOld = (uint8_t) nTransportChannels; + + error = IVAS_ERR_OK; + + return error; +} +#endif diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index 06fc8820ae8537027eb77e76bd98ecc71fdc7fcb..fd8735dda63eff206e85de26e0ab2721dbaa0e41 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -86,6 +86,15 @@ typedef enum _IVAS_DEC_COMPLEXITY_LEVEL } IVAS_DEC_COMPLEXITY_LEVEL; #endif + +#ifdef VARIABLE_SPEED_DECODING +typedef enum +{ + IVAS_DEC_VOIP_MODE_VOIP = 0, + IVAS_DEC_VOIP_MODE_VARIABLE_SPEED = 1 +} IVAS_DEC_VOIP_MODE; +#endif + #ifdef DEBUGGING typedef enum _IVAS_DEC_FORCED_REND_MODE { @@ -217,23 +226,49 @@ ivas_error IVAS_DEC_VoIP_FeedFrame( const bool qBit /* i : Q bit for AMR-WB IO */ ); +#ifdef VARIABLE_SPEED_DECODING +/*! r: error code */ +ivas_error IVAS_DEC_VoIP_SetScale( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const int16_t scale /* i : TSM scale to set */ +); +#endif + /*! r: error code */ ivas_error IVAS_DEC_VoIP_GetSamples( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ uint16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ int16_t *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 */ const uint32_t systemTimestamp_ms /* i : current system timestamp */ +#if defined( JBM_TSM_ON_TCS ) || defined(VARIABLE_SPEED_DECODING ) + , + uint16_t *sampleAvailableNext /* o : samples available for the next call */ +#endif #ifdef SUPPORT_JBM_TRACEFILE , JbmTraceFileWriterFn jbmWriterFn, void* jbmWriter #endif ); +#if defined( JBM_TSM_ON_TCS ) || defined(VARIABLE_SPEED_DECODING ) +ivas_error IVAS_DEC_VoIP_Flush( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const int16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ + int16_t *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 */ + uint16_t *nSamplesAvailableNext, /* o : number of samples still available */ + int16_t *nSamplesFlushed /* o : number of samples flushed */ +); +#endif + /* Setter functions - apply changes to decoder configuration */ /*! r: error code */ ivas_error IVAS_DEC_EnableVoIP( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ +#ifdef VARIABLE_SPEED_DECODING + const IVAS_DEC_VOIP_MODE voipMode, /* i : VoIP or varable speed */ + const uint16_t speedFac, /* i : speed factor for varable speed */ +#endif const int16_t jbmSafetyMargin, /* i : allowed delay reserve for JBM, in milliseconds */ const IVAS_DEC_INPUT_FORMAT inputFormat /* i : format of the input bitstream */ ); @@ -349,6 +384,10 @@ ivas_error IVAS_DEC_GetPcmFrameSize( /*! r: true if decoder has no data in VoIP jitter buffer */ bool IVAS_DEC_VoIP_IsEmpty( IVAS_DEC_HANDLE hIvasDec /* i/o: IVAS decoder handle */ +#ifdef JBM_TSM_ON_TCS + , + int16_t nSamplesAsked +#endif ); ivas_error IVAS_DEC_VoIP_Get_CA_offset( diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c index c05ae7c2626401afd599719743834488a63786fd..a7572aea3fe8d0e2bd0663d981ce9e67d6e9f01b 100644 --- a/lib_rend/ivas_crend.c +++ b/lib_rend/ivas_crend.c @@ -939,8 +939,13 @@ static ivas_error ivas_rend_crendConvolver( const CREND_WRAPPER *pCrend, IVAS_REND_AudioConfig inConfig, IVAS_REND_AudioConfig outConfig, +#ifdef JBM_TSM_ON_TCS + float *pcm_in[], + float *pcm_out[], +#else float pcm_in[][L_FRAME48k], float pcm_out[][L_FRAME48k], +#endif const int32_t output_Fs, const int16_t i_ts ) { @@ -1105,12 +1110,19 @@ ivas_error ivas_rend_crendProcess( HEAD_TRACK_DATA_HANDLE hHeadTrackData, IVAS_OUTPUT_SETUP_HANDLE hIntSetup, EFAP_HANDLE hEFAPdata, +#ifdef JBM_TSM_ON_TCS + float *output[], /* i/o: input/output audio channels */ +#else float output[][L_FRAME48k], /* i/o: input/output audio channels */ +#endif const int32_t output_Fs ) { int16_t i, subframe_idx, output_frame, subframe_len; int16_t nchan_out; float pcm_tmp[BINAURAL_CHANNELS][L_FRAME48k]; +#ifdef JBM_TSM_ON_TCS + float *p_pcm_tmp[BINAURAL_CHANNELS]; +#endif AUDIO_CONFIG in_config; IVAS_REND_AudioConfigType inConfigType; ivas_error error; @@ -1133,6 +1145,12 @@ ivas_error ivas_rend_crendProcess( output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); subframe_len = output_frame / MAX_PARAM_SPATIAL_SUBFRAMES; +#ifdef JBM_TSM_ON_TCS + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + p_pcm_tmp[i] = pcm_tmp[i]; + } +#endif for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ ) { if ( hDecoderConfig && hDecoderConfig->Opt_Headrotation && hHeadTrackData && hHeadTrackData->num_quaternions >= 0 ) @@ -1156,14 +1174,22 @@ ivas_error ivas_rend_crendProcess( if ( ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) || ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) ) { +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_rend_crendConvolver( pCrend, inRendConfig, outRendConfig, output, p_pcm_tmp, output_Fs, subframe_idx ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_rend_crendConvolver( pCrend, inRendConfig, outRendConfig, output, pcm_tmp, output_Fs, subframe_idx ) ) != IVAS_ERR_OK ) +#endif { return error; } if ( pCrend->hCrend->hReverb != NULL ) { +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_reverb_process( pCrend->hCrend->hReverb, in_config, 1, output, p_pcm_tmp, subframe_idx ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_reverb_process( pCrend->hCrend->hReverb, in_config, 1, output, pcm_tmp, subframe_idx ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1185,3 +1211,130 @@ ivas_error ivas_rend_crendProcess( return IVAS_ERR_OK; } + +#ifdef JBM_TSM_ON_TCS +ivas_error ivas_rend_crendProcessSubframe( + const CREND_WRAPPER *pCrend, + const AUDIO_CONFIG inConfig, + const AUDIO_CONFIG outConfig, + DECODER_CONFIG_HANDLE hDecoderConfig, + HEAD_TRACK_DATA_HANDLE hHeadTrackData, + IVAS_OUTPUT_SETUP_HANDLE hIntSetup, + EFAP_HANDLE hEFAPdata, + DECODER_TC_BUFFER_HANDLE hTcBuffer, + float *input_f[], + float *output[], /* i/o: input/output audio channels */ + const int16_t n_samples_to_render, + const int32_t output_Fs ) +{ + int16_t subframe_idx, subframe_len; + int16_t nchan_out, nchan_in, ch, first_sf, last_sf, slot_size, slots_to_render; + float *tc_local[MAX_TRANSPORT_CHANNELS]; + float pcm_tmp[BINAURAL_CHANNELS][L_FRAME48k]; + float *p_pcm_tmp[BINAURAL_CHANNELS]; + AUDIO_CONFIG in_config; + IVAS_REND_AudioConfigType inConfigType; + ivas_error error; + IVAS_REND_AudioConfig inRendConfig; + IVAS_REND_AudioConfig outRendConfig; + + push_wmops( "ivas_rend_crendProcessSubframe" ); + + inRendConfig = getRendAudioConfigFromIvasAudioConfig( inConfig ); + outRendConfig = getRendAudioConfigFromIvasAudioConfig( outConfig ); + + in_config = getIvasAudioConfigFromRendAudioConfig( inRendConfig ); + inConfigType = getAudioConfigType( inRendConfig ); + if ( ( error = getAudioConfigNumChannels( outRendConfig, &nchan_out ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( ( error = getAudioConfigNumChannels( inRendConfig, &nchan_in ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( ch = 0; ch < nchan_in; ch++ ) + { + tc_local[ch] = input_f[ch]; + } + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + p_pcm_tmp[ch] = pcm_tmp[ch]; + } + + slot_size = hTcBuffer->n_samples_granularity; + /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ + slots_to_render = min( hTcBuffer->num_slots - hTcBuffer->slots_rendered, n_samples_to_render / slot_size ); + first_sf = hTcBuffer->subframes_rendered; + last_sf = first_sf; + hTcBuffer->slots_rendered += slots_to_render; + while ( slots_to_render > 0 ) + { + slots_to_render -= hTcBuffer->subframe_nbslots[last_sf]; + last_sf++; + } + + for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + { + subframe_len = hTcBuffer->subframe_nbslots[subframe_idx] * hTcBuffer->n_samples_granularity; + if ( hDecoderConfig && hDecoderConfig->Opt_Headrotation && hHeadTrackData && hHeadTrackData->num_quaternions >= 0 ) + { + + /* Rotation in SHD for: + MC with elevation (5_1_2 / 5_1_4 / 7_1_4) -> BINAURAL + SBA SPAR -> BINAURAL or BINAURAL_ROOM + */ + if ( in_config == AUDIO_CONFIG_FOA || in_config == AUDIO_CONFIG_HOA2 || in_config == AUDIO_CONFIG_HOA3 ) + { + rotateFrame_shd( hHeadTrackData, tc_local, subframe_len, *hIntSetup, 0 ); + } + /* Rotation in SD for MC -> BINAURAL_ROOM */ + else if ( ( hIntSetup != NULL ) && hIntSetup->is_loudspeaker_setup ) + { + rotateFrame_sd( hHeadTrackData, tc_local, subframe_len, *hIntSetup, hEFAPdata, 0 ); + } + } + + if ( ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) || ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) ) + { + if ( ( error = ivas_rend_crendConvolver( pCrend, inRendConfig, outRendConfig, tc_local, p_pcm_tmp, output_Fs, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( pCrend->hCrend->hReverb != NULL ) + { + if ( ( error = ivas_reverb_process( pCrend->hCrend->hReverb, in_config, 1, tc_local, p_pcm_tmp, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + for ( ch = 0; ch < nchan_in; ch++ ) + { + tc_local[ch] += subframe_len; + } + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + p_pcm_tmp[ch] += subframe_len; + } + } + else + { + return IVAS_ERR_INVALID_INPUT_FORMAT; + } + } + + /* move to output */ + for ( ch = 0; ch < nchan_out; ch++ ) + { + mvr2r( pcm_tmp[ch], output[ch], n_samples_to_render ); + } + + + hTcBuffer->subframes_rendered = last_sf; + pop_wmops(); + + return IVAS_ERR_OK; +} +#endif diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index d212517d0803ac1bd01ddc39ca07e823ca40a451..06fd160bb2819cdb9c10a65cfa6b668ff536592b 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -71,8 +71,11 @@ *------------------------------------------------------------------------*/ #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS +#ifdef JBM_TSM_ON_TCS +static void ivas_dirac_dec_binaural_internal( Decoder_Struct *st_ivas, float *output_f[], const int16_t nchan_transport, const int16_t subframe ); +#else static void ivas_dirac_dec_binaural_internal( Decoder_Struct *st_ivas, float output_f[][L_FRAME48k], const int16_t nchan_transport, const int16_t subframe ); - +#endif static void ivas_dirac_dec_decorrelate_slot( DIRAC_DEC_HANDLE hDirAC, const int16_t slot, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float decRe[][CLDFB_NO_CHANNELS_MAX], float decIm[][CLDFB_NO_CHANNELS_MAX] ); static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( Decoder_Struct *st_ivas, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float Rmat[3][3], const int16_t subframe ); @@ -87,11 +90,20 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric static void ivas_dirac_dec_binaural_determine_processing_matrices( Decoder_Struct *st_ivas, const int16_t max_band_decorr, float Rmat[3][3] ); #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS +#ifdef JBM_TSM_ON_TCS +static void ivas_dirac_dec_binaural_process_output( Decoder_Struct *st_ivas, float *output_f[], float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, const int16_t numInChannels, const int16_t subframe ); + +static void adaptTransportSignalsHeadtracked( HEAD_TRACK_DATA_HANDLE hHeadTrackData, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nBins, const int16_t nSlots, float Rmat[3][3] ); + +static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( HEAD_TRACK_DATA_HANDLE hHeadTrackData, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nBins, const int16_t nSlots, float Rmat[3][3] ); +#else static void ivas_dirac_dec_binaural_process_output( Decoder_Struct *st_ivas, float output_f[][L_FRAME48k], float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, const int16_t numInChannels, const int16_t subframe ); static void adaptTransportSignalsHeadtracked( HEAD_TRACK_DATA_HANDLE hHeadTrackData, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nBins, float Rmat[3][3] ); static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( HEAD_TRACK_DATA_HANDLE hHeadTrackData, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nBins, float Rmat[3][3] ); +#endif + #else static void ivas_dirac_dec_binaural_process_output( Decoder_Struct *st_ivas, float output_f[][L_FRAME48k], float inRe[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, const uint8_t numInputChannels, const uint8_t firstSlot, const uint8_t slotEnd ); @@ -115,6 +127,19 @@ static void matrixTransp2Mul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], f static float configure_reqularization_factor( const IVAS_FORMAT ivas_format, const int32_t ivas_brate ); #endif +#ifdef JBM_TSM_ON_TCS +#ifndef FIX_355_REFACTOR_PARAMBIN_TO_5MS +static void ivas_dirac_dec_binaural_process_output_sf( Decoder_Struct *st_ivas, float *output_f[], float inRe[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, const uint8_t numInChannels ); + +static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_sf( HEAD_TRACK_DATA_HANDLE hHeadTrackData, float inIm[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inRe[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const uint8_t slotEnd, const uint8_t nBins, float Rmat[3][3] ); + +static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices_sf( Decoder_Struct *st_ivas, float inRe[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], int16_t azimuth[CLDFB_NO_CHANNELS_MAX], int16_t elevation[CLDFB_NO_CHANNELS_MAX], float energy_ratio1[CLDFB_NO_CHANNELS_MAX], float spreadCoherence[CLDFB_NO_CHANNELS_MAX], float surroundingCoherence[CLDFB_NO_CHANNELS_MAX], float Rmat[3][3] ); + +static void ivas_dirac_dec_binaural_internal_sf( Decoder_Struct *st_ivas, float *output_f[], const int16_t nchan_transport ); + +static void ivas_dirac_dec_decorrelate_slot_sf( DIRAC_DEC_HANDLE hDirAC, const int8_t slot, float inRe[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float decRe[][CLDFB_NO_CHANNELS_MAX], float decIm[][CLDFB_NO_CHANNELS_MAX] ); +#endif +#endif /*------------------------------------------------------------------------- * ivas_dirac_dec_init_binaural_data() * @@ -236,14 +261,27 @@ ivas_error ivas_dirac_dec_init_binaural_data( if ( hBinaural->hReverb == NULL ) { +#if defined( JBM_TSM_ON_TCS ) && !defined( FIX_355_REFACTOR_PARAMBIN_TO_5MS ) + int16_t reverbBlockSize = st_ivas->hDecoderConfig->voip_active ? 1 : CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; + if ( ( error = ivas_binaural_reverb_open( &hBinaural->hReverb, + nBins, + reverbBlockSize, NULL, + st_ivas->hIntSetup.output_config, + output_Fs, + RENDERER_BINAURAL_PARAMETRIC_ROOM, + st_ivas->hHrtfFastConv, + st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + +#else if ( ( error = ivas_binaural_reverb_open( &hBinaural->hReverb, nBins, - CLDFB_SLOTS_PER_SUBFRAME, NULL, + CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, st_ivas->hIntSetup.output_config, output_Fs, RENDERER_BINAURAL_PARAMETRIC_ROOM, st_ivas->hHrtfFastConv, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -260,6 +298,18 @@ ivas_error ivas_dirac_dec_init_binaural_data( { if ( hBinaural->useSubframeMode ) { +#ifdef JBM_TSM_ON_TCS + reverbBlockSize = st_ivas->hDecoderConfig->voip_active ? 1 : CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; + if ( ( error = ivas_binaural_reverb_open( &hBinaural->hReverb, + nBins, + reverbBlockSize, NULL, + st_ivas->hIntSetup.output_config, + output_Fs, + RENDERER_BINAURAL_PARAMETRIC_ROOM, + st_ivas->hHrtfFastConv, + st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + +#else if ( ( error = ivas_binaural_reverb_open( &hBinaural->hReverb, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, @@ -268,6 +318,7 @@ ivas_error ivas_dirac_dec_init_binaural_data( RENDERER_BINAURAL_PARAMETRIC_ROOM, st_ivas->hHrtfFastConv, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -345,6 +396,21 @@ ivas_error ivas_dirac_dec_init_binaural_data( st_ivas->hDiracDecBin = hBinaural; +#ifdef JBM_TSM_ON_TCS + /* allocate transport channels*/ + if ( st_ivas->hDecoderConfig->voip_active == 1 && st_ivas->hTcBuffer == NULL ) + { + int16_t nchan_to_allocate; + + nchan_to_allocate = 2 * BINAURAL_CHANNELS; + if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, TC_BUFFER_MODE_RENDERER, ivas_jbm_dec_get_num_tc_channels( st_ivas ), nchan_to_allocate, nchan_to_allocate, NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + +#endif /* JBM_TMS_ON_TCS*/ + return IVAS_ERR_OK; } @@ -423,6 +489,68 @@ ivas_error ivas_dirac_dec_binaural_copy_hrtfs( return IVAS_ERR_OK; } +#ifdef JBM_TSM_ON_TCS +void ivas_dirac_dec_binaural_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ + uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ + uint16_t *nSamplesAvailable, /* o : number of CLDFB slots still to render */ + const int16_t nchan_transport, + float *output_f[] /* o : rendered time signal */ +) +{ + int16_t slots_to_render, first_sf, last_sf, subframe_idx; + uint16_t slot_size, ch; + uint16_t nchan_out; + DIRAC_DEC_HANDLE hDirAC; + float *output_f_local[MAX_OUTPUT_CHANNELS]; + + hDirAC = st_ivas->hDirAC; + nchan_out = BINAURAL_CHANNELS; +#ifdef DEBUGGING + assert( hDirAC ); +#endif + for ( ch = 0; ch < nchan_out; ch++ ) + { + output_f_local[ch] = output_f[ch]; + } + slot_size = NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); + /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ + slots_to_render = min( hDirAC->num_slots - hDirAC->slots_rendered, nSamplesAsked / slot_size ); + *nSamplesRendered = slots_to_render * slot_size; + first_sf = hDirAC->subframes_rendered; + last_sf = first_sf; + while ( slots_to_render > 0 ) + { + slots_to_render -= hDirAC->subframe_nbslots[last_sf]; + last_sf++; + } +#ifdef DEBUGGING + assert( slots_to_render == 0 ); +#endif + for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + { + int16_t n_samples_sf = slot_size * hDirAC->subframe_nbslots[subframe_idx]; +#ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS + ivas_dirac_dec_binaural_internal( st_ivas, output_f_local, nchan_transport, subframe_idx ); +#else + ivas_dirac_dec_binaural_internal_sf( st_ivas, output_f_local, nchan_transport ); +#endif + for ( ch = 0; ch < nchan_out; ch++ ) + { + output_f_local[ch] += n_samples_sf; + } + } + if ( hDirAC->slots_rendered == hDirAC->num_slots ) + { + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % st_ivas->hDirAC->dirac_md_buffer_length; + } + *nSamplesAvailable = ( hDirAC->num_slots - hDirAC->slots_rendered ) * slot_size; + + return; +} +#endif + /*------------------------------------------------------------------------- * ivas_dirac_dec_binaural() * @@ -437,27 +565,84 @@ void ivas_dirac_dec_binaural( { #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS int16_t subframe; +#endif +#ifdef JBM_TSM_ON_TCS + float cng_td_buffer[L_FRAME16k]; + float *p_output[MAX_OUTPUT_CHANNELS]; + int16_t ch; + int16_t slot_size; + int16_t numInChannels; + + slot_size = NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); + for ( ch = 0; ch < 2 * BINAURAL_CHANNELS; ch++ ) + { + p_output[ch] = &output_f[ch][0]; + } + numInChannels = nchan_transport; + if ( st_ivas->hOutSetup.separateChannelEnabled ) + { + numInChannels++; + } + for ( ch = 0; ch < numInChannels; ch++ ) + { + st_ivas->hTcBuffer->tc[ch] = &output_f[ch][0]; + } + + ivas_dirac_dec_set_md_map( st_ivas, DEFAULT_JBM_CLDFB_TIMESLOTS ); + if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR ) + { + ivas_spar_dec_set_render_map( st_ivas, DEFAULT_JBM_CLDFB_TIMESLOTS ); + } #endif + if ( st_ivas->hDiracDecBin->useTdDecorr ) { float *decorr_signal[BINAURAL_CHANNELS]; +#ifndef JBM_TSM_ON_TCS int16_t ch; +#endif int16_t output_frame; for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { decorr_signal[ch] = (float *) &( output_f[ch + BINAURAL_CHANNELS][0] ); +#ifdef JBM_TSM_ON_TCS + st_ivas->hTcBuffer->tc[ch + BINAURAL_CHANNELS] = decorr_signal[ch]; +#endif } output_frame = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ); - +#ifdef JBM_TSM_ON_TCS + { + ivas_td_decorr_process( st_ivas->hDiracDecBin->hTdDecorr, p_output, decorr_signal, output_frame ); + } +#else ivas_td_decorr_process( st_ivas->hDiracDecBin->hTdDecorr, output_f, decorr_signal, output_frame ); +#endif + } +#ifdef JBM_TSM_ON_TCS + if ( nchan_transport == 1 && st_ivas->nchan_transport != 2 && st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ) + { + Decoder_State *st = st_ivas->hSCE[0]->hCoreCoder[0]; + st_ivas->hTcBuffer->tc[nchan_transport] = &cng_td_buffer[0]; + generate_masking_noise_lb_dirac( st->hFdCngDec->hFdCngCom, st_ivas->hTcBuffer->tc[nchan_transport], DEFAULT_JBM_CLDFB_TIMESLOTS, st->cna_dirac_flag && st->flag_cna ); } +#endif #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS for ( subframe = 0; subframe < MAX_PARAM_SPATIAL_SUBFRAMES; subframe++ ) { +#ifdef JBM_TSM_ON_TCS + int16_t n_samples_sf = slot_size * st_ivas->hDirAC->subframe_nbslots[subframe]; + ivas_dirac_dec_binaural_internal( st_ivas, p_output, nchan_transport, subframe ); + for ( ch = 0; ch < 2 * BINAURAL_CHANNELS; ch++ ) + { + p_output[ch] += n_samples_sf; + } + st_ivas->hDirAC->dirac_read_idx = ( st_ivas->hDirAC->dirac_read_idx + 1 ) % st_ivas->hDirAC->dirac_md_buffer_length; +#else ivas_dirac_dec_binaural_internal( st_ivas, output_f, nchan_transport, subframe ); +#endif } #else if ( st_ivas->hDiracDecBin->useSubframeMode ) @@ -473,7 +658,12 @@ void ivas_dirac_dec_binaural( ivas_dirac_dec_binaural_internal( st_ivas, output_f, nchan_transport, 0u, (uint8_t) MAX_PARAM_SPATIAL_SUBFRAMES ); } #endif - +#ifdef JBM_TSM_ON_TCS + for ( ch = 0; ch < 2 * BINAURAL_CHANNELS; ch++ ) + { + st_ivas->hTcBuffer->tc[ch] = NULL; + } +#endif return; } @@ -481,26 +671,31 @@ void ivas_dirac_dec_binaural( /*------------------------------------------------------------------------- * Local functions *------------------------------------------------------------------------*/ - -#ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS -static void ivas_dirac_dec_binaural_internal( +#ifdef JBM_TSM_ON_TCS +#ifndef FIX_355_REFACTOR_PARAMBIN_TO_5MS +static void ivas_dirac_dec_binaural_internal_sf( Decoder_Struct *st_ivas, - float output_f[][L_FRAME48k], - const int16_t nchan_transport, - const int16_t subframe ) + float *output_f[], + const int16_t nchan_transport ) { DIRAC_DEC_HANDLE hDirAC; - int16_t slot, ch, numInChannels; - float Cldfb_RealBuffer_in[4][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer_in[4][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + uint8_t slot, ch, nBins, numInChannels; + float Cldfb_RealBuffer_in[2 * BINAURAL_CHANNELS][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_in[2 * BINAURAL_CHANNELS][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + /* local copies of azi, ele, diffuseness */ + int16_t azimuth[CLDFB_NO_CHANNELS_MAX]; + int16_t elevation[CLDFB_NO_CHANNELS_MAX]; + float spreadCoherence[CLDFB_NO_CHANNELS_MAX]; + float surroundingCoherence[CLDFB_NO_CHANNELS_MAX]; + float energy_ratio1[CLDFB_NO_CHANNELS_MAX]; float Rmat[3][3]; + uint16_t subframe_idx, slot_idx_start; int16_t max_band_decorr; DIFFUSE_DISTRIBUTION_DATA diffuseDistData; - int16_t nBins, offsetSamples; + hDirAC = st_ivas->hDirAC; - nBins = hDirAC->num_freq_bands; - offsetSamples = subframe * CLDFB_SLOTS_PER_SUBFRAME * nBins; + nBins = (uint8_t) hDirAC->num_freq_bands; /* The input channel number at this processing function (not nchan_transport) */ numInChannels = BINAURAL_CHANNELS; @@ -521,14 +716,24 @@ static void ivas_dirac_dec_binaural_internal( Rmat[2][1] = 0.0f; Rmat[2][2] = 1.0f; + slot_idx_start = hDirAC->slots_rendered; + subframe_idx = hDirAC->subframes_rendered; + + /* copy parameters into local buffers*/ + mvs2s( hDirAC->azimuth[hDirAC->render_to_md_map[subframe_idx]], azimuth, hDirAC->num_freq_bands ); + mvs2s( hDirAC->elevation[hDirAC->render_to_md_map[subframe_idx]], elevation, hDirAC->num_freq_bands ); + mvr2r( hDirAC->spreadCoherence[hDirAC->render_to_md_map[subframe_idx]], spreadCoherence, hDirAC->num_freq_bands ); + mvr2r( hDirAC->surroundingCoherence[hDirAC->render_to_md_map[subframe_idx]], surroundingCoherence, hDirAC->num_freq_bands ); + mvr2r( hDirAC->energy_ratio1[hDirAC->render_to_md_map[subframe_idx]], energy_ratio1, hDirAC->num_freq_bands ); + /* CLDFB Analysis of input */ - for ( slot = 0; slot < CLDFB_SLOTS_PER_SUBFRAME; slot++ ) + for ( slot = 0; slot < hDirAC->subframe_nbslots[hDirAC->subframes_rendered]; slot++ ) { for ( ch = 0; ch < numInChannels; ch++ ) { if ( ch == 0 || nchan_transport == 2 ) { - cldfbAnalysis_ts( &( output_f[ch][nBins * slot + offsetSamples] ), + cldfbAnalysis_ts( &( st_ivas->hTcBuffer->tc[ch][nBins * ( slot + slot_idx_start )] ), Cldfb_RealBuffer_in[ch][slot], Cldfb_ImagBuffer_in[ch][slot], nBins, st_ivas->cldfbAnaDec[ch] ); @@ -545,16 +750,15 @@ static void ivas_dirac_dec_binaural_internal( if ( st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ) { int16_t numCoreBands, b; - int16_t slotInFrame; numCoreBands = st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->numCoreBands; - slotInFrame = subframe * CLDFB_SLOTS_PER_SUBFRAME + slot; + generate_masking_noise_dirac( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom, st_ivas->cldfbAnaDec[1], - &( output_f[1][L_FRAME48k - L_FRAME16k] ), /*used as temporary static buffer for the whole frame*/ + st_ivas->hTcBuffer->tc[nchan_transport], Cldfb_RealBuffer_in[2][slot], Cldfb_ImagBuffer_in[2][slot], - slotInFrame, + slot + slot_idx_start, st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna, ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ); @@ -562,7 +766,7 @@ static void ivas_dirac_dec_binaural_internal( st_ivas->cldfbAnaDec[1], /*nothing will be analyzed, just get cnst*/ NULL, Cldfb_RealBuffer_in[1][slot], Cldfb_ImagBuffer_in[1][slot], - slotInFrame, + slot + slot_idx_start, st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna, ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ); @@ -604,7 +808,7 @@ static void ivas_dirac_dec_binaural_internal( { for ( ch = BINAURAL_CHANNELS; ch < ( 2 * BINAURAL_CHANNELS ); ch++ ) { - cldfbAnalysis_ts( &( output_f[ch][nBins * slot + offsetSamples] ), + cldfbAnalysis_ts( &( st_ivas->hTcBuffer->tc[ch][nBins * ( slot + slot_idx_start )] ), Cldfb_RealBuffer_in[ch][slot], Cldfb_ImagBuffer_in[ch][slot], nBins, st_ivas->cldfbAnaDec[ch] ); @@ -621,25 +825,26 @@ static void ivas_dirac_dec_binaural_internal( if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR ) { st_ivas->hDirAC->hDiffuseDist = &diffuseDistData; + ivas_spar_param_to_masa_param_mapping_sf( st_ivas, azimuth, elevation, energy_ratio1, spreadCoherence, surroundingCoherence, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in ); - ivas_spar_param_to_masa_param_mapping( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe ); + ivas_sba_prototype_renderer_sf( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in ); - ivas_sba_prototype_renderer( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe ); + /* we are done with SPAR, update SPAR info*/ + st_ivas->hSpar->slots_rendered += st_ivas->hSpar->subframe_nbslots[st_ivas->hSpar->subframes_rendered]; + st_ivas->hSpar->subframes_rendered++; } if ( st_ivas->hHeadTrackData && st_ivas->hHeadTrackData->num_quaternions >= 0 ) { - QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[subframe], Rmat ); + QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[subframe_idx], Rmat ); if ( nchan_transport == 2 ) { - adaptTransportSignalsHeadtracked( st_ivas->hHeadTrackData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, Rmat ); - - ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( st_ivas->hHeadTrackData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, Rmat ); + ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_sf( st_ivas->hHeadTrackData, Cldfb_ImagBuffer_in, Cldfb_RealBuffer_in, (uint8_t) hDirAC->subframe_nbslots[subframe_idx], nBins, Rmat ); } } - ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, Rmat, subframe ); + ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices_sf( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, azimuth, elevation, energy_ratio1, spreadCoherence, surroundingCoherence, Rmat ); if ( st_ivas->ivas_format == ISM_FORMAT ) { @@ -656,35 +861,46 @@ static void ivas_dirac_dec_binaural_internal( ivas_dirac_dec_binaural_determine_processing_matrices( st_ivas, max_band_decorr, Rmat ); - ivas_dirac_dec_binaural_process_output( st_ivas, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, max_band_decorr, numInChannels, subframe ); + ivas_dirac_dec_binaural_process_output_sf( st_ivas, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, max_band_decorr, numInChannels ); + + /* we are done with DirAC, update DirAC info*/ + st_ivas->hDirAC->slots_rendered += st_ivas->hDirAC->subframe_nbslots[st_ivas->hDirAC->subframes_rendered]; + st_ivas->hDirAC->subframes_rendered++; st_ivas->hDirAC->hDiffuseDist = NULL; - hDirAC->dirac_read_idx = ( hDirAC->dirac_read_idx + 1 ) % hDirAC->dirac_md_buffer_length; return; } -#else +#endif +#endif + +#ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS static void ivas_dirac_dec_binaural_internal( Decoder_Struct *st_ivas, +#ifdef JBM_TSM_ON_TCS + float *output_f[], +#else float output_f[][L_FRAME48k], +#endif const int16_t nchan_transport, - const uint8_t firstSubframe, - const uint8_t nSubframes ) + const int16_t subframe ) { DIRAC_DEC_HANDLE hDirAC; - uint8_t slot, ch, nBins, numInChannels; - float Cldfb_RealBuffer_in[4][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer_in[4][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + int16_t slot, ch, numInChannels; + float Cldfb_RealBuffer_in[4][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_in[4][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; float Rmat[3][3]; - uint8_t firstSlot, slotEnd; int16_t max_band_decorr; DIFFUSE_DISTRIBUTION_DATA diffuseDistData; - - firstSlot = firstSubframe * ( CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES ); - slotEnd = ( firstSubframe + nSubframes ) * ( CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES ); + int16_t nBins, offsetSamples; hDirAC = st_ivas->hDirAC; - nBins = (uint8_t) hDirAC->num_freq_bands; + nBins = hDirAC->num_freq_bands; +#ifdef JBM_TSM_ON_TCS + offsetSamples = hDirAC->slots_rendered * nBins; +#else + offsetSamples = subframe * CLDFB_SLOTS_PER_SUBFRAME * nBins; +#endif /* The input channel number at this processing function (not nchan_transport) */ numInChannels = BINAURAL_CHANNELS; @@ -706,16 +922,25 @@ static void ivas_dirac_dec_binaural_internal( Rmat[2][2] = 1.0f; /* CLDFB Analysis of input */ - for ( slot = firstSlot; slot < slotEnd; slot++ ) +#ifdef JBM_TSM_ON_TCS + for ( slot = 0; slot < hDirAC->subframe_nbslots[subframe]; slot++ ) +#else + for ( slot = 0; slot < CLDFB_SLOTS_PER_SUBFRAME; slot++ ) +#endif { for ( ch = 0; ch < numInChannels; ch++ ) { if ( ch == 0 || nchan_transport == 2 ) { - cldfbAnalysis_ts( &( output_f[ch][nBins * slot] ), - Cldfb_RealBuffer_in[ch][slot], - Cldfb_ImagBuffer_in[ch][slot], - nBins, st_ivas->cldfbAnaDec[ch] ); + cldfbAnalysis_ts( +#ifdef JBM_TSM_ON_TCS + &( st_ivas->hTcBuffer->tc[ch][nBins * slot + offsetSamples] ), +#else + &( output_f[ch][nBins * slot + offsetSamples] ), +#endif + Cldfb_RealBuffer_in[ch][slot], + Cldfb_ImagBuffer_in[ch][slot], + nBins, st_ivas->cldfbAnaDec[ch] ); } else if ( st_ivas->nchan_transport == 2 ) /* Stereo signal transmitted as mono with DFT stereo */ { @@ -729,14 +954,24 @@ static void ivas_dirac_dec_binaural_internal( if ( st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ) { int16_t numCoreBands, b; + int16_t slotInFrame; numCoreBands = st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->numCoreBands; +#ifdef JBM_TSM_ON_TCS + slotInFrame = hDirAC->slots_rendered + slot; +#else + slotInFrame = subframe * CLDFB_SLOTS_PER_SUBFRAME + slot; +#endif generate_masking_noise_dirac( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom, st_ivas->cldfbAnaDec[1], +#ifdef JBM_TSM_ON_TCS + st_ivas->hTcBuffer->tc[nchan_transport], +#else &( output_f[1][L_FRAME48k - L_FRAME16k] ), /*used as temporary static buffer for the whole frame*/ +#endif Cldfb_RealBuffer_in[2][slot], Cldfb_ImagBuffer_in[2][slot], - slot, + slotInFrame, st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna, ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ); @@ -744,7 +979,7 @@ static void ivas_dirac_dec_binaural_internal( st_ivas->cldfbAnaDec[1], /*nothing will be analyzed, just get cnst*/ NULL, Cldfb_RealBuffer_in[1][slot], Cldfb_ImagBuffer_in[1][slot], - slot, + slotInFrame, st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna, ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ); @@ -786,10 +1021,15 @@ static void ivas_dirac_dec_binaural_internal( { for ( ch = BINAURAL_CHANNELS; ch < ( 2 * BINAURAL_CHANNELS ); ch++ ) { - cldfbAnalysis_ts( &( output_f[ch][nBins * slot] ), - Cldfb_RealBuffer_in[ch][slot], - Cldfb_ImagBuffer_in[ch][slot], - nBins, st_ivas->cldfbAnaDec[ch] ); + cldfbAnalysis_ts( +#ifdef JBM_TSM_ON_TCS + &( st_ivas->hTcBuffer->tc[ch][nBins * slot + offsetSamples] ), +#else + &( output_f[ch][nBins * slot + offsetSamples] ), +#endif + Cldfb_RealBuffer_in[ch][slot], + Cldfb_ImagBuffer_in[ch][slot], + nBins, st_ivas->cldfbAnaDec[ch] ); if ( st_ivas->nchan_transport == 1 && st_ivas->ivas_format == SBA_FORMAT ) { @@ -804,24 +1044,30 @@ static void ivas_dirac_dec_binaural_internal( { st_ivas->hDirAC->hDiffuseDist = &diffuseDistData; - ivas_spar_param_to_masa_param_mapping( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, firstSubframe, nSubframes ); + ivas_spar_param_to_masa_param_mapping( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe ); - ivas_sba_prototype_renderer( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, firstSubframe, nSubframes ); + ivas_sba_prototype_renderer( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe ); } if ( st_ivas->hHeadTrackData && st_ivas->hHeadTrackData->num_quaternions >= 0 ) { - QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[firstSubframe], Rmat ); + QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[subframe], Rmat ); if ( nchan_transport == 2 ) { - adaptTransportSignalsHeadtracked( st_ivas->hHeadTrackData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, firstSlot, slotEnd, nBins, Rmat ); +#ifdef JBM_TSM_ON_TCS + adaptTransportSignalsHeadtracked( st_ivas->hHeadTrackData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hDirAC->subframe_nbslots[subframe], Rmat ); - ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( st_ivas->hHeadTrackData, Cldfb_ImagBuffer_in, Cldfb_RealBuffer_in, firstSlot, slotEnd, nBins, Rmat ); + ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( st_ivas->hHeadTrackData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hDirAC->subframe_nbslots[subframe], Rmat ); +#else + adaptTransportSignalsHeadtracked( st_ivas->hHeadTrackData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, Rmat ); + + ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( st_ivas->hHeadTrackData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, Rmat ); +#endif } } - ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, Rmat, firstSubframe, nSubframes ); + ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, Rmat, subframe ); if ( st_ivas->ivas_format == ISM_FORMAT ) { @@ -838,46 +1084,302 @@ static void ivas_dirac_dec_binaural_internal( ivas_dirac_dec_binaural_determine_processing_matrices( st_ivas, max_band_decorr, Rmat ); - ivas_dirac_dec_binaural_process_output( st_ivas, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, max_band_decorr, numInChannels, firstSlot, slotEnd ); + ivas_dirac_dec_binaural_process_output( st_ivas, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, max_band_decorr, numInChannels, subframe ); st_ivas->hDirAC->hDiffuseDist = NULL; - return; -} -#endif - -#ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS -static void ivas_dirac_dec_decorrelate_slot( - DIRAC_DEC_HANDLE hDirAC, - const int16_t slot, - float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - float decRe[][CLDFB_NO_CHANNELS_MAX], - float decIm[][CLDFB_NO_CHANNELS_MAX] ) +#ifdef JBM_TSM_ON_TCS + hDirAC->slots_rendered += hDirAC->subframe_nbslots[subframe]; + hDirAC->subframes_rendered++; #else -static void ivas_dirac_dec_decorrelate_slot( - DIRAC_DEC_HANDLE hDirAC, - const int8_t slot, - float inRe[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - float inIm[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - float decRe[][CLDFB_NO_CHANNELS_MAX], - float decIm[][CLDFB_NO_CHANNELS_MAX] ) + hDirAC->dirac_read_idx = ( hDirAC->dirac_read_idx + 1 ) % hDirAC->dirac_md_buffer_length; #endif + + return; +} +#else +static void ivas_dirac_dec_binaural_internal( + Decoder_Struct *st_ivas, + float output_f[][L_FRAME48k], + const int16_t nchan_transport, + const uint8_t firstSubframe, + const uint8_t nSubframes ) { - int16_t offset, ch, bin; - float onset_filter[BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, 60 bins */ - float decorrelatedFrameInterleaved[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */ + DIRAC_DEC_HANDLE hDirAC; + uint8_t slot, ch, nBins, numInChannels; + float Cldfb_RealBuffer_in[4][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_in[4][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float Rmat[3][3]; + uint8_t firstSlot, slotEnd; + int16_t max_band_decorr; + DIFFUSE_DISTRIBUTION_DATA diffuseDistData; - /* Decorrelation needs interleaved data. Copy left and right signals to proto_frame_f */ - for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) - { - offset = hDirAC->num_freq_bands * BINAURAL_CHANNELS * ch; - for ( bin = 0; bin < hDirAC->num_freq_bands; bin++ ) - { - hDirAC->proto_frame_f[( bin * BINAURAL_CHANNELS ) + offset] = inRe[ch][slot][bin]; - hDirAC->proto_frame_f[( bin * BINAURAL_CHANNELS ) + offset + 1] = inIm[ch][slot][bin]; - } + firstSlot = firstSubframe * ( CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES ); + slotEnd = ( firstSubframe + nSubframes ) * ( CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES ); + + hDirAC = st_ivas->hDirAC; + nBins = (uint8_t) hDirAC->num_freq_bands; + + /* The input channel number at this processing function (not nchan_transport) */ + numInChannels = BINAURAL_CHANNELS; + if ( st_ivas->hOutSetup.separateChannelEnabled ) + { + numInChannels++; + } + + Rmat[0][0] = 1.0f; + Rmat[0][1] = 0.0f; + Rmat[0][2] = 0.0f; + + Rmat[1][0] = 0.0f; + Rmat[1][1] = 1.0f; + Rmat[1][2] = 0.0f; + + Rmat[2][0] = 0.0f; + Rmat[2][1] = 0.0f; + Rmat[2][2] = 1.0f; + + /* CLDFB Analysis of input */ + for ( slot = firstSlot; slot < slotEnd; slot++ ) + { + for ( ch = 0; ch < numInChannels; ch++ ) + { + if ( ch == 0 || nchan_transport == 2 ) + { + cldfbAnalysis_ts( &( output_f[ch][nBins * slot] ), + Cldfb_RealBuffer_in[ch][slot], + Cldfb_ImagBuffer_in[ch][slot], + nBins, st_ivas->cldfbAnaDec[ch] ); + } + else if ( st_ivas->nchan_transport == 2 ) /* Stereo signal transmitted as mono with DFT stereo */ + { + /* At mono input duplicate the channel to dual-mono */ + mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins ); + mvr2r( Cldfb_ImagBuffer_in[0][slot], Cldfb_ImagBuffer_in[1][slot], nBins ); + } + else /* when nchan_transport == 1 and ch == 1 */ + { + /* CNA and HB FD-CNG*/ + if ( st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ) + { + int16_t numCoreBands, b; + + numCoreBands = st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->numCoreBands; + + generate_masking_noise_dirac( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom, + st_ivas->cldfbAnaDec[1], +#ifdef JBM_TSM_ON_TCS + st_ivas->hTcBuffer->tc[1], +#else + &( output_f[1][L_FRAME48k - L_FRAME16k] ), /*used as temporary static buffer for the whole frame*/ +#endif + Cldfb_RealBuffer_in[2][slot], Cldfb_ImagBuffer_in[2][slot], + slot, + st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna, + ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ); + + generate_masking_noise_dirac( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom, + st_ivas->cldfbAnaDec[1], /*nothing will be analyzed, just get cnst*/ + NULL, + Cldfb_RealBuffer_in[1][slot], Cldfb_ImagBuffer_in[1][slot], + slot, + st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna, + ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ); + + /* LB: Copy first channel + LB-CNG to first and second channels with same scaling (dual-mono)*/ + for ( b = 0; b < numCoreBands; b++ ) + { + Cldfb_RealBuffer_in[0][slot][b] = INV_SQRT2 * ( Cldfb_RealBuffer_in[0][slot][b] + Cldfb_RealBuffer_in[2][slot][b] ); + Cldfb_RealBuffer_in[1][slot][b] = Cldfb_RealBuffer_in[0][slot][b]; + Cldfb_ImagBuffer_in[0][slot][b] = INV_SQRT2 * ( Cldfb_ImagBuffer_in[0][slot][b] + Cldfb_ImagBuffer_in[2][slot][b] ); + Cldfb_ImagBuffer_in[1][slot][b] = Cldfb_ImagBuffer_in[0][slot][b]; + } + + /* HB: Copy first channel to second channel and add HB-CNGs with different scalings*/ + for ( ; b < nBins; b++ ) + { + Cldfb_RealBuffer_in[0][slot][b] *= INV_SQRT2; + Cldfb_RealBuffer_in[1][slot][b] = Cldfb_RealBuffer_in[0][slot][b] + 0.5f * Cldfb_RealBuffer_in[1][slot][b] + Cldfb_RealBuffer_in[0][slot][b]; + Cldfb_RealBuffer_in[0][slot][b] += 0.5f * Cldfb_RealBuffer_in[2][slot][b]; + + Cldfb_ImagBuffer_in[0][slot][b] *= INV_SQRT2; + Cldfb_ImagBuffer_in[1][slot][b] = Cldfb_ImagBuffer_in[0][slot][b] + 0.5f * Cldfb_ImagBuffer_in[1][slot][b]; + Cldfb_ImagBuffer_in[0][slot][b] += 0.5f * Cldfb_ImagBuffer_in[2][slot][b]; + } + } + else + { + /* At mono input duplicate the channel to dual-mono, and apply gain + correction to ensure same overall level as in stereo mode */ + v_multc( Cldfb_RealBuffer_in[0][slot], INV_SQRT_2, Cldfb_RealBuffer_in[0][slot], nBins ); + v_multc( Cldfb_ImagBuffer_in[0][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[0][slot], nBins ); + + mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins ); + mvr2r( Cldfb_ImagBuffer_in[0][slot], Cldfb_ImagBuffer_in[1][slot], nBins ); + } + } + } + + if ( st_ivas->hDiracDecBin->useTdDecorr ) + { + for ( ch = BINAURAL_CHANNELS; ch < ( 2 * BINAURAL_CHANNELS ); ch++ ) + { + cldfbAnalysis_ts( +#ifdef JBM_TSM_ON_TCS + &( st_ivas->hTcBuffer->tc[ch][nBins * slot] ), +#else + &( output_f[ch][nBins * slot] ), +#endif + Cldfb_RealBuffer_in[ch][slot], + Cldfb_ImagBuffer_in[ch][slot], + nBins, st_ivas->cldfbAnaDec[ch] ); + + if ( st_ivas->nchan_transport == 1 && st_ivas->ivas_format == SBA_FORMAT ) + { + v_multc( Cldfb_RealBuffer_in[ch][slot], INV_SQRT_2, Cldfb_RealBuffer_in[ch][slot], nBins ); + v_multc( Cldfb_ImagBuffer_in[ch][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[ch][slot], nBins ); + } + } + } + } + + if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR ) + { + st_ivas->hDirAC->hDiffuseDist = &diffuseDistData; + + ivas_spar_param_to_masa_param_mapping( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, firstSubframe, nSubframes ); + + ivas_sba_prototype_renderer( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, firstSubframe, nSubframes ); + } + + if ( st_ivas->hHeadTrackData && st_ivas->hHeadTrackData->num_quaternions >= 0 ) + { + QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[firstSubframe], Rmat ); + + if ( nchan_transport == 2 ) + { + adaptTransportSignalsHeadtracked( st_ivas->hHeadTrackData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, firstSlot, slotEnd, nBins, Rmat ); + + ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( st_ivas->hHeadTrackData, Cldfb_ImagBuffer_in, Cldfb_RealBuffer_in, firstSlot, slotEnd, nBins, Rmat ); + } + } + + ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, Rmat, firstSubframe, nSubframes ); + + if ( st_ivas->ivas_format == ISM_FORMAT ) + { + max_band_decorr = 0; + } + else if ( st_ivas->hDiracDecBin->useTdDecorr ) + { + max_band_decorr = CLDFB_NO_CHANNELS_MAX; + } + else + { + max_band_decorr = st_ivas->hDirAC->h_freq_domain_decorr_ap_params->max_band_decorr; + } + + ivas_dirac_dec_binaural_determine_processing_matrices( st_ivas, max_band_decorr, Rmat ); + + ivas_dirac_dec_binaural_process_output( st_ivas, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, max_band_decorr, numInChannels, firstSlot, slotEnd ); + + st_ivas->hDirAC->hDiffuseDist = NULL; + +#ifdef JBM_TSM_ON_TCS + st_ivas->hDirAC->slots_rendered += ( slotEnd - firstSlot ); + st_ivas->hDirAC->subframes_rendered += nSubframes; +#endif + + return; +} +#endif + + +#ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS +static void ivas_dirac_dec_decorrelate_slot( + DIRAC_DEC_HANDLE hDirAC, + const int16_t slot, + float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + float decRe[][CLDFB_NO_CHANNELS_MAX], + float decIm[][CLDFB_NO_CHANNELS_MAX] ) +#else +static void ivas_dirac_dec_decorrelate_slot( + DIRAC_DEC_HANDLE hDirAC, + const int8_t slot, + float inRe[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float inIm[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float decRe[][CLDFB_NO_CHANNELS_MAX], + float decIm[][CLDFB_NO_CHANNELS_MAX] ) +#endif +{ + int16_t offset, ch, bin; + float onset_filter[BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, 60 bins */ + float decorrelatedFrameInterleaved[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */ + + /* Decorrelation needs interleaved data. Copy left and right signals to proto_frame_f */ + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + offset = hDirAC->num_freq_bands * BINAURAL_CHANNELS * ch; + for ( bin = 0; bin < hDirAC->num_freq_bands; bin++ ) + { + hDirAC->proto_frame_f[( bin * BINAURAL_CHANNELS ) + offset] = inRe[ch][slot][bin]; + hDirAC->proto_frame_f[( bin * BINAURAL_CHANNELS ) + offset + 1] = inIm[ch][slot][bin]; + } + } + + /* Decorrelate proto signal to decorrelatedFrameInterleaved */ + ivas_dirac_dec_decorr_process( hDirAC->num_freq_bands, + hDirAC->num_outputs_diff, + hDirAC->num_protos_diff, + hDirAC->synthesisConf, + BINAURAL_CHANNELS, + hDirAC->proto_frame_f, + hDirAC->num_protos_diff, + hDirAC->proto_index_diff, + decorrelatedFrameInterleaved, + onset_filter, + hDirAC->h_freq_domain_decorr_ap_params, + hDirAC->h_freq_domain_decorr_ap_state ); + + /* De-interleave decorrelated signals*/ + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + offset = hDirAC->num_freq_bands * BINAURAL_CHANNELS * ch; + for ( bin = 0; bin < hDirAC->num_freq_bands; bin++ ) + { + decRe[ch][bin] = decorrelatedFrameInterleaved[( bin * BINAURAL_CHANNELS ) + offset]; + decIm[ch][bin] = decorrelatedFrameInterleaved[( bin * BINAURAL_CHANNELS ) + offset + 1]; + } + } + + return; +} + +#ifdef JBM_TSM_ON_TCS +#ifndef FIX_355_REFACTOR_PARAMBIN_TO_5MS +static void ivas_dirac_dec_decorrelate_slot_sf( + DIRAC_DEC_HANDLE hDirAC, + const int8_t slot, + float inRe[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + float inIm[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + float decRe[][CLDFB_NO_CHANNELS_MAX], + float decIm[][CLDFB_NO_CHANNELS_MAX] ) +{ + int16_t offset, ch, bin; + float onset_filter[BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, 60 bins */ + float decorrelatedFrameInterleaved[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */ + + /* Decorrelation needs interleaved data. Copy left and right signals to proto_frame_f */ + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + offset = hDirAC->num_freq_bands * BINAURAL_CHANNELS * ch; + for ( bin = 0; bin < hDirAC->num_freq_bands; bin++ ) + { + hDirAC->proto_frame_f[( bin * BINAURAL_CHANNELS ) + offset] = inRe[ch][slot][bin]; + hDirAC->proto_frame_f[( bin * BINAURAL_CHANNELS ) + offset + 1] = inIm[ch][slot][bin]; + } } /* Decorrelate proto signal to decorrelatedFrameInterleaved */ @@ -900,13 +1402,418 @@ static void ivas_dirac_dec_decorrelate_slot( offset = hDirAC->num_freq_bands * BINAURAL_CHANNELS * ch; for ( bin = 0; bin < hDirAC->num_freq_bands; bin++ ) { - decRe[ch][bin] = decorrelatedFrameInterleaved[( bin * BINAURAL_CHANNELS ) + offset]; - decIm[ch][bin] = decorrelatedFrameInterleaved[( bin * BINAURAL_CHANNELS ) + offset + 1]; + decRe[ch][bin] = decorrelatedFrameInterleaved[( bin * BINAURAL_CHANNELS ) + offset]; + decIm[ch][bin] = decorrelatedFrameInterleaved[( bin * BINAURAL_CHANNELS ) + offset + 1]; + } + } + + return; +} + +static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices_sf( + Decoder_Struct *st_ivas, + float inRe[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + float inIm[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + int16_t azimuth[CLDFB_NO_CHANNELS_MAX], + int16_t elevation[CLDFB_NO_CHANNELS_MAX], + float energy_ratio1[CLDFB_NO_CHANNELS_MAX], + float spreadCoherence[CLDFB_NO_CHANNELS_MAX], + float surroundingCoherence[CLDFB_NO_CHANNELS_MAX], + float Rmat[3][3] ) +{ + uint8_t ch, slot, bin; + uint8_t separateCenterChannelRendering; + int16_t nBins, idx, subframe; + float frameMeanDiffusenessEneWeight[CLDFB_NO_CHANNELS_MAX]; + DIRAC_DEC_HANDLE hDirAC; + DIRAC_DEC_BIN_HANDLE h; + float IIReneLimiterFactor; + float qualityBasedSmFactor; + float lowBitRateEQ[CLDFB_NO_CHANNELS_MAX]; + uint8_t applyLowBitRateEQ; + float subFrameTotalEne[CLDFB_NO_CHANNELS_MAX]; + int16_t md_idx; + + hDirAC = st_ivas->hDirAC; + h = st_ivas->hDiracDecBin; + separateCenterChannelRendering = st_ivas->hOutSetup.separateChannelEnabled; + nBins = hDirAC->num_freq_bands; /* Actually bins */ + subframe = hDirAC->subframes_rendered; + md_idx = hDirAC->render_to_md_map[hDirAC->subframes_rendered]; + + set_zero( h->ChCrossRe, nBins ); + set_zero( h->ChCrossIm, nBins ); + set_zero( h->ChCrossReOut, nBins ); + set_zero( h->ChCrossImOut, nBins ); + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + set_zero( h->ChEne[ch], nBins ); + set_zero( h->ChEneOut[ch], nBins ); + } + set_zero( h->frameMeanDiffuseness, nBins ); + + set_zero( frameMeanDiffusenessEneWeight, CLDFB_NO_CHANNELS_MAX ); + + /* Determine EQ for low bit rates (13.2 and 16.4 kbps) */ + applyLowBitRateEQ = 0; + if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MC_FORMAT ) && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE ) + { + applyLowBitRateEQ = 1; + if ( st_ivas->hDecoderConfig->ivas_total_brate == IVAS_16k4 ) + { + for ( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ ) + { + lowBitRateEQ[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = lowBitRateBinauralEQ[bin] * 0.5f + 0.5f; + } + } + else + { + for ( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ ) + { + lowBitRateEQ[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = lowBitRateBinauralEQ[bin]; + } + } + } + + /* Formulate input and target covariance matrices combining all subframes */ + set_zero( subFrameTotalEne, CLDFB_NO_CHANNELS_MAX ); + + /* Calculate input covariance matrix */ + for ( slot = 0; slot < (uint8_t) hDirAC->subframe_nbslots[subframe]; slot++ ) + { + for ( bin = 0; bin < nBins; bin++ ) + { + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + float instEne; + + instEne = ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ); + instEne += ( inIm[ch][slot][bin] * inIm[ch][slot][bin] ); + h->ChEne[ch][bin] += instEne; + subFrameTotalEne[bin] += instEne; + } + h->ChCrossRe[bin] += inRe[0][slot][bin] * inRe[1][slot][bin]; + h->ChCrossRe[bin] += inIm[0][slot][bin] * inIm[1][slot][bin]; + h->ChCrossIm[bin] += inRe[0][slot][bin] * inIm[1][slot][bin]; + h->ChCrossIm[bin] -= inIm[0][slot][bin] * inRe[1][slot][bin]; + } + } + + /* Apply EQ at low bit rates */ + if ( applyLowBitRateEQ ) + { + int16_t lastEqBin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET + LOW_BIT_RATE_BINAURAL_EQ_BINS - 1; + + for ( bin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET; bin < lastEqBin; bin++ ) + { + subFrameTotalEne[bin] *= lowBitRateEQ[bin]; + } + for ( ; bin < nBins; bin++ ) + { + subFrameTotalEne[bin] *= lowBitRateEQ[lastEqBin]; + } + } + + if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->nchan_transport == 2 ) + { + float tempRe, tempIm; + + set_zero( subFrameTotalEne, CLDFB_NO_CHANNELS_MAX ); + + for ( slot = 0; slot < (uint8_t) hDirAC->subframe_nbslots[subframe]; slot++ ) + { + for ( bin = 0; bin < nBins; bin++ ) + { + tempRe = inRe[0][slot][bin] + inRe[1][slot][bin]; + tempIm = inIm[0][slot][bin] + inIm[1][slot][bin]; + subFrameTotalEne[bin] += tempRe * tempRe + tempIm * tempIm; + } + } + } + + /* Determine target covariance matrix containing target binaural properties */ + for ( bin = 0; bin < nBins; bin++ ) + { + float diffuseness = 1.0f; /* ratio1 and ratio2 are subtracted from diffuseness further below */ + float surCoh = 0.0f, spreadCoh = 0.0f; /* Default values if spreadSurroundCoherenceApplied == false */ + float diffEne, dirEne, meanEnePerCh; + uint16_t dirIndex; + + /* When BINAURAL_ROOM is not indicated, hBinaural->earlyPartEneCorrection[bin] values are all 1.0f. + * When BINAURAL_ROOM is indicated, the binaural audio output is based on combined use of the + * HRTF data set and a BRIR-based data set. The HRTF data set is spectrally corrected to match + * the early spectrum of the BRIR data, using the spectral correction data in + * hBinaural->earlyPartEneCorrection[bin], based on the BRIR set. */ + meanEnePerCh = h->earlyPartEneCorrection[bin] * subFrameTotalEne[bin] / 2.0f; + + /* Determine direct part target covariance matrix (for 1 or 2 directions) */ + for ( dirIndex = 0; dirIndex < hDirAC->numSimultaneousDirections; dirIndex++ ) + { + int16_t aziDeg, eleDeg; + float lRealp, lImagp, rRealp, rImagp; + float lRealpTmp, lImagpTmp, rRealpTmp, rImagpTmp; + float hrtfEne[BINAURAL_CHANNELS], hrtfCrossRe, hrtfCrossIm, ratio; + + if ( dirIndex == 0 ) /* For first of the two simultaneous directions */ + { + aziDeg = azimuth[bin]; + eleDeg = elevation[bin]; + ratio = energy_ratio1[bin]; + spreadCoh = spreadCoherence[bin]; + } + else /* For second of the two simultaneous directions */ + { + aziDeg = hDirAC->azimuth2[md_idx][bin]; + eleDeg = hDirAC->elevation2[md_idx][bin]; + ratio = hDirAC->energy_ratio2[md_idx][bin]; + spreadCoh = hDirAC->spreadCoherence2[md_idx][bin]; + } + diffuseness -= ratio; /* diffuseness = 1 - ratio1 - ratio2 */ + + if ( separateCenterChannelRendering ) + { + /* In masa + mono rendering mode, the center directions originate from phantom sources, so the + * spread coherence is increased */ + float aziRad, eleRad, doaVectorX, spatialAngleDeg, altSpreadCoh; + + aziRad = (float) aziDeg * PI_OVER_180; + eleRad = (float) eleDeg * PI_OVER_180; + doaVectorX = cosf( aziRad ) * cosf( eleRad ); + spatialAngleDeg = acosf( doaVectorX ) * _180_OVER_PI; + altSpreadCoh = 1.0f - ( spatialAngleDeg / 30.0f ); + spreadCoh = max( spreadCoh, altSpreadCoh ); + } + + getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, h->renderStereoOutputInsteadOfBinaural, Rmat ); + + if ( h->renderStereoOutputInsteadOfBinaural ) + { + /* Synthesizing spread coherence is not needed for stereo loudspeaker output, + * as directional sound is reproduced with two loudspeakers in any case */ + spreadCoh = 0.0f; + } + + if ( spreadCoh > 0.0f ) + { + float centerMul, sidesMul; + float hrtfEneCenter, hrtfEneSides, hrtfEneRealized, eneCorrectionFactor; + float w1, w2, w3, eq; + + hrtfEneCenter = ( lRealp * lRealp ) + ( lImagp * lImagp ) + ( rRealp * rRealp ) + ( rImagp * rImagp ); + + /* Spread coherence is synthesized as coherent sources at 30 degree horizontal spacing. + * The following formulas determine the gains for these sources. + * spreadCoh = 0: Only panning + * spreadCoh = 0.5: Three sources coherent panning (e.g. 30 0 -30 deg azi) + * spreadCoh = 1.0: Two sources coherent panning with gap (as above, but center is silent) */ + if ( spreadCoh < 0.5f ) + { + /* 0.0f < spreadCoh < 0.5f */ + sidesMul = 0.5774f * spreadCoh * 2.0f; /* sqrt(1/3) = 0.5774f */ + centerMul = 1.0f - ( spreadCoh * 2.0f ) + sidesMul; + } + else + { + /* 0.5f <= spreadCoh < 1.0f */ + centerMul = 2.0f - ( 2.0f * spreadCoh ); + sidesMul = inv_sqrt( centerMul + 2.0f ); + centerMul *= sidesMul; + } + + /* Apply the gain for the center source of the three coherent sources */ + lRealp *= centerMul; + lImagp *= centerMul; + rRealp *= centerMul; + rImagp *= centerMul; + + /* Apply the gain for the left source of the three coherent sources */ + getDirectPartGains( bin, aziDeg + 30, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, h->renderStereoOutputInsteadOfBinaural, Rmat ); + + hrtfEneSides = ( lRealpTmp * lRealpTmp ) + ( lImagpTmp * lImagpTmp ) + ( rRealpTmp * rRealpTmp ) + ( rImagpTmp * rImagpTmp ); + lRealp += sidesMul * lRealpTmp; + lImagp += sidesMul * lImagpTmp; + rRealp += sidesMul * rRealpTmp; + rImagp += sidesMul * rImagpTmp; + + /* Apply the gain for the right source of the three coherent sources. + * -30 degrees to 330 wrapping due to internal functions. */ + getDirectPartGains( bin, aziDeg + 330, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, h->renderStereoOutputInsteadOfBinaural, Rmat ); + + hrtfEneSides += ( lRealpTmp * lRealpTmp ) + ( lImagpTmp * lImagpTmp ) + ( rRealpTmp * rRealpTmp ) + ( rImagpTmp * rImagpTmp ); + lRealp += sidesMul * lRealpTmp; + lImagp += sidesMul * lImagpTmp; + rRealp += sidesMul * rRealpTmp; + rImagp += sidesMul * rImagpTmp; + + /* Formulate an eneCorrectionFactor that compensates for the coherent summation of the HRTFs */ + hrtfEneRealized = ( lRealp * lRealp ) + ( lImagp * lImagp ) + ( rRealp * rRealp ) + ( rImagp * rImagp ); + eneCorrectionFactor = ( ( hrtfEneSides * sidesMul * sidesMul ) + + ( hrtfEneCenter * centerMul * centerMul ) ) / + max( 1e-12f, hrtfEneRealized ); + + /* Weighting factors to determine appropriate target spectrum for spread coherent sound */ + if ( spreadCoh < 0.5 ) + { + w1 = 1.0f - 2.0f * spreadCoh; + w2 = 2.0f * spreadCoh; + w3 = 0.0f; + } + else + { + w1 = 0.0f; + w2 = 2.0f - 2.0f * spreadCoh; + w3 = 2.0f * spreadCoh - 1.0f; + } + + if ( ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ) + { + idx = min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 ); + + /* Apply the target spectrum to the eneCorrectionFactor */ + if ( separateCenterChannelRendering ) /* spreadCoh mostly originates from phantom sources in separate channel rendering mode */ + { + eneCorrectionFactor *= w1 * 1.0f + ( w2 + w3 ) * spreadCohEne1[idx]; + } + else + { + eneCorrectionFactor *= w1 * 1.0f + w2 * spreadCohEne05[idx] + w3 * spreadCohEne1[idx]; + } + } + + /* Equalize the spread coherent combined HRTFs */ + eq = min( 4.0f, sqrtf( eneCorrectionFactor ) ); + lRealp *= eq; + lImagp *= eq; + rRealp *= eq; + rImagp *= eq; + } + + hrtfEne[0] = ( lRealp * lRealp ) + ( lImagp * lImagp ); + hrtfEne[1] = ( rRealp * rRealp ) + ( rImagp * rImagp ); + hrtfCrossRe = ( lRealp * rRealp ) + ( lImagp * rImagp ); + hrtfCrossIm = ( -lImagp * rRealp ) + ( lRealp * rImagp ); + + /* Add direct part (1 or 2) covariance matrix */ + dirEne = ratio * meanEnePerCh; + h->ChEneOut[0][bin] += dirEne * hrtfEne[0]; /* Dir ene part*/ + h->ChEneOut[1][bin] += dirEne * hrtfEne[1]; + h->ChCrossReOut[bin] += dirEne * hrtfCrossRe; /* Dir cross re */ + h->ChCrossImOut[bin] += dirEne * hrtfCrossIm; /* Dir cross im */ + } + + /* Add diffuse / ambient part covariance matrix */ + diffuseness = max( 0.0f, diffuseness ); + diffEne = diffuseness * meanEnePerCh; + surCoh = surroundingCoherence[bin]; + if ( ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ) + { + if ( !h->renderStereoOutputInsteadOfBinaural ) + { + idx = min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 ); + /* Apply target spectrum that emphasizes low frequencies when the sound is surround coherent */ + diffEne *= ( 1.0f - surCoh ) + surCoh * surCohEne[idx]; + } + } + h->ChEneOut[0][bin] += diffEne; /* Diff ene part*/ + h->ChEneOut[1][bin] += diffEne; + + if ( h->renderStereoOutputInsteadOfBinaural ) + { + /* When rendering stereo, ambience (except for surround coherent sound) has zero ICC. */ + h->ChCrossReOut[bin] += surCoh * diffEne; + } + else /* When rendering binaural, ambience has frequency dependent ICC. */ + { + if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR && bin < BINAURAL_COHERENCE_DIFFERENCE_BINS ) + { + float diffuseFieldCoherence; + diffuseFieldCoherence = hDirAC->hDiffuseDist->diffuseRatioX[bin] * h->diffuseFieldCoherenceX[bin] + hDirAC->hDiffuseDist->diffuseRatioY[bin] * h->diffuseFieldCoherenceY[bin] + hDirAC->hDiffuseDist->diffuseRatioZ[bin] * h->diffuseFieldCoherenceZ[bin]; + h->ChCrossReOut[bin] += ( ( 1.0f - surCoh ) * diffuseFieldCoherence + surCoh ) * diffEne; + } + else + { + h->ChCrossReOut[bin] += ( ( 1.0f - surCoh ) * h->diffuseFieldCoherence[bin] + surCoh ) * diffEne; + } + } + + /* Store parameters for formulating average diffuseness over frame */ + h->frameMeanDiffuseness[bin] += diffEne; + frameMeanDiffusenessEneWeight[bin] += meanEnePerCh; + } + + + /* Formulate average diffuseness over frame */ + for ( bin = 0; bin < nBins; bin++ ) + { + h->frameMeanDiffuseness[bin] /= fmaxf( 1e-12f, frameMeanDiffusenessEneWeight[bin] ); + } + + /* Determine encoding quality based additional smoothing factor */ + qualityBasedSmFactor = 1.0f; + if ( st_ivas->hMasa != NULL ) + { + qualityBasedSmFactor = st_ivas->hMasa->data.dir_decode_quality; + qualityBasedSmFactor *= qualityBasedSmFactor; + } + + /* Temporal IIR-type smoothing of covariance matrices */ + if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE ) + { + IIReneLimiterFactor = 16.0f + ( 1.0f - qualityBasedSmFactor ); + } + else + { + IIReneLimiterFactor = 8.0f + ( 1.0f - qualityBasedSmFactor ); + } + for ( bin = 0; bin < nBins; bin++ ) + { + float eneRatio, IIReneLimiter; + + /* Temporally smooth cov mtx estimates for resulting mixing matrix stability. The design principle is that + * the energy history (IIR) must not be more than double of the current frame energy. This provides more + * robust performance at energy offsets when compared to typical IIR averaging. */ + eneRatio = ( h->ChEne[0][bin] + h->ChEne[1][bin] ) / fmaxf( 1e-12f, ( h->ChEnePrev[0][bin] + h->ChEnePrev[1][bin] ) ); + IIReneLimiter = fminf( 1.0f, eneRatio * IIReneLimiterFactor ); + + h->ChCrossRe[bin] *= qualityBasedSmFactor; + h->ChCrossIm[bin] *= qualityBasedSmFactor; + h->ChCrossReOut[bin] *= qualityBasedSmFactor; + h->ChCrossImOut[bin] *= qualityBasedSmFactor; + + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + h->ChEne[ch][bin] *= qualityBasedSmFactor; + h->ChEneOut[ch][bin] *= qualityBasedSmFactor; + } + + h->ChCrossRe[bin] += IIReneLimiter * h->ChCrossRePrev[bin]; + h->ChCrossIm[bin] += IIReneLimiter * h->ChCrossImPrev[bin]; + h->ChCrossReOut[bin] += IIReneLimiter * h->ChCrossReOutPrev[bin]; + h->ChCrossImOut[bin] += IIReneLimiter * h->ChCrossImOutPrev[bin]; + + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + h->ChEne[ch][bin] += IIReneLimiter * h->ChEnePrev[ch][bin]; + h->ChEneOut[ch][bin] += IIReneLimiter * h->ChEneOutPrev[ch][bin]; + } + + /* Store energy values and coefficients for next round */ + h->ChCrossRePrev[bin] = h->ChCrossRe[bin]; + h->ChCrossImPrev[bin] = h->ChCrossIm[bin]; + h->ChCrossReOutPrev[bin] = h->ChCrossReOut[bin]; + h->ChCrossImOutPrev[bin] = h->ChCrossImOut[bin]; + + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + h->ChEnePrev[ch][bin] = h->ChEne[ch][bin]; + h->ChEneOutPrev[ch][bin] = h->ChEneOut[ch][bin]; } } return; } +#endif +#endif #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS @@ -971,10 +1878,18 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric /* Formulate input and target covariance matrices for this subframe */ set_zero( subFrameTotalEne, CLDFB_NO_CHANNELS_MAX ); +#ifdef JBM_TSM_ON_TCS + dirac_read_idx = hDirAC->render_to_md_map[subframe]; +#else dirac_read_idx = hDirAC->dirac_read_idx; +#endif /* Calculate input covariance matrix */ +#ifdef JBM_TSM_ON_TCS + for ( slot = 0; slot < hDirAC->subframe_nbslots[subframe]; slot++ ) +#else for ( slot = 0; slot < hDirAC->subframe_nbslots; slot++ ) +#endif { for ( bin = 0; bin < nBins; bin++ ) { @@ -1015,7 +1930,11 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric set_zero( subFrameTotalEne, CLDFB_NO_CHANNELS_MAX ); +#ifdef JBM_TSM_ON_TCS + for ( slot = 0; slot < hDirAC->subframe_nbslots[subframe]; slot++ ) +#else for ( slot = 0; slot < hDirAC->subframe_nbslots; slot++ ) +#endif { for ( bin = 0; bin < nBins; bin++ ) { @@ -1222,7 +2141,11 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR && bin < BINAURAL_COHERENCE_DIFFERENCE_BINS ) { float diffuseFieldCoherence; +#ifdef JBM_TSM_ON_TCS + diffuseFieldCoherence = hDirAC->hDiffuseDist->diffuseRatioX[bin] * h->diffuseFieldCoherenceX[bin] + hDirAC->hDiffuseDist->diffuseRatioY[bin] * h->diffuseFieldCoherenceY[bin] + hDirAC->hDiffuseDist->diffuseRatioZ[bin] * h->diffuseFieldCoherenceZ[bin]; +#else diffuseFieldCoherence = hDirAC->hDiffuseDist->diffuseRatioX[subframe][bin] * h->diffuseFieldCoherenceX[bin] + hDirAC->hDiffuseDist->diffuseRatioY[subframe][bin] * h->diffuseFieldCoherenceY[bin] + hDirAC->hDiffuseDist->diffuseRatioZ[subframe][bin] * h->diffuseFieldCoherenceZ[bin]; +#endif h->ChCrossReOut[bin] += ( ( 1.0f - surCoh ) * diffuseFieldCoherence + surCoh ) * diffEne; } else @@ -1326,6 +2249,9 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric float lowBitRateEQ[CLDFB_NO_CHANNELS_MAX]; uint8_t applyLowBitRateEQ; int16_t dirac_read_idx; +#ifdef JBM_TSM_ON_TCS + int16_t slot_idx_start; +#endif hDirAC = st_ivas->hDirAC; h = st_ivas->hDiracDecBin; @@ -1366,18 +2292,31 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric } } +#ifdef JBM_TSM_ON_TCS + slot_idx_start = hDirAC->slots_rendered; +#endif + /* Formulate input and target covariance matrices combining all subframes */ for ( subframe = firstSubframe; subframe < ( firstSubframe + nSubframes ); subframe++ ) { float subFrameTotalEne[CLDFB_NO_CHANNELS_MAX]; set_zero( subFrameTotalEne, CLDFB_NO_CHANNELS_MAX ); + dirac_read_idx = hDirAC->dirac_read_idx; /* Calculate input covariance matrix */ +#ifdef JBM_TSM_ON_TCS + for ( slot = 0; slot < (uint8_t) hDirAC->subframe_nbslots[subframe]; slot++ ) +#else for ( slot = 0; slot < (uint8_t) hDirAC->subframe_nbslots; slot++ ) +#endif { +#ifdef JBM_TSM_ON_TCS + int16_t slotThis = slot + slot_idx_start; +#else int16_t slotThis = slot + ( hDirAC->subframe_nbslots * subframe ); +#endif for ( bin = 0; bin < nBins; bin++ ) { @@ -1418,9 +2357,17 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric set_zero( subFrameTotalEne, CLDFB_NO_CHANNELS_MAX ); +#ifdef JBM_TSM_ON_TCS + for ( slot = 0; slot < (uint8_t) hDirAC->subframe_nbslots[subframe]; slot++ ) +#else for ( slot = 0; slot < (uint8_t) hDirAC->subframe_nbslots; slot++ ) +#endif { +#ifdef JBM_TSM_ON_TCS + int16_t slotThis = slot + slot_idx_start; +#else int16_t slotThis = slot + ( hDirAC->subframe_nbslots * subframe ); +#endif for ( bin = 0; bin < nBins; bin++ ) { @@ -1640,8 +2587,10 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric h->frameMeanDiffuseness[bin] += diffEne; frameMeanDiffusenessEneWeight[bin] += meanEnePerCh; } - hDirAC->dirac_read_idx = ( hDirAC->dirac_read_idx + 1 ) % hDirAC->dirac_md_buffer_length; +#ifdef JBM_TSM_ON_TCS + slot_idx_start += hDirAC->subframe_nbslots[subframe]; +#endif } /* Formulate average diffuseness over frame */ @@ -1888,11 +2837,132 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( return; } +#ifdef JBM_TSM_ON_TCS +#ifndef FIX_355_REFACTOR_PARAMBIN_TO_5MS +static void ivas_dirac_dec_binaural_process_output_sf( + Decoder_Struct *st_ivas, + float *output_f[], + float inRe[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + float inIm[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + const int16_t max_band_decorr, + const uint8_t numInChannels ) +{ + uint8_t slot, bin, chA, chB; + int16_t nBins; + float outSlotRe[CLDFB_NO_CHANNELS_MAX], outSlotIm[CLDFB_NO_CHANNELS_MAX]; + float decSlotRe[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], decSlotIm[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + float reverbRe[BINAURAL_CHANNELS][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float reverbIm[BINAURAL_CHANNELS][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + uint16_t numSlots; + DIRAC_DEC_BIN_HANDLE h; + float interpVal; + float *decSlotRePointer; + float *decSlotImPointer; + + numSlots = st_ivas->hDirAC->subframe_nbslots[st_ivas->hDirAC->subframes_rendered]; + h = st_ivas->hDiracDecBin; + nBins = st_ivas->hDirAC->num_freq_bands; + + + interpVal = 0.0f; + for ( slot = 0; slot < numSlots; slot++ ) + { + interpVal += 1.0f / (float) numSlots; + + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) + { + /* Process second / room effect part of binaural output when needed */ + ivas_binaural_reverb_processSlot( st_ivas->hDiracDecBin->hReverb, numInChannels, inRe, inIm, reverbRe, reverbIm, slot ); + } + if ( !st_ivas->hDiracDecBin->useTdDecorr && max_band_decorr > 0 ) + { +#ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS + ivas_dirac_dec_decorrelate_slot( st_ivas->hDirAC, slot, inRe, inIm, decSlotRe, decSlotIm ); +#else + ivas_dirac_dec_decorrelate_slot_sf( st_ivas->hDirAC, slot, inRe, inIm, decSlotRe, decSlotIm ); +#endif + } + + for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + float *outSlotRePr, *outSlotImPr; /* Pointers needed for function call compatibility */ + + set_zero( outSlotRe, CLDFB_NO_CHANNELS_MAX ); + set_zero( outSlotIm, CLDFB_NO_CHANNELS_MAX ); + + /* Processing of the first / HRTF part of the binaural output. */ + for ( chB = 0; chB < numInChannels; chB++ ) + { + if ( st_ivas->hDiracDecBin->useTdDecorr ) + { + decSlotRePointer = inRe[chB + 2][slot]; + decSlotImPointer = inIm[chB + 2][slot]; + } + else + { + decSlotRePointer = decSlotRe[chB]; + decSlotImPointer = decSlotIm[chB]; + } + + for ( bin = 0; bin < nBins; bin++ ) + { + float gain; + + /* Mixing using the formulated processing matrix M */ + gain = ( 1.0f - interpVal ) * h->processMtxRePrev[chA][chB][bin] + + interpVal * h->processMtxRe[chA][chB][bin]; + outSlotRe[bin] += gain * inRe[chB][slot][bin]; + outSlotIm[bin] += gain * inIm[chB][slot][bin]; + + gain = ( 1.0f - interpVal ) * h->processMtxImPrev[chA][chB][bin] + + interpVal * h->processMtxIm[chA][chB][bin]; + outSlotRe[bin] -= gain * inIm[chB][slot][bin]; + outSlotIm[bin] += gain * inRe[chB][slot][bin]; + + /* Mixing decorrelated signals using the formulated residual processing matrix Mdec */ + if ( bin < max_band_decorr && chB < 2 ) + { + gain = ( 1.0f - interpVal ) * h->processMtxDecRePrev[chA][chB][bin] + + interpVal * h->processMtxDecRe[chA][chB][bin]; + outSlotRe[bin] += gain * decSlotRePointer[bin]; + outSlotIm[bin] += gain * decSlotImPointer[bin]; + + gain = ( 1.0f - interpVal ) * h->processMtxDecImPrev[chA][chB][bin] + + interpVal * h->processMtxDecIm[chA][chB][bin]; + outSlotRe[bin] -= gain * decSlotImPointer[bin]; + outSlotIm[bin] += gain * decSlotRePointer[bin]; + } + } + } + + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) + { + /* Combine second (reverb) part with the first (HRTF) part to obtain binaural output signal with room effect */ + v_add( outSlotRe, reverbRe[chA][slot], outSlotRe, CLDFB_NO_CHANNELS_MAX ); + v_add( outSlotIm, reverbIm[chA][slot], outSlotIm, CLDFB_NO_CHANNELS_MAX ); + } + + outSlotRePr = &( outSlotRe[0] ); + outSlotImPr = &( outSlotIm[0] ); + + /* Inverse filter bank */ + cldfbSynthesis( &outSlotRePr, &outSlotImPr, &( output_f[chA][nBins * slot] ), nBins, st_ivas->cldfbSynDec[chA] ); + } + } + + return; +} +#endif +#endif #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS static void ivas_dirac_dec_binaural_process_output( Decoder_Struct *st_ivas, +#ifdef JBM_TSM_ON_TCS + float *output_f[], +#else float output_f[][L_FRAME48k], +#endif float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, @@ -1910,21 +2980,41 @@ static void ivas_dirac_dec_binaural_process_output( float *decSlotRePointer; float *decSlotImPointer; int16_t offsetSamples; +#ifdef JBM_TSM_ON_TCS + int16_t nSlots; +#endif h = st_ivas->hDiracDecBin; nBins = st_ivas->hDirAC->num_freq_bands; +#ifdef JBM_TSM_ON_TCS + offsetSamples = 0; + nSlots = st_ivas->hDirAC->subframe_nbslots[subframe]; +#else offsetSamples = subframe * CLDFB_SLOTS_PER_SUBFRAME * nBins; +#endif if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) { /* Process second / room effect part of binaural output when needed */ +#ifdef JBM_TSM_ON_TCS + ivas_binaural_reverb_processSubframe( st_ivas->hDiracDecBin->hReverb, numInChannels, nSlots, inRe, inIm, reverbRe, reverbIm ); +#else ivas_binaural_reverb_processSubframe( st_ivas->hDiracDecBin->hReverb, numInChannels, inRe, inIm, reverbRe, reverbIm ); +#endif } interpVal = 0.0f; +#ifdef JBM_TSM_ON_TCS + for ( slot = 0; slot < nSlots; slot++ ) +#else for ( slot = 0; slot < CLDFB_SLOTS_PER_SUBFRAME; slot++ ) +#endif { +#ifdef JBM_TSM_ON_TCS + interpVal += 1.0f / (float) nSlots; +#else interpVal += 1.0f / ( (float) CLDFB_SLOTS_PER_SUBFRAME ); +#endif if ( !st_ivas->hDiracDecBin->useTdDecorr && max_band_decorr > 0 ) { ivas_dirac_dec_decorrelate_slot( st_ivas->hDirAC, slot, inRe, inIm, decSlotRe, decSlotIm ); @@ -2112,6 +3202,111 @@ static void ivas_dirac_dec_binaural_process_output( } #endif +#ifdef JBM_TSM_ON_TCS +#ifndef FIX_355_REFACTOR_PARAMBIN_TO_5MS +static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_sf( + HEAD_TRACK_DATA_HANDLE hHeadTrackData, + float inIm[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + float inRe[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + const uint8_t slotEnd, + const uint8_t nBins, + float Rmat[3][3] ) +{ + uint8_t slot, bin, ch; + float tmpVal; + + /* When not currently in prototype signal left-right switching procedure, check if such switching is needed */ + if ( hHeadTrackData->lrSwitchedNext == hHeadTrackData->lrSwitchedCurrent ) + { + float thresholdDotProduct = 0.17f; /* Corresponds to 10-degree switching threshold */ + if ( ( hHeadTrackData->lrSwitchedCurrent == 0 ) && ( Rmat[1][1] < -thresholdDotProduct ) ) + { + hHeadTrackData->lrSwitchedNext = 1; + } + if ( ( hHeadTrackData->lrSwitchedCurrent == 1 ) && ( Rmat[1][1] > thresholdDotProduct ) ) + { + hHeadTrackData->lrSwitchedNext = 0; + } + } + + /* When currently in interpolation */ + if ( hHeadTrackData->lrSwitchedNext != hHeadTrackData->lrSwitchedCurrent ) + { + for ( slot = 0; slot < slotEnd; slot++ ) + { + float switchOrderFactor, origOrderFactor; + + hHeadTrackData->lrSwitchInterpVal += 0.0025f; /* Corresponds to 0.5 seconds interpolation time */ + + if ( hHeadTrackData->lrSwitchInterpVal > 0.999f ) + { + /* Stop interpolation, reset values */ + hHeadTrackData->lrSwitchInterpVal = 0.0f; + hHeadTrackData->lrSwitchedCurrent = hHeadTrackData->lrSwitchedNext; + } + + /* Gains for determining portion of switched channel order and original channel order */ + tmpVal = (float) hHeadTrackData->lrSwitchedNext * hHeadTrackData->lrSwitchInterpVal; + tmpVal += (float) hHeadTrackData->lrSwitchedCurrent * ( 1.0f - hHeadTrackData->lrSwitchInterpVal ); + switchOrderFactor = sqrtf( tmpVal ); + origOrderFactor = sqrtf( 1.0f - tmpVal ); + + for ( bin = 0; bin < nBins; bin++ ) + { + /* determine original order (1) signals and switched order (2) signals */ + float re1[BINAURAL_CHANNELS], re2[BINAURAL_CHANNELS], im1[BINAURAL_CHANNELS], im2[BINAURAL_CHANNELS]; + + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + re1[ch] = inRe[ch][slot][bin] * origOrderFactor; + re2[ch] = inRe[1 - ch][slot][bin] * switchOrderFactor; + im1[ch] = inIm[ch][slot][bin] * origOrderFactor; + im2[ch] = inIm[1 - ch][slot][bin] * switchOrderFactor; + } + + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + float eneRef, ene, eq; + + /* Interpolate / mix original and switched order signals */ + inRe[ch][slot][bin] = re1[ch] + re2[ch]; + inIm[ch][slot][bin] = im1[ch] + im2[ch]; + + /* Equalize interpolated signals to preserve energy per bin */ + eneRef = ( re1[ch] * re1[ch] ) + ( re2[ch] * re2[ch] ) + ( im1[ch] * im1[ch] ) + ( im2[ch] * im2[ch] ); + ene = ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] ); + eq = sqrtf( eneRef / fmaxf( 1e-12f, ene ) ); + eq = fminf( 4.0f, eq ); + inRe[ch][slot][bin] *= eq; + inIm[ch][slot][bin] *= eq; + } + } + } + } + else + { + /* If not in interpolation, but in switched prototype situation, then switch left and right channels */ + if ( hHeadTrackData->lrSwitchedCurrent == 1 ) + { + for ( slot = 0; slot < slotEnd; slot++ ) + { + for ( bin = 0; bin < nBins; bin++ ) + { + tmpVal = inRe[0][slot][bin]; + inRe[0][slot][bin] = inRe[1][slot][bin]; + inRe[1][slot][bin] = tmpVal; + tmpVal = inIm[0][slot][bin]; + inIm[0][slot][bin] = inIm[1][slot][bin]; + inIm[1][slot][bin] = tmpVal; + } + } + } + } + + return; +} +#endif +#endif #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS static void adaptTransportSignalsHeadtracked( @@ -2119,6 +3314,9 @@ static void adaptTransportSignalsHeadtracked( float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nBins, +#ifdef JBM_TSM_ON_TCS + const int16_t nSlots, +#endif float Rmat[3][3] ) { int16_t slot, ch, bin, louderCh; @@ -2150,7 +3348,11 @@ static void adaptTransportSignalsHeadtracked( for ( ch = 0; ch < 2; ch++ ) { ch_nrg[ch] = 0.0f; +#ifdef JBM_TSM_ON_TCS + for ( slot = 0; slot < nSlots; slot++ ) +#else for ( slot = 0; slot < CLDFB_SLOTS_PER_SUBFRAME; slot++ ) +#endif { for ( bin = bin_lo; bin < bin_hi; bin++ ) { @@ -2186,7 +3388,11 @@ static void adaptTransportSignalsHeadtracked( { float band_nrg = 0.0f; +#ifdef JBM_TSM_ON_TCS + for ( slot = 0; slot < nSlots; slot++ ) +#else for ( slot = 0; slot < CLDFB_SLOTS_PER_SUBFRAME; slot++ ) +#endif { for ( bin = bin_lo; bin < bin_hi; bin++ ) { @@ -2212,7 +3418,11 @@ static void adaptTransportSignalsHeadtracked( ene_proc = hHeadTrackData->procChEneIIR[0][band_idx] + hHeadTrackData->procChEneIIR[1][band_idx]; eqVal = fminf( 4.0f, sqrtf( ene_target / fmaxf( 1e-12f, ene_proc ) ) ); +#ifdef JBM_TSM_ON_TCS + for ( slot = 0; slot < nSlots; slot++ ) +#else for ( slot = 0; slot < CLDFB_SLOTS_PER_SUBFRAME; slot++ ) +#endif { for ( ch = 0; ch < 2; ch++ ) { @@ -2368,6 +3578,9 @@ static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( const uint8_t firstSlot, const uint8_t slotEnd, const uint8_t nBins, +#endif +#ifdef JBM_TSM_ON_TCS + const int16_t nSlots, #endif float Rmat[3][3] ) { @@ -2396,7 +3609,11 @@ static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( if ( hHeadTrackData->lrSwitchedNext != hHeadTrackData->lrSwitchedCurrent ) { #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS +#ifdef JBM_TSM_ON_TCS + for ( slot = 0; slot < nSlots; slot++ ) +#else for ( slot = 0; slot < CLDFB_SLOTS_PER_SUBFRAME; slot++ ) +#endif #else for ( slot = firstSlot; slot < slotEnd; slot++ ) #endif @@ -2456,7 +3673,11 @@ static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( if ( hHeadTrackData->lrSwitchedCurrent == 1 ) { #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS +#ifdef JBM_TSM_ON_TCS + for ( slot = 0; slot < nSlots; slot++ ) +#else for ( slot = 0; slot < CLDFB_SLOTS_PER_SUBFRAME; slot++ ) +#endif #else for ( slot = firstSlot; slot < slotEnd; slot++ ) #endif diff --git a/lib_rend/ivas_limiter.c b/lib_rend/ivas_limiter.c index 28c272bc0c820c180908817035d9446a12d6b819..7875165e51d0ce47be819eba3bd6124fe92061be 100644 --- a/lib_rend/ivas_limiter.c +++ b/lib_rend/ivas_limiter.c @@ -171,11 +171,15 @@ void ivas_limiter_close( *-------------------------------------------------------------------*/ void ivas_limiter_dec( - IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ + IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ +#ifdef JBM_TSM_ON_TCS + float *output[MAX_OUTPUT_CHANNELS], /* i/o: input/output buffer */ +#else float output[MAX_OUTPUT_CHANNELS][L_FRAME48k], /* i/o: input/output buffer */ - const int16_t num_channels, /* i : number of channels to be processed */ - const int16_t output_frame, /* i : number of samples per channel in the buffer */ - const int16_t BER_detect /* i : BER detect flag */ +#endif + const int16_t num_channels, /* i : number of channels to be processed */ + const int16_t output_frame, /* i : number of samples per channel in the buffer */ + const int16_t BER_detect /* i : BER detect flag */ ) { int16_t c; diff --git a/lib_rend/ivas_objectRenderer.c b/lib_rend/ivas_objectRenderer.c index 540a03f4518a7b6d7a5b118c39ed7879a3578762..83db83293750b00ae85ae5b3a5f721d9c2a0da84 100644 --- a/lib_rend/ivas_objectRenderer.c +++ b/lib_rend/ivas_objectRenderer.c @@ -50,6 +50,7 @@ * Local function prototypes *---------------------------------------------------------------------*/ + static void TDREND_Clear_Update_flags( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd ); static void angles_to_vec( const float radius, const float azimuth, const float elevation, float *vec ); @@ -264,14 +265,27 @@ ivas_error ivas_td_binaural_renderer_unwrap( const int16_t Opt_Headrotation, /* i : Head rotation flag */ const IVAS_QUATERNION *Quaternions, /* i : Head tracking data per subframe */ const IVAS_VECTOR3 *Pos, /* i : Listener position data per subframe */ - float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ - const int16_t output_frame /* i : output frame length */ +#ifdef JBM_TSM_ON_TCS + float *output[], /* i/o: SCE channels / Binaural synthesis */ +#else + float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ +#endif + const int16_t output_frame /* i : output frame length */ ) { int16_t subframe_length; int16_t subframe_idx; float reverb_signal[BINAURAL_CHANNELS][L_FRAME48k]; ivas_error error; +#ifdef JBM_TSM_ON_TCS + float *p_reverb_signal[BINAURAL_CHANNELS]; + int16_t ch; + + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + p_reverb_signal[ch] = reverb_signal[ch]; + } +#endif subframe_length = output_frame / MAX_PARAM_SPATIAL_SUBFRAMES; @@ -285,7 +299,11 @@ ivas_error ivas_td_binaural_renderer_unwrap( if ( hReverb != NULL && hReverb->pConfig.roomAcoustics.late_reverb_on ) { +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_reverb_process( hReverb, transport_config, 0, output, p_reverb_signal, subframe_idx ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_reverb_process( hReverb, transport_config, 0, output, reverb_signal, subframe_idx ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -318,9 +336,13 @@ ivas_error ivas_td_binaural_renderer_unwrap( ivas_error TDREND_GetMix( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - float output[][L_FRAME48k], /* i/o: ISM object synth / rendered output in 0,1 */ - const int16_t subframe_length, /* i/o: subframe length */ - const int16_t subframe_idx /* i : Subframe index to 5 ms subframe */ +#ifdef JBM_TSM_ON_TCS + float *output[], /* i/o: ISM object synth / rendered output in 0,1 */ +#else + float output[][L_FRAME48k], /* i/o: ISM object synth / rendered output in 0,1 */ +#endif + const int16_t subframe_length, /* i/o: subframe length */ + const int16_t subframe_idx /* i : Subframe index to 5 ms subframe */ ) { int16_t i; @@ -429,7 +451,11 @@ void TDREND_Update_object_positions( const int16_t lfe_idx, /* i : Input LFE index */ const IVAS_FORMAT in_format, /* i : Format of input sources */ const ISM_METADATA_HANDLE *hIsmMetaData, /* i : Input metadata for ISM objects */ - float output[][L_FRAME48k] /* i/o: SCE/MC channels */ +#ifdef JBM_TSM_ON_TCS + float *output[] +#else + float output[][L_FRAME48k] /* i/o: SCE/MC channels */ +#endif ) { TDREND_DirAtten_t *DirAtten_p; @@ -621,6 +647,15 @@ ivas_error ivas_td_binaural_renderer_ext( IVAS_REND_AudioConfigType inConfigType; AUDIO_CONFIG transport_config; ivas_error error; +#ifdef JBM_TSM_ON_TCS + float *p_output[MAX_OUTPUT_CHANNELS]; + int16_t ch; + + for ( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ ) + { + p_output[ch] = output[ch]; + } +#endif push_wmops( "ivas_td_binaural_renderer_ext" ); @@ -661,9 +696,16 @@ ivas_error ivas_td_binaural_renderer_ext( #endif } +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_td_binaural_renderer_unwrap( hReverb, transport_config, pTDRend->hBinRendererTd, num_src, lfe_idx, ivas_format, hIsmMetaData, headRotData->headRotEnabled, + ( headRotData != NULL ) ? headRotData->headPositions : NULL, + ( headRotData != NULL ) ? headRotData->Pos : NULL, p_output, output_frame ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_td_binaural_renderer_unwrap( hReverb, transport_config, pTDRend->hBinRendererTd, num_src, lfe_idx, ivas_format, hIsmMetaData, headRotData->headRotEnabled, ( headRotData != NULL ) ? headRotData->headPositions : NULL, ( headRotData != NULL ) ? headRotData->Pos : NULL, output, output_frame ) ) != IVAS_ERR_OK ) + +#endif { return error; } diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index efa211124382f4c05ce4b3e77df0724c1608625a..b43a048f38f901638e8e2885fa4da2d0feaaf0fc 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -92,7 +92,11 @@ void ivas_limiter_close( void ivas_limiter_dec ( IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ +#ifdef JBM_TSM_ON_TCS + float *output[MAX_OUTPUT_CHANNELS], /* i/o: input/output buffer */ +#else float output[MAX_OUTPUT_CHANNELS][L_FRAME48k], /* i/o: input/output buffer */ +#endif const int16_t num_channels, /* i : number of channels to be processed */ const int16_t output_frame, /* i : number of samples per channel in the buffer */ const int16_t BER_detect /* i : BER detect flag */ @@ -165,6 +169,17 @@ void ivas_dirac_dec_binaural( const int16_t nchan_transport /* i : number of transport channels */ ); +#ifdef JBM_TSM_ON_TCS +void ivas_dirac_dec_binaural_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ + uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ + uint16_t *nSamplesAvailable, /* o : number of CLDFB slots still to render */ + const int16_t nchan_transport, + float *output_f[] /* o : rendered time signal */ +); +#endif + ivas_error ivas_dirac_dec_init_binaural_data( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : HRTF structure for rendering */ @@ -231,7 +246,11 @@ ivas_error ivas_td_binaural_renderer_unwrap( const int16_t Opt_Headrotation, /* i : Head rotation flag */ const IVAS_QUATERNION *Quaternions, /* i : Head tracking data per subframe */ const IVAS_VECTOR3 *Pos, /* i : Listener position data per subframe */ - float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ +#ifdef JBM_TSM_ON_TCS + float *output[], /* i/o: SCE channels / Binaural synthesis */ +#else + float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ +#endif const int16_t output_frame /* i : output frame length */ ); @@ -273,7 +292,11 @@ void ivas_td_binaural_close( ivas_error TDREND_GetMix( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ +#ifdef JBM_TSM_ON_TCS + float *output[], /* i/o: ISM object synth / rendered output in 0,1 */ +#else float output[][L_FRAME48k], /* i/o: ISM object synth / rendered output in 0,1 */ +#endif const int16_t subframe_length, /* i/o: subframe length */ const int16_t subframe_idx /* i : Subframe index to 5 ms subframe */ ); @@ -291,7 +314,11 @@ void TDREND_Update_object_positions( const int16_t lfe_idx, /* i : Input LFE index */ const IVAS_FORMAT in_format, /* i : Format of input sources */ const ISM_METADATA_HANDLE *hIsmMetaData, /* i : Input metadata for ISM objects */ +#ifdef JBM_TSM_ON_TCS + float *output[] /* i/o: SCE/MC channels */ +#else float output[][L_FRAME48k] /* i/o: SCE/MC channels */ +#endif ); void BSplineModelEvalDealloc( @@ -507,11 +534,29 @@ ivas_error ivas_rend_crendProcess( HEAD_TRACK_DATA_HANDLE hHeadTrackData, IVAS_OUTPUT_SETUP_HANDLE hIntSetup, EFAP_HANDLE hEFAPdata, +#ifdef JBM_TSM_ON_TCS + float *output[], /* i/o: input/output audio channels */ +#else float output[][L_FRAME48k], /* i/o: input/output audio channels */ +#endif const int32_t output_Fs ); - +#ifdef JBM_TSM_ON_TCS +ivas_error ivas_rend_crendProcessSubframe( + const CREND_WRAPPER *pCrend, + const AUDIO_CONFIG inConfig, + const AUDIO_CONFIG outConfig, + DECODER_CONFIG_HANDLE hDecoderConfig, + HEAD_TRACK_DATA_HANDLE hHeadTrackData, + IVAS_OUTPUT_SETUP_HANDLE hIntSetup, + EFAP_HANDLE hEFAPdata, + DECODER_TC_BUFFER_HANDLE hTcBuffer, + float *input_f[], + float *output[], /* i/o: input/output audio channels */ + const int16_t n_samples_to_render, + const int32_t output_Fs ); +#endif ivas_error ivas_crend_init_from_rom( @@ -555,6 +600,9 @@ void ivas_binaural_reverb_close( void ivas_binaural_reverb_processSubframe( REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ const int16_t numInChannels, /* i : num input channels to be processed */ +#ifdef JBM_TSM_ON_TCS + const int16_t numSlots, /* i : number of slots to be processed */ +#endif float inReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data real */ float inImag[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data imag */ float outReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data real */ @@ -572,6 +620,20 @@ void ivas_binaural_reverb_processFrame( ); #endif +#ifdef JBM_TSM_ON_TCS +#ifndef FIX_355_REFACTOR_PARAMBIN_TO_5MS +void ivas_binaural_reverb_processSlot( + REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ + const int16_t numInChannels, /* i : num inputs to be processed */ + float inReal[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data real, Comment: This change swaps two first dimensions as first dimension is not constant. */ + float inImag[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data imag */ + float outReal[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data real */ + float outImag[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data imag */ + const uint8_t offsetSamplesIO /* i : number of offset samples */ +); +#endif +#endif + ivas_error ivas_reverb_open( REVERB_HANDLE *hReverb, /* i/o: Reverberator handle */ const AUDIO_CONFIG input_audio_config, /* i : reverb. input audio configuration */ @@ -588,8 +650,13 @@ ivas_error ivas_reverb_process( const REVERB_HANDLE hReverb, /* i : Reverberator handle */ const AUDIO_CONFIG input_audio_config, /* i : reverb. input audio configuration */ const int16_t mix_signals, /* i : add reverb to output signal */ +#ifdef JBM_TSM_ON_TCS + float *pcm_in[], /* i : the PCM audio to apply reverb on */ + float *pcm_out[], /* o : the PCM audio with reverb applied */ +#else float pcm_in[][L_FRAME48k], /* i : the PCM audio to apply reverb on */ float pcm_out[][L_FRAME48k], /* o : the PCM audio with reverb applied */ +#endif const int16_t i_ts /* i : subframe index */ ); @@ -812,7 +879,11 @@ void SHrotmatgen( void rotateFrame_shd( HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */ - float output[][L_FRAME48k], /* i/o: unrotated HOA3 signal buffer in TD */ +#ifdef JBM_TSM_ON_TCS + float *output[], /* i/o: unrotated HOA3 signal buffer in TD */ +#else + float output[][L_FRAME48k], /* i/o: unrotated HOA3 signal buffer in TD */ +#endif const int16_t subframe_len, /* i : subframe length per channel */ const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */ const int16_t subframe_idx /* i : subframe index */ @@ -820,7 +891,11 @@ void rotateFrame_shd( void rotateFrame_sd( HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */ - float output[][L_FRAME48k], /* i/o: unrotated SD signal buffer in TD */ +#ifdef JBM_TSM_ON_TCS + float *output[], /* i/o: unrotated SD signal buffer in TD */ +#else + float output[][L_FRAME48k], /* i/o: unrotated SD signal buffer in TD */ +#endif const int16_t subframe_len, /* i : subframe length per channel */ const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */ const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ @@ -832,6 +907,9 @@ void rotateFrame_shd_cldfb( float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain imag part */ float Rmat[3][3], /* i : real-space rotation matrix */ const int16_t nInChannels, /* i : number of channels */ +#ifdef JBM_TSM_ON_TCS + const int16_t numTimeSlots, /* i : number of time slots to process */ +#endif const int16_t shd_rot_max_order /* i : split-order rotation method */ ); @@ -841,6 +919,9 @@ void rotateFrame_sd_cldfb( float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain imag part */ const IVAS_OUTPUT_SETUP_HANDLE hOutputSetup, /* i : output format setup number of channels */ const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ +#ifdef JBM_TSM_ON_TCS + const int16_t numTimeSlots, /* i : number of time slots to process */ +#endif const int16_t nb_band /* i : number of CLDFB bands to process */ ); diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c index af2717cc11a01fbe8a5bb9e41e33ca1b7a4f5dc9..12a8b55ddbcbdd2e053170d24711c20ab5d7bddd 100644 --- a/lib_rend/ivas_reverb.c +++ b/lib_rend/ivas_reverb.c @@ -1437,7 +1437,11 @@ static void reverb_block( static ivas_error downmix_input_block( const REVERB_HANDLE hReverb, +#ifdef JBM_TSM_ON_TCS + float *pcm_in[], +#else float pcm_in[][L_FRAME48k], +#endif const AUDIO_CONFIG input_audio_config, float *pPcm_out, const int16_t input_offset ) @@ -1579,9 +1583,14 @@ ivas_error ivas_reverb_process( const REVERB_HANDLE hReverb, /* i : Reverberator handle */ const AUDIO_CONFIG input_audio_config, /* i : reverb. input audio configuration */ const int16_t mix_signals, /* i : add reverb to output signal */ - float pcm_in[][L_FRAME48k], /* i : the PCM audio to apply reverb on */ - float pcm_out[][L_FRAME48k], /* o : the PCM audio with reverb applied */ - const int16_t i_ts /* i : subframe index */ +#ifdef JBM_TSM_ON_TCS + float *pcm_in[], /* i : the PCM audio to apply reverb on */ + float *pcm_out[], /* o : the PCM audio with reverb applied */ +#else + float pcm_in[][L_FRAME48k], /* i : the PCM audio to apply reverb on */ + float pcm_out[][L_FRAME48k], /* o : the PCM audio with reverb applied */ +#endif + const int16_t i_ts /* i : subframe index */ ) { float tmp0[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp1[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp2[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; @@ -1618,8 +1627,11 @@ ivas_error ivas_reverb_process( #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS void ivas_binaural_reverb_processSubframe( - REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ - const int16_t numInChannels, /* i : num inputs to be processed */ + REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ + const int16_t numInChannels, /* i : num inputs to be processed */ +#ifdef JBM_TSM_ON_TCS + const int16_t numSlots, /* i : number of slots to be processed */ +#endif float inReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data real, Comment: This change swaps two first dimensions as first dimension is not constant. */ float inImag[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data imag */ float outReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data real */ @@ -1640,12 +1652,24 @@ void ivas_binaural_reverb_processFrame( /* Declare the required variables */ int16_t idx, bin, ch, sample, invertSampleIndex, tapIdx, *phaseShiftTypePr; float **tapRealPr, **tapImagPr; + push_wmops( "binaural_reverb" ); /* 1) Rotate the data in the loop buffer of the reverberator. * Notice that the audio at the loop buffers is at time-inverted order * for convolution purposes later on. */ for ( bin = 0; bin < hReverb->numBins; bin++ ) { +#ifdef JBM_TSM_ON_TCS + /* Move the data forwards by blockSize (i.e. by the frame size of 16 CLDFB slots) */ + mvr2r( hReverb->loopBufReal[bin], hReverb->loopBufReal[bin] + numSlots, hReverb->loopBufLength[bin] ); + mvr2r( hReverb->loopBufImag[bin], hReverb->loopBufImag[bin] + numSlots, hReverb->loopBufLength[bin] ); + + /* Add the data from the end of the loop to the beginning, with an attenuation factor + * according to RT60. This procedure generates an IIR decaying response. The response + * is decorrelated later on. */ + v_multc( hReverb->loopBufReal[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor[bin], hReverb->loopBufReal[bin], numSlots ); + v_multc( hReverb->loopBufImag[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor[bin], hReverb->loopBufImag[bin], numSlots ); +#else /* Move the data forwards by blockSize (i.e. by the frame size of 16 CLDFB slots) */ mvr2r( hReverb->loopBufReal[bin], hReverb->loopBufReal[bin] + hReverb->blockSize, hReverb->loopBufLength[bin] ); mvr2r( hReverb->loopBufImag[bin], hReverb->loopBufImag[bin] + hReverb->blockSize, hReverb->loopBufLength[bin] ); @@ -1655,17 +1679,27 @@ void ivas_binaural_reverb_processFrame( * is decorrelated later on. */ v_multc( hReverb->loopBufReal[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor[bin], hReverb->loopBufReal[bin], hReverb->blockSize ); v_multc( hReverb->loopBufImag[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor[bin], hReverb->loopBufImag[bin], hReverb->blockSize ); +#endif } /* 2) Apply the determined pre-delay to the input audio, and add the delayed audio to the loop. */ idx = hReverb->preDelayBufferIndex; +#ifdef JBM_TSM_ON_TCS + for ( sample = 0; sample < numSlots; sample++ ) +#else for ( sample = 0; sample < hReverb->blockSize; sample++ ) +#endif { #ifndef FIX_355_REFACTOR_PARAMBIN_TO_5MS uint16_t sampleWithOffset; sampleWithOffset = sample + offsetSamplesIO; #endif +#ifdef JBM_TSM_ON_TCS + invertSampleIndex = numSlots - sample - 1; +#else invertSampleIndex = hReverb->blockSize - sample - 1; +#endif + for ( bin = 0; bin < hReverb->numBins; bin++ ) { /* Add from pre-delay buffer a sample to the loop buffer, in a time-inverted order. @@ -1721,17 +1755,41 @@ void ivas_binaural_reverb_processFrame( /* These tap pointers have been determined to point to the loop buffer at sparse locations */ tapRealPr = hReverb->tapPointersReal[bin][ch]; tapImagPr = hReverb->tapPointersImag[bin][ch]; + phaseShiftTypePr = hReverb->tapPhaseShiftType[bin][ch]; /* Flush output */ +#ifdef JBM_TSM_ON_TCS + set_f( hReverb->outputBufferReal[bin][ch], 0.0f, numSlots ); + set_f( hReverb->outputBufferImag[bin][ch], 0.0f, numSlots ); +#else set_f( hReverb->outputBufferReal[bin][ch], 0.0f, hReverb->blockSize ); set_f( hReverb->outputBufferImag[bin][ch], 0.0f, hReverb->blockSize ); +#endif /* Add from temporally decaying sparse tap locations the audio to the output. */ for ( tapIdx = 0; tapIdx < hReverb->taps[bin][ch]; tapIdx++ ) { switch ( phaseShiftTypePr[tapIdx] ) { +#ifdef JBM_TSM_ON_TCS + case 0: /* 0 degrees phase */ + v_add( hReverb->outputBufferReal[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferReal[bin][ch], numSlots ); + v_add( hReverb->outputBufferImag[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferImag[bin][ch], numSlots ); + break; + case 1: /* 90 degrees phase */ + v_sub( hReverb->outputBufferReal[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferReal[bin][ch], numSlots ); + v_add( hReverb->outputBufferImag[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferImag[bin][ch], numSlots ); + break; + case 2: /* 180 degrees phase */ + v_sub( hReverb->outputBufferReal[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferReal[bin][ch], numSlots ); + v_sub( hReverb->outputBufferImag[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferImag[bin][ch], numSlots ); + break; + default: /* 270 degrees phase */ + v_add( hReverb->outputBufferReal[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferReal[bin][ch], numSlots ); + v_sub( hReverb->outputBufferImag[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferImag[bin][ch], numSlots ); + break; +#else case 0: /* 0 degrees phase */ v_add( hReverb->outputBufferReal[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferReal[bin][ch], hReverb->blockSize ); v_add( hReverb->outputBufferImag[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferImag[bin][ch], hReverb->blockSize ); @@ -1748,6 +1806,7 @@ void ivas_binaural_reverb_processFrame( v_add( hReverb->outputBufferReal[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferReal[bin][ch], hReverb->blockSize ); v_sub( hReverb->outputBufferImag[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferImag[bin][ch], hReverb->blockSize ); break; +#endif } } } @@ -1757,7 +1816,11 @@ void ivas_binaural_reverb_processFrame( { if ( hReverb->useBinauralCoherence ) { +#ifdef JBM_TSM_ON_TCS + for ( sample = 0; sample < numSlots; sample++ ) +#else for ( sample = 0; sample < hReverb->blockSize; sample++ ) +#endif { float leftRe, rightRe, leftIm, rightIm; @@ -1778,15 +1841,23 @@ void ivas_binaural_reverb_processFrame( /* 4) Write data to output */ for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { +#ifdef JBM_TSM_ON_TCS + for ( sample = 0; sample < numSlots; sample++ ) +#else for ( sample = 0; sample < hReverb->blockSize; sample++ ) +#endif { #ifndef FIX_355_REFACTOR_PARAMBIN_TO_5MS uint16_t sampleWithOffset; sampleWithOffset = sample + offsetSamplesIO; #endif - /* Audio was in the temporally inverted order for convolution, re-invert audio to output */ +/* Audio was in the temporally inverted order for convolution, re-invert audio to output */ +#ifdef JBM_TSM_ON_TCS + invertSampleIndex = numSlots - sample - 1; +#else invertSampleIndex = hReverb->blockSize - sample - 1; +#endif #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS for ( bin = 0; bin < hReverb->numBins; bin++ ) @@ -1814,9 +1885,180 @@ void ivas_binaural_reverb_processFrame( } } + pop_wmops(); return; } +#ifdef JBM_TSM_ON_TCS +#ifndef FIX_355_REFACTOR_PARAMBIN_TO_5MS +/*------------------------------------------------------------------------- + * ivas_binaural_reverb_processSlot() + * + * Compute the reverberation - room effect + *------------------------------------------------------------------------*/ + +void ivas_binaural_reverb_processSlot( + REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ + const int16_t numInChannels, /* i : num inputs to be processed */ + float inReal[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data real, Comment: This change swaps two first dimensions as first dimension is not constant. */ + float inImag[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data imag */ + float outReal[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data real */ + float outImag[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data imag */ + const uint8_t offsetSamplesIO /* i : number of offset samples */ +) +{ + /* Declare the required variables */ + int16_t idx, bin, ch, sample, invertSampleIndex, tapIdx, *phaseShiftTypePr; + float **tapRealPr, **tapImagPr; + +#ifdef DEBUGGING + assert( hReverb->blockSize == 1 ); +#endif + + push_wmops( "binaural_reverb" ); + /* 1) Rotate the data in the loop buffer of the reverberator. + * Notice that the audio at the loop buffers is at time-inverted order + * for convolution purposes later on. */ + for ( bin = 0; bin < hReverb->numBins; bin++ ) + { + /* Move the data forwards by blockSize (i.e. by the frame size of 16 CLDFB slots) */ + mvr2r( hReverb->loopBufReal[bin], hReverb->loopBufReal[bin] + hReverb->blockSize, hReverb->loopBufLength[bin] ); + mvr2r( hReverb->loopBufImag[bin], hReverb->loopBufImag[bin] + hReverb->blockSize, hReverb->loopBufLength[bin] ); + + /* Add the data from the end of the loop to the beginning, with an attenuation factor + * according to RT60. This procedure generates an IIR decaying response. The response + * is decorrelated later on. */ + v_multc( hReverb->loopBufReal[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor[bin], hReverb->loopBufReal[bin], hReverb->blockSize ); + v_multc( hReverb->loopBufImag[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor[bin], hReverb->loopBufImag[bin], hReverb->blockSize ); + } + + /* 2) Apply the determined pre-delay to the input audio, and add the delayed audio to the loop. */ + idx = hReverb->preDelayBufferIndex; + for ( sample = 0; sample < hReverb->blockSize; sample++ ) + { + uint16_t sampleWithOffset; + sampleWithOffset = sample + offsetSamplesIO; + invertSampleIndex = hReverb->blockSize - sample - 1; + for ( bin = 0; bin < hReverb->numBins; bin++ ) + { + /* Add from pre-delay buffer a sample to the loop buffer, in a time-inverted order. + * Also apply the spectral gains determined for the reverberation */ + hReverb->loopBufReal[bin][invertSampleIndex] += hReverb->preDelayBufferReal[idx][bin] * hReverb->reverbEqGains[bin]; + hReverb->loopBufImag[bin][invertSampleIndex] += hReverb->preDelayBufferImag[idx][bin] * hReverb->reverbEqGains[bin]; + hReverb->preDelayBufferReal[idx][bin] = 0.0f; + hReverb->preDelayBufferImag[idx][bin] = 0.0f; + } + + /* Add every second input channel as is to the pre-delay buffer, and every second input channel with + * 90 degrees phase shift to reduce energy imbalances between coherent and incoherent sounds */ + for ( ch = 0; ch < numInChannels; ch++ ) + { + if ( ch % 2 ) + { + v_add( hReverb->preDelayBufferReal[idx], inReal[ch][sampleWithOffset], hReverb->preDelayBufferReal[idx], hReverb->numBins ); + v_add( hReverb->preDelayBufferImag[idx], inImag[ch][sampleWithOffset], hReverb->preDelayBufferImag[idx], hReverb->numBins ); + } + else + { + v_sub( hReverb->preDelayBufferReal[idx], inImag[ch][sampleWithOffset], hReverb->preDelayBufferReal[idx], hReverb->numBins ); + v_add( hReverb->preDelayBufferImag[idx], inReal[ch][sampleWithOffset], hReverb->preDelayBufferImag[idx], hReverb->numBins ); + } + } + idx = ( idx + 1 ) % hReverb->preDelayBufferLength; + } + hReverb->preDelayBufferIndex = idx; + + /* 3) Perform the filtering/decorrelating, using complex and sparse FIR filtering */ + for ( bin = 0; bin < hReverb->numBins; bin++ ) + { + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + /* These tap pointers have been determined to point to the loop buffer at sparse locations */ + tapRealPr = hReverb->tapPointersReal[bin][ch]; + tapImagPr = hReverb->tapPointersImag[bin][ch]; + phaseShiftTypePr = hReverb->tapPhaseShiftType[bin][ch]; + + /* Flush output */ + set_f( hReverb->outputBufferReal[bin][ch], 0.0f, hReverb->blockSize ); + set_f( hReverb->outputBufferImag[bin][ch], 0.0f, hReverb->blockSize ); + + /* Add from temporally decaying sparse tap locations the audio to the output. */ + for ( tapIdx = 0; tapIdx < hReverb->taps[bin][ch]; tapIdx++ ) + { + switch ( phaseShiftTypePr[tapIdx] ) + { + case 0: /* 0 degrees phase */ + v_add( hReverb->outputBufferReal[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferReal[bin][ch], hReverb->blockSize ); + v_add( hReverb->outputBufferImag[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferImag[bin][ch], hReverb->blockSize ); + break; + case 1: /* 90 degrees phase */ + v_sub( hReverb->outputBufferReal[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferReal[bin][ch], hReverb->blockSize ); + v_add( hReverb->outputBufferImag[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferImag[bin][ch], hReverb->blockSize ); + break; + case 2: /* 180 degrees phase */ + v_sub( hReverb->outputBufferReal[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferReal[bin][ch], hReverb->blockSize ); + v_sub( hReverb->outputBufferImag[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferImag[bin][ch], hReverb->blockSize ); + break; + default: /* 270 degrees phase */ + v_add( hReverb->outputBufferReal[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferReal[bin][ch], hReverb->blockSize ); + v_sub( hReverb->outputBufferImag[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferImag[bin][ch], hReverb->blockSize ); + break; + } + } + } + + /* Generate diffuse field binaural coherence by mixing the incoherent reverberated channels with pre-defined gains */ + if ( bin <= hReverb->highestBinauralCoherenceBin ) + { + if ( hReverb->useBinauralCoherence ) + { + for ( sample = 0; sample < hReverb->blockSize; sample++ ) + { + float leftRe, rightRe, leftIm, rightIm; + + leftRe = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferReal[bin][0][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferReal[bin][1][sample]; + rightRe = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferReal[bin][1][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferReal[bin][0][sample]; + leftIm = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferImag[bin][0][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferImag[bin][1][sample]; + rightIm = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferImag[bin][1][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferImag[bin][0][sample]; + + hReverb->outputBufferReal[bin][0][sample] = leftRe; + hReverb->outputBufferReal[bin][1][sample] = rightRe; + hReverb->outputBufferImag[bin][0][sample] = leftIm; + hReverb->outputBufferImag[bin][1][sample] = rightIm; + } + } + } + } + + /* 4) Write data to output */ + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + for ( sample = 0; sample < hReverb->blockSize; sample++ ) + { + uint16_t sampleWithOffset; + + sampleWithOffset = sample + offsetSamplesIO; + /* Audio was in the temporally inverted order for convolution, re-invert audio to output */ + invertSampleIndex = hReverb->blockSize - sample - 1; + + for ( bin = 0; bin < hReverb->numBins; bin++ ) + { + outReal[ch][sampleWithOffset][bin] = hReverb->outputBufferReal[bin][ch][invertSampleIndex]; + outImag[ch][sampleWithOffset][bin] = hReverb->outputBufferImag[bin][ch][invertSampleIndex]; + } + for ( ; bin < CLDFB_NO_CHANNELS_MAX; bin++ ) + { + outReal[ch][sampleWithOffset][bin] = 0.0f; + outImag[ch][sampleWithOffset][bin] = 0.0f; + } + } + } + + pop_wmops(); + return; +} +#endif +#endif /*------------------------------------------------------------------------- * ivas_binaural_reverb_open() diff --git a/lib_rend/ivas_rotation.c b/lib_rend/ivas_rotation.c index 4d9eeef3d5f228f8514d21fc80c52835a7d93cbe..5719e2ffddf4f5079d8d6dde0922434cd679115b 100644 --- a/lib_rend/ivas_rotation.c +++ b/lib_rend/ivas_rotation.c @@ -261,10 +261,14 @@ void rotateAziEle( void rotateFrame_shd( HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */ - float output[][L_FRAME48k], /* i/o: unrotated HOA3 signal buffer in TD */ - const int16_t subframe_len, /* i : subframe length per channel */ - const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */ - const int16_t subframe_idx /* i : subframe index */ +#ifdef JBM_TSM_ON_TCS + float *output[], /* i/o: unrotated HOA3 signal buffer in TD */ +#else + float output[][L_FRAME48k], /* i/o: unrotated HOA3 signal buffer in TD */ +#endif + const int16_t subframe_len, /* i : subframe length per channel */ + const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */ + const int16_t subframe_idx /* i : subframe index */ ) { int16_t i, l, n, m; @@ -364,11 +368,15 @@ void rotateFrame_shd( void rotateFrame_sd( HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */ - float output[][L_FRAME48k], /* i/o: unrotated SD signal buffer in TD */ - const int16_t subframe_len, /* i : subframe length per channel */ - const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */ - const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ - const int16_t subframe_idx /* i : subframe index */ +#ifdef JBM_TSM_ON_TCS + float *output[], /* i/o: unrotated SD signal buffer in TD */ +#else + float output[][L_FRAME48k], /* i/o: unrotated SD signal buffer in TD */ +#endif + const int16_t subframe_len, /* i : subframe length per channel */ + const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */ + const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ + const int16_t subframe_idx /* i : subframe index */ ) { int16_t i, j; @@ -502,7 +510,10 @@ void rotateFrame_shd_cldfb( float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain imag part */ float Rmat[3][3], /* i : real-space rotation matrix */ const int16_t nInChannels, /* i : number of channels */ - const int16_t shd_rot_max_order /* i : split-order rotation method */ +#ifdef JBM_TSM_ON_TCS + const int16_t numTimeSlots, +#endif + const int16_t shd_rot_max_order /* i : split-order rotation method */ ) { int16_t n = 0; @@ -525,7 +536,11 @@ void rotateFrame_shd_cldfb( SHrotmatgen( SHrotmat, Rmat, shd_rot_max_order ); /* rotation by mtx multiplication */ +#ifdef JBM_TSM_ON_TCS + for ( i = 0; i < numTimeSlots; i++ ) +#else for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) +#endif { for ( iBand = 0; iBand < CLDFB_NO_CHANNELS_MAX; iBand++ ) { @@ -596,7 +611,10 @@ void rotateFrame_sd_cldfb( float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain imag part */ const IVAS_OUTPUT_SETUP_HANDLE hOutputSetup, /* i : output format setup number of channels */ const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ - const int16_t nb_band /* i : number of CLDFB bands to process */ +#ifdef JBM_TSM_ON_TCS + const int16_t numTimeSlots, /* i : number of time slots to process */ +#endif + const int16_t nb_band /* i : number of CLDFB bands to process */ ) { int16_t iBlock, iBand, m, n; @@ -654,7 +672,11 @@ void rotateFrame_sd_cldfb( p_imagRot = imagRot[n]; if ( g1 > 0.f ) { +#ifdef JBM_TSM_ON_TCS + for ( iBlock = 0; iBlock < numTimeSlots; iBlock++ ) +#else for ( iBlock = 0; iBlock < MAX_PARAM_SPATIAL_SUBFRAMES; iBlock++ ) +#endif { p_real = Cldfb_RealBuffer[m][iBlock]; p_imag = Cldfb_ImagBuffer[m][iBlock]; @@ -674,7 +696,11 @@ void rotateFrame_sd_cldfb( { p_realRot = realRot[n]; p_imagRot = imagRot[n]; +#ifdef JBM_TSM_ON_TCS + for ( iBlock = 0; iBlock < numTimeSlots; iBlock++ ) +#else for ( iBlock = 0; iBlock < MAX_PARAM_SPATIAL_SUBFRAMES; iBlock++ ) +#endif { p_real = Cldfb_RealBuffer[n][iBlock]; p_imag = Cldfb_ImagBuffer[n][iBlock]; diff --git a/lib_rend/ivas_sba_rendering.c b/lib_rend/ivas_sba_rendering.c index f59df117b4ef938b3b2d8bac9481046f9c2c40ad..c549461c37f2f4275be8899bc39fd913782250ba 100644 --- a/lib_rend/ivas_sba_rendering.c +++ b/lib_rend/ivas_sba_rendering.c @@ -50,6 +50,158 @@ * Render prototype audio signals using SBA mixing matrices *-------------------------------------------------------------------*/ +#ifdef JBM_TSM_ON_TCS +void ivas_sba_prototype_renderer_sf( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ + float inRe[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : Input audio in CLDFB domain, real */ + float inIm[][JBM_CLDFB_SLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /* i : Input audio in CLDFB domain, imag */ +) +{ + float mixer_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS]; + SPAR_DEC_HANDLE hSpar; + DECODER_CONFIG_HANDLE hDecoderConfig; + int16_t num_spar_bands, spar_band; + int16_t b, ts; + int16_t num_cldfb_bands, numch_in, numch_out; + int16_t cldfb_band; + int16_t out_ch, in_ch; + int16_t firstInCh, inChEnd, firstOutCh, outChEnd; + int16_t slot_idx_start; + + push_wmops( "ivas_sba_prototype_renderer" ); + + hSpar = st_ivas->hSpar; + hDecoderConfig = st_ivas->hDecoderConfig; + num_spar_bands = hSpar->hFbMixer->pFb->filterbank_num_bands; + + num_cldfb_bands = hSpar->hFbMixer->pFb->fb_bin_to_band.num_cldfb_bands; + numch_in = hSpar->hFbMixer->fb_cfg->num_in_chans; + numch_out = hSpar->hFbMixer->fb_cfg->num_out_chans; + + if ( st_ivas->nchan_transport == 1 ) + { + firstInCh = 0; + inChEnd = 1; + firstOutCh = 0; + outChEnd = 1; + } + else /* 2 TC */ + { + firstInCh = 0; + inChEnd = 2; + firstOutCh = 1; + outChEnd = 2; + } + slot_idx_start = hSpar->slots_rendered; + /* Apply mixing matrix */ + for ( ts = 0; ts < hSpar->subframe_nbslots[hSpar->subframes_rendered]; ts++ ) + { + int16_t md_idx = hSpar->render_to_md_map[ts + slot_idx_start]; + /* determine SPAR parameters for this time slot */ + ivas_spar_get_parameters( hSpar, hDecoderConfig, md_idx, numch_out, numch_in, num_spar_bands, mixer_mat ); + + for ( cldfb_band = 0; cldfb_band < num_cldfb_bands; cldfb_band++ ) + { + float out_re[IVAS_SPAR_MAX_CH]; + float out_im[IVAS_SPAR_MAX_CH]; + float cldfb_par; + ivas_fb_bin_to_band_data_t *bin2band = &hSpar->hFbMixer->pFb->fb_bin_to_band; + + for ( out_ch = firstOutCh; out_ch < outChEnd; out_ch++ ) + { + out_re[out_ch] = 0.0f; + out_im[out_ch] = 0.0f; + + for ( in_ch = firstInCh; in_ch < inChEnd; in_ch++ ) + { + if ( cldfb_band < CLDFB_PAR_WEIGHT_START_BAND ) /* tuning parameter, depends on how much SPAR Filters overlap for the CLDFB bands */ + { + spar_band = bin2band->p_cldfb_map_to_spar_band[cldfb_band]; + cldfb_par = mixer_mat[out_ch][in_ch][spar_band]; + } + else + { + cldfb_par = 0.0f; + for ( spar_band = bin2band->p_spar_start_bands[cldfb_band]; spar_band < num_spar_bands; spar_band++ ) + { + /* accumulate contributions from all SPAR bands */ + cldfb_par += mixer_mat[out_ch][in_ch][spar_band] * bin2band->pp_cldfb_weights_per_spar_band[cldfb_band][spar_band]; + } + } + + out_re[out_ch] += inRe[in_ch][ts][cldfb_band] * cldfb_par; + out_im[out_ch] += inIm[in_ch][ts][cldfb_band] * cldfb_par; + } + } + + /*update CLDFB data with the parameter-modified data*/ + for ( out_ch = firstOutCh; out_ch < outChEnd; out_ch++ ) + { + inRe[out_ch][ts][cldfb_band] = out_re[out_ch]; + inIm[out_ch][ts][cldfb_band] = out_im[out_ch]; + } + } + + /* Update mixing matrices */ + if ( ( ( slot_idx_start + ts + 1 ) == hSpar->num_slots ) || ( ( md_idx / JBM_CLDFB_SLOTS_IN_SUBFRAME ) != ( hSpar->render_to_md_map[ts + slot_idx_start + 1] / JBM_CLDFB_SLOTS_IN_SUBFRAME ) ) ) + { + /* we have crossed an unadapted parameter sf border, update previous mixing matrices */ + int16_t md_sf = md_idx / JBM_CLDFB_SLOTS_IN_SUBFRAME; + hSpar->i_subframe++; + hSpar->i_subframe = min( hSpar->i_subframe, MAX_PARAM_SPATIAL_SUBFRAMES ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[1][0][0], hSpar->hMdDec->mixer_mat_prev[0][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[2][0][0], hSpar->hMdDec->mixer_mat_prev[1][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[3][0][0], hSpar->hMdDec->mixer_mat_prev[2][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[4][0][0], hSpar->hMdDec->mixer_mat_prev[3][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + + for ( out_ch = 0; out_ch < numch_out; out_ch++ ) + { + for ( in_ch = 0; in_ch < numch_in; in_ch++ ) + { + for ( b = 0; b < num_spar_bands; b++ ) + { + hSpar->hMdDec->mixer_mat_prev[4][out_ch][in_ch][b] = hSpar->hMdDec->mixer_mat[out_ch][in_ch][b + md_sf * IVAS_MAX_NUM_BANDS]; + } + } + } + } + } + + /* Create prototypes */ + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) + { + for ( ts = 0; ts < hSpar->subframe_nbslots[hSpar->subframes_rendered]; ts++ ) + { + if ( st_ivas->nchan_transport == 1 ) /* Dual mono */ + { + mvr2r( inRe[0][ts], inRe[1][ts], CLDFB_NO_CHANNELS_MAX ); + mvr2r( inIm[0][ts], inIm[1][ts], CLDFB_NO_CHANNELS_MAX ); + } + else if ( st_ivas->nchan_transport == 2 ) /* Opposing cardioids */ + { + float temp_signal[CLDFB_NO_CHANNELS_MAX]; + + v_add( inRe[0][ts], inRe[1][ts], temp_signal, CLDFB_NO_CHANNELS_MAX ); + v_sub( inRe[0][ts], inRe[1][ts], inRe[1][ts], CLDFB_NO_CHANNELS_MAX ); + mvr2r( temp_signal, inRe[0][ts], CLDFB_NO_CHANNELS_MAX ); + v_multc( inRe[0][ts], 0.5f, inRe[0][ts], CLDFB_NO_CHANNELS_MAX ); + v_multc( inRe[1][ts], 0.5f, inRe[1][ts], CLDFB_NO_CHANNELS_MAX ); + + v_add( inIm[0][ts], inIm[1][ts], temp_signal, CLDFB_NO_CHANNELS_MAX ); + v_sub( inIm[0][ts], inIm[1][ts], inIm[1][ts], CLDFB_NO_CHANNELS_MAX ); + mvr2r( temp_signal, inIm[0][ts], CLDFB_NO_CHANNELS_MAX ); + v_multc( inIm[0][ts], 0.5f, inIm[0][ts], CLDFB_NO_CHANNELS_MAX ); + v_multc( inIm[1][ts], 0.5f, inIm[1][ts], CLDFB_NO_CHANNELS_MAX ); + } + } + } + + pop_wmops(); + + return; +} +#endif + #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS void ivas_sba_prototype_renderer( Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ @@ -81,6 +233,9 @@ void ivas_sba_prototype_renderer( int16_t firstSlot, slotEnd, firstInCh, inChEnd, firstOutCh, outChEnd; int16_t sf_idx; #endif +#ifdef JBM_TSM_ON_TCS + int16_t slot_idx_start, md_idx; +#endif push_wmops( "ivas_sba_prototype_renderer" ); @@ -95,6 +250,9 @@ void ivas_sba_prototype_renderer( num_cldfb_bands = hSpar->hFbMixer->pFb->fb_bin_to_band.num_cldfb_bands; numch_in = hSpar->hFbMixer->fb_cfg->num_in_chans; numch_out = hSpar->hFbMixer->fb_cfg->num_out_chans; +#ifdef JBM_TSM_ON_TCS + slot_idx_start = hSpar->slots_rendered; +#endif if ( st_ivas->nchan_transport == 1 ) { @@ -113,10 +271,19 @@ void ivas_sba_prototype_renderer( /* Apply mixing matrix */ #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS +#ifdef JBM_TSM_ON_TCS + for ( ts = 0; ts < hSpar->subframe_nbslots[hSpar->subframes_rendered]; ts++ ) +#else for ( ts = 0; ts < CLDFB_SLOTS_PER_SUBFRAME; ts++ ) +#endif { /* determine SPAR parameters for this time slot */ +#ifdef JBM_TSM_ON_TCS + md_idx = hSpar->render_to_md_map[ts + slot_idx_start]; + ivas_spar_get_parameters( hSpar, hDecoderConfig, md_idx, numch_out, numch_in, num_spar_bands, mixer_mat ); +#else ivas_spar_get_parameters( hSpar, hDecoderConfig, ts + subframe * CLDFB_SLOTS_PER_SUBFRAME, numch_out, numch_in, num_spar_bands, mixer_mat ); +#endif for ( cldfb_band = 0; cldfb_band < num_cldfb_bands; cldfb_band++ ) { @@ -159,8 +326,34 @@ void ivas_sba_prototype_renderer( inIm[out_ch][ts][cldfb_band] = out_im[out_ch]; } } +#ifdef JBM_TSM_ON_TCS + /* Update mixing matrices */ + if ( ( ( slot_idx_start + ts + 1 ) == hSpar->num_slots ) || ( ( md_idx / JBM_CLDFB_SLOTS_IN_SUBFRAME ) != ( hSpar->render_to_md_map[ts + slot_idx_start + 1] / JBM_CLDFB_SLOTS_IN_SUBFRAME ) ) ) + { + /* we have crossed an unadapted parameter sf border, update previous mixing matrices */ + int16_t md_sf = md_idx / JBM_CLDFB_SLOTS_IN_SUBFRAME; + hSpar->i_subframe++; + hSpar->i_subframe = min( hSpar->i_subframe, MAX_PARAM_SPATIAL_SUBFRAMES ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[1][0][0], hSpar->hMdDec->mixer_mat_prev[0][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[2][0][0], hSpar->hMdDec->mixer_mat_prev[1][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[3][0][0], hSpar->hMdDec->mixer_mat_prev[2][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[4][0][0], hSpar->hMdDec->mixer_mat_prev[3][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + + for ( out_ch = 0; out_ch < numch_out; out_ch++ ) + { + for ( in_ch = 0; in_ch < numch_in; in_ch++ ) + { + for ( b = 0; b < num_spar_bands; b++ ) + { + hSpar->hMdDec->mixer_mat_prev[4][out_ch][in_ch][b] = hSpar->hMdDec->mixer_mat[out_ch][in_ch][b + md_sf * IVAS_MAX_NUM_BANDS]; + } + } + } + } +#endif } +#ifndef JBM_TSM_ON_TCS /* Update mixing matrices */ hSpar->i_subframe++; hSpar->i_subframe = min( hSpar->i_subframe, MAX_PARAM_SPATIAL_SUBFRAMES ); @@ -179,6 +372,7 @@ void ivas_sba_prototype_renderer( } } } +#endif #else for ( ts = firstSlot; ts < slotEnd; ts++ ) { @@ -256,7 +450,11 @@ void ivas_sba_prototype_renderer( if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) { #ifdef FIX_355_REFACTOR_PARAMBIN_TO_5MS +#ifdef JBM_TSM_ON_TCS + for ( ts = 0; ts < hSpar->subframe_nbslots[subframe]; ts++ ) +#else for ( ts = 0; ts < CLDFB_SLOTS_PER_SUBFRAME; ts++ ) +#endif #else for ( ts = firstSlot; ts < slotEnd; ts++ ) #endif @@ -285,6 +483,10 @@ void ivas_sba_prototype_renderer( } } +#ifdef JBM_TSM_ON_TCS + hSpar->subframes_rendered++; + hSpar->slots_rendered += hSpar->subframe_nbslots[subframe]; +#endif pop_wmops(); return; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 81e2ce5bba4305c5ddf72763e8044439f0f62d62..d82e00c067b188c43a54804ba1e5acc5b870c75d 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -2481,6 +2481,9 @@ static DecoderDummy *initDecoderDummy( decDummy->hDecoderConfig->output_Fs = sampleRate; decDummy->hDecoderConfig->nchan_out = numOutChannels; decDummy->hDecoderConfig->Opt_Headrotation = 0; +#ifdef JBM_TSM_ON_TCS + decDummy->hDecoderConfig->voip_active = 0; +#endif decDummy->hBinRenderer = NULL; decDummy->hEFAPdata = NULL; @@ -2492,6 +2495,9 @@ static DecoderDummy *initDecoderDummy( decDummy->hMasa = NULL; decDummy->hDiracDecBin = NULL; decDummy->hQMetaData = NULL; +#ifdef JBM_TSM_ON_TCS + decDummy->hTcBuffer = NULL; +#endif decDummy->hDecoderConfig->output_config = getIvasAudioConfigFromRendAudioConfig( outConfig ); decDummy->nchan_transport = numTransChannels; @@ -2528,6 +2534,11 @@ static DecoderDummy *initDecoderDummy( decDummy->hRenderConfig = NULL; } +#ifdef JBM_TSM_ON_TCS + /* get a default TC buffer, needed for some renderers */ + ivas_jbm_dec_tc_buffer_open( decDummy, TC_BUFFER_MODE_NONE, 0, 0, 0, 1 ); +#endif + decDummy->renderer_type = RENDERER_DISABLE; return decDummy; @@ -2635,6 +2646,11 @@ static void freeDecoderDummy( /* Parametric binaural renderer handle */ ivas_dirac_dec_close_binaural_data( &pDecDummy->hDiracDecBin ); +#ifdef JBM_TSM_ON_TCS + /* TC buffer */ + ivas_jbm_dec_tc_buffer_close( &pDecDummy->hTcBuffer ); +#endif + free( pDecDummy ); pDecDummy = NULL; @@ -4402,6 +4418,13 @@ static ivas_error renderIsmToBinauralRoom( IVAS_REND_AudioBuffer tmpMcBuffer; IVAS_REND_AudioObjectPosition rotatedPos; const IVAS_REND_HeadRotData *headRotData; +#ifdef JBM_TSM_ON_TCS + float *p_tmpRendBuffer[MAX_OUTPUT_CHANNELS]; + for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + p_tmpRendBuffer[i] = tmpRendBuffer[i]; + } +#endif push_wmops( "renderIsmToBinauralRoom" ); @@ -4501,8 +4524,13 @@ static ivas_error renderIsmToBinauralRoom( copyBufferTo2dArray( tmpMcBuffer, tmpRendBuffer ); +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_rend_crendProcess( ismInput->crendWrapper, AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_BINAURAL_ROOM, + NULL, NULL, NULL, NULL, p_tmpRendBuffer, *ismInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_rend_crendProcess( ismInput->crendWrapper, AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_BINAURAL_ROOM, NULL, NULL, NULL, NULL, tmpRendBuffer, *ismInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -4775,6 +4803,15 @@ static ivas_error renderMcToBinaural( ivas_error error; IVAS_REND_AudioBuffer tmpRotBuffer; +#ifdef JBM_TSM_ON_TCS + float *p_tmpRendBuffer[MAX_OUTPUT_CHANNELS]; + int16_t i; + for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + p_tmpRendBuffer[i] = tmpRendBuffer[i]; + } +#endif + push_wmops( "renderMcToBinaural" ); headRotEnabled = mcInput->base.ctx.pHeadRotData->headRotEnabled; @@ -4814,8 +4851,13 @@ static ivas_error renderMcToBinaural( } /* call CREND */ +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, getIvasAudioConfigFromRendAudioConfig( mcInput->base.inConfig ), getIvasAudioConfigFromRendAudioConfig( outConfig ), + NULL, NULL, NULL, NULL, p_tmpRendBuffer, *mcInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, getIvasAudioConfigFromRendAudioConfig( mcInput->base.inConfig ), getIvasAudioConfigFromRendAudioConfig( outConfig ), NULL, NULL, NULL, NULL, tmpRendBuffer, *mcInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -4845,6 +4887,15 @@ static ivas_error renderMcToBinauralRoom( ivas_error error; IVAS_REND_AudioBuffer tmpRotBuffer; +#ifdef JBM_TSM_ON_TCS + float *p_tmpRendBuffer[MAX_OUTPUT_CHANNELS]; + int16_t i; + for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + p_tmpRendBuffer[i] = tmpRendBuffer[i]; + } +#endif + push_wmops( "renderMcToBinauralRoom" ); headRotEnabled = mcInput->base.ctx.pHeadRotData->headRotEnabled; @@ -4884,8 +4935,13 @@ static ivas_error renderMcToBinauralRoom( } /* call CREND */ +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, getIvasAudioConfigFromRendAudioConfig( mcInput->base.inConfig ), getIvasAudioConfigFromRendAudioConfig( outConfig ), + NULL, NULL, NULL, NULL, p_tmpRendBuffer, *mcInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, getIvasAudioConfigFromRendAudioConfig( mcInput->base.inConfig ), getIvasAudioConfigFromRendAudioConfig( outConfig ), NULL, NULL, NULL, NULL, tmpRendBuffer, *mcInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -4918,12 +4974,23 @@ static ivas_error renderMcCustomLsToBinauralRoom( IVAS_REND_AudioBuffer tmpMcBuffer; IVAS_REND_AudioBuffer *tmpBufPtr; +#ifdef JBM_TSM_ON_TCS + float *p_tmpCrendBuffer[MAX_OUTPUT_CHANNELS]; +#endif + push_wmops( "renderMcCustomLsToBinauralRoom" ); tmpRotBuffer = outAudio; /* avoid compilation warning */ headRotEnabled = mcInput->base.ctx.pHeadRotData->headRotEnabled; +#ifdef JBM_TSM_ON_TCS + for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + p_tmpCrendBuffer[i] = tmpCrendBuffer[i]; + } +#endif + /* apply rotation */ if ( headRotEnabled ) { @@ -4957,8 +5024,13 @@ static ivas_error renderMcCustomLsToBinauralRoom( copyBufferTo2dArray( tmpMcBuffer, tmpCrendBuffer ); /* call CREND */ +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, AUDIO_CONFIG_7_1_4, getIvasAudioConfigFromRendAudioConfig( outConfig ), NULL, NULL, NULL, NULL, + p_tmpCrendBuffer, *mcInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, AUDIO_CONFIG_7_1_4, getIvasAudioConfigFromRendAudioConfig( outConfig ), NULL, NULL, NULL, NULL, tmpCrendBuffer, *mcInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -5161,8 +5233,20 @@ static ivas_error renderSbaToBinaural( ivas_error error; IVAS_REND_AudioBuffer tmpRotBuffer; +#ifdef JBM_TSM_ON_TCS + float *p_tmpCrendBuffer[MAX_OUTPUT_CHANNELS]; + int16_t i; +#endif + push_wmops( "renderSbaToBinaural" ); +#ifdef JBM_TSM_ON_TCS + for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + p_tmpCrendBuffer[i] = tmpCrendBuffer[i]; + } +#endif + /* apply rotation */ if ( sbaInput->base.ctx.pHeadRotData->headRotEnabled ) { @@ -5186,8 +5270,13 @@ static ivas_error renderSbaToBinaural( } /* call CREND */ +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_rend_crendProcess( sbaInput->crendWrapper, getIvasAudioConfigFromRendAudioConfig( sbaInput->base.inConfig ), getIvasAudioConfigFromRendAudioConfig( outConfig ), + NULL, NULL, NULL, NULL, p_tmpCrendBuffer, *sbaInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_rend_crendProcess( sbaInput->crendWrapper, getIvasAudioConfigFromRendAudioConfig( sbaInput->base.inConfig ), getIvasAudioConfigFromRendAudioConfig( outConfig ), NULL, NULL, NULL, NULL, tmpCrendBuffer, *sbaInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -5213,10 +5302,21 @@ static ivas_error renderSbaToBinauralRoom( IVAS_REND_AudioBuffer tmpMcBuffer; IVAS_REND_AudioBuffer *tmpBufPtr; +#ifdef JBM_TSM_ON_TCS + float *p_tmpCrendBuffer[MAX_OUTPUT_CHANNELS]; +#endif + tmpRotBuffer = outAudio; /* avoid compilation warning */ push_wmops( "renderSbaToBinauralRoom" ); +#ifdef JBM_TSM_ON_TCS + for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + p_tmpCrendBuffer[i] = tmpCrendBuffer[i]; + } +#endif + headRotEnabled = sbaInput->base.ctx.pHeadRotData->headRotEnabled; /* apply rotation */ @@ -5255,8 +5355,13 @@ static ivas_error renderSbaToBinauralRoom( copyBufferTo2dArray( tmpMcBuffer, tmpCrendBuffer ); /* call CREND */ +#ifdef JBM_TSM_ON_TCS + if ( ( error = ivas_rend_crendProcess( sbaInput->crendWrapper, AUDIO_CONFIG_7_1_4, getIvasAudioConfigFromRendAudioConfig( outConfig ), + NULL, NULL, NULL, NULL, p_tmpCrendBuffer, *sbaInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_rend_crendProcess( sbaInput->crendWrapper, AUDIO_CONFIG_7_1_4, getIvasAudioConfigFromRendAudioConfig( outConfig ), NULL, NULL, NULL, NULL, tmpCrendBuffer, *sbaInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -5409,7 +5514,11 @@ static void renderMasaToMc( } else { +#ifdef JBM_TSM_ON_TCS + ivas_dirac_dec( masaInput->decDummy, tmpBuffer, masaInput->base.inputBuffer.config.numChannels ); +#else ivas_dirac_dec( masaInput->decDummy, tmpBuffer, masaInput->base.inputBuffer.config.numChannels, NULL, NULL, -1 ); +#endif } accumulate2dArrayToBuffer( tmpBuffer, &outAudio ); @@ -5426,7 +5535,11 @@ static void renderMasaToSba( copyBufferTo2dArray( masaInput->base.inputBuffer, tmpBuffer ); copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->decDummy->hDirAC ); +#ifdef JBM_TSM_ON_TCS + ivas_dirac_dec( masaInput->decDummy, tmpBuffer, masaInput->base.inputBuffer.config.numChannels ); +#else ivas_dirac_dec( masaInput->decDummy, tmpBuffer, masaInput->base.inputBuffer.config.numChannels, NULL, NULL, -1 ); +#endif accumulate2dArrayToBuffer( tmpBuffer, &outAudio ); diff --git a/lib_util/tinywaveout_c.h b/lib_util/tinywaveout_c.h index d0531eb6653c47288f7db1b6f1c84d454f55227d..b82c0cd131a20a9fea782b08e523ebdb56ac6e3d 100644 --- a/lib_util/tinywaveout_c.h +++ b/lib_util/tinywaveout_c.h @@ -490,6 +490,49 @@ static int32_t WriteWavShort( return __TWO_SUCCESS; } +#ifdef DEBUG_JBM +/* this function expects values in the 16 bit range +-32767/8 */ +static int32_t WriteWavFloat( + WAVEFILEOUT *self, + float sampleBuffer[], + uint32_t nSamples ) +{ + uint32_t i; + int32_t err = __TWO_SUCCESS; + + if ( !self ) + { + return __TWO_ERROR; + } + if ( !sampleBuffer ) + { + return __TWO_ERROR; + } + if ( __dataSizeChk( self, nSamples * sizeof( float ) ) ) + { + return __TWO_ERROR; + } + + for ( i = 0; i < nSamples; i++ ) + { + if ( self->bps == 32 ) + { + err = __WriteSample32( self, sampleBuffer[i] / 32768.0f ); + } + else + { + err = __TWO_ERROR; + } + if ( err != __TWO_SUCCESS ) + { + return err; + } + } + + return __TWO_SUCCESS; +} +#endif + static int32_t CloseWav( WAVEFILEOUT *self ) { diff --git a/lib_util/tsm_scale_file_reader.c b/lib_util/tsm_scale_file_reader.c new file mode 100644 index 0000000000000000000000000000000000000000..fbd1824d9dfd4d7219ad72c18549bc19a9d016a9 --- /dev/null +++ b/lib_util/tsm_scale_file_reader.c @@ -0,0 +1,148 @@ +/****************************************************************************************************** + + (C) 2022-2023 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 "tsm_scale_file_reader.h" +#include "cmdl_tools.h" +#include +#include +#include + +struct TsmScaleFileReader +{ + FILE *file; + char *file_path; + bool fileRewind; +}; + + +/*---------------------------------------------------------------------* + * TsmScaleFileReader_open() + * + * Allocates memory for an TsmScaleFileReader and opens the file at given path for reading. + *---------------------------------------------------------------------*/ + +/*! r: JbmFileReader handle */ +TsmScaleFileReader *TsmScaleFileReader_open( + const char *filePath /* i : path to CA config file */ +) +{ + TsmScaleFileReader *self; + FILE *file; + + if ( !filePath ) + { + return NULL; + } + + file = fopen( filePath, "rb" ); + + if ( !file ) + { + return NULL; + } + + self = calloc( sizeof( TsmScaleFileReader ), 1 ); + self->file = file; + self->file_path = calloc( sizeof( char ), strlen( filePath ) + 1 ); + strcpy( self->file_path, filePath ); + + return self; +} + + +/*---------------------------------------------------------------------* + * TsmScaleFileReader_readScale() + * + * Read TSM scale entry + *---------------------------------------------------------------------*/ + +ivas_error TsmScaleFileReader_readScale( + TsmScaleFileReader *self, /* i/o: TsmScaleFileReader handle */ + int16_t *scale /* o : scale */ +) +{ + int tmp; + if ( 1 != fscanf( self->file, "%d", &tmp ) ) + { + if ( feof( self->file ) ) + { + rewind( self->file ); + self->fileRewind = true; + return TsmScaleFileReader_readScale( self, scale ); + } + return IVAS_ERR_FAILED_FILE_PARSE; + } + *scale = (int16_t) tmp; + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * JbmFileReader_close() + * + * De-allocates all underlying memory of an JbmFileReader. + *---------------------------------------------------------------------*/ + +void TsmScaleFileReader_close( + TsmScaleFileReader **selfPtr /* i/o: pointer to JbmFileReader handle */ +) +{ + if ( selfPtr == NULL || *selfPtr == NULL ) + { + return; + } + + fclose( ( *selfPtr )->file ); + free( ( *selfPtr )->file_path ); + free( *selfPtr ); + *selfPtr = NULL; + + return; +} + + +/*---------------------------------------------------------------------* + * JbmFileReader_getFilePath() + * + *---------------------------------------------------------------------*/ + +const char *TsmScaleFileReader_getFilePath( + TsmScaleFileReader *self /* i/o: JbmFileReader handle */ +) +{ + if ( self == NULL ) + { + return NULL; + } + + return self->file_path; +} diff --git a/lib_util/tsm_scale_file_reader.h b/lib_util/tsm_scale_file_reader.h new file mode 100644 index 0000000000000000000000000000000000000000..7a795a25cb27316f36acef8bb07dfe67c6dcbf4c --- /dev/null +++ b/lib_util/tsm_scale_file_reader.h @@ -0,0 +1,67 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef IVAS_TSM_SCALE_FILE_READER_H +#define IVAS_TSM_SCALE_FILE_READER_H + +#include +#include "common_api_types.h" +#include "ivas_error.h" + +/* clang-format off */ + +typedef struct TsmScaleFileReader TsmScaleFileReader; + + +/*! r: TsmScaleFileReader handle */ +TsmScaleFileReader *TsmScaleFileReader_open( + const char *filePath /* i : path to TSM scale file */ +); + +ivas_error TsmScaleFileReader_readScale( + TsmScaleFileReader* self, /* i/o: TsmScaleFileReader handle */ + int16_t *scale /* o : next scale */ +); + +void TsmScaleFileReader_close( + TsmScaleFileReader **selfPtr /* i/o: pointer to TsmScaleFileReader handle */ +); + +/*! r: path to the currently opened file or NULL if `self` is NULL */ +const char *TsmScaleFileReader_getFilePath( + TsmScaleFileReader* self /* i/o: TsmScaleFileReader handle */ +); + + +/* clang-format on */ + +#endif /* IVAS_TSM_SCALE_FILE_READER_H */ diff --git a/scripts/batch_comp_audio.py b/scripts/batch_comp_audio.py index 72ae3fcc7d6a506aea3d94386f0a02e5b77e1af1..97e9f8f54840f22f71fddb44ebd0bddd8fa486ce 100755 --- a/scripts/batch_comp_audio.py +++ b/scripts/batch_comp_audio.py @@ -96,10 +96,9 @@ def main(args): if not args.diffs_only or diff > 0: if diff == 0.0: - label = "\033[00;32m[OKAY]\033[00;00m" + label = "[OKAY]" else: - label = "\033[00;31m[FAIL]\033[00;00m" - + label = "[FAIL]" result = f"{label} Max. diff (PCM) for file {f}: {diff}" if args.verbose and diff != 0.0: @@ -108,10 +107,10 @@ def main(args): print(result, file=out_file) - if num_files_diff > 0: - print(f"{num_files_diff} files differ/don't exist", file=out_file) - else: - print(f"All files are bitexact", file=out_file) + if num_files_diff > 0: + print(f"{num_files_diff} files differ/don't exist", file=out_file) + else: + print(f"All files are bitexact", file=out_file) def compare_files(f, fol1, fol2, outputs_dict): diff --git a/scripts/config/ivas_modes.json b/scripts/config/ivas_modes.json index ab08c4e5cd8039bab7406e191dfad601a99eb25d..d4f1e107cc6c2a798920a8874115ed24f5902f9d 100644 --- a/scripts/config/ivas_modes.json +++ b/scripts/config/ivas_modes.json @@ -964,6 +964,44 @@ ] } }, + "MASA_1TC_1DIR_b{bitrate}_{bandwidth}_rs": { + "encmodeoption": [ + "-masa", + "1" + ], + "encoptions": [ + "-max_band", + "{bandwidth}" + ], + "dec": { + "7_1_4": [], + "HOA3": [], + "mono": [], + "stereo": [], + "EXT": [] + }, + "in_config": "MASA1TC1DIR", + "table_name": "MASA 1TC 1DIR@{table_bitrate} kbps RS {bandwidth}", + "nummetadata": 1, + "metadatafilenames": [ + "{item}.met" + ], + "rs": true, + "amr": false, + "mono": false, + "bitrates": { + "wb": { + "all": "{sw_files_path}/sw_13k2_512k.bin" + }, + "swb": { + "all": "{sw_files_path}/sw_13k2_512k.bin" + }, + "fb": { + "all": "{sw_files_path}/sw_13k2_512k.bin" + } + } + + }, "MASA_2TC_1DIR_b{bitrate}_{bandwidth}_cbr": { "encmodeoption": [ "-masa", @@ -1034,6 +1072,46 @@ ] } }, + "MASA_2TC_1DIR_b{bitrate}_{bandwidth}_rs": { + "encmodeoption": [ + "-masa", + "2" + ], + "encoptions": [ + "-max_band", + "{bandwidth}" + ], + "dec": { + "7_1_4": [], + "HOA3": [], + "mono": [], + "stereo": [], + "EXT": [] + }, + "in_config": "MASA2TC1DIR", + "table_name": "MASA 2TC 1DIR@{table_bitrate} kbps {bandwidth}", + "nummetadata": 1, + "metadatafilenames": [ + "{item}.met" + ], + "rs": true, + "amr": false, + "mono": false, + "rs": true, + "amr": false, + "mono": false, + "bitrates": { + "wb": { + "all": "{sw_files_path}/sw_13k2_512k.bin" + }, + "swb": { + "all": "{sw_files_path}/sw_13k2_512k.bin" + }, + "fb": { + "all": "{sw_files_path}/sw_13k2_512k.bin" + } + } + }, "MASA_1TC_2DIR_b{bitrate}_{bandwidth}_cbr": { "encmodeoption": [ "-masa", @@ -1851,6 +1929,39 @@ ] } }, + "ISM1_b{bitrate}_{bandwidth}_rs": { + "encmodeoption": [ + "-ism", + "1" + ], + "encoptions": [ + "-max_band", + "{bandwidth}" + ], + "dec": { + "EXT": [] + }, + "in_config": "ISM1", + "table_name": "ISM1@{table_bitrate} RS kbps {bandwidth}", + "nummetadata": 1, + "metadatafilenames": [ + "stvISM{mdi}.csv" + ], + "rs": true, + "amr": false, + "mono": false, + "bitrates": { + "wb": { + "all": "{sw_files_path}/sw_13k2_128k.bin" + }, + "swb": { + "all": "{sw_files_path}/sw_13k2_128k.bin" + }, + "fb": { + "all": "{sw_files_path}/sw_32k_128k.bin" + } + } + }, "ISM1_b{bitrate}_dtx_{bandwidth}_cbr": { "encmodeoption": [ "-ism", @@ -2030,6 +2141,39 @@ 256000 ] } + }, + "ISM2_b{bitrate}_{bandwidth}_rs": { + "encmodeoption": [ + "-ism", + "2" + ], + "encoptions": [ + "-max_band", + "{bandwidth}" + ], + "dec": { + "EXT": [] + }, + "in_config": "ISM2", + "table_name": "ISM2@{table_bitrate} kbps RS {bandwidth}", + "nummetadata": 2, + "metadatafilenames": [ + "stvISM{mdi}.csv" + ], + "rs": true, + "amr": false, + "mono": false, + "bitrates": { + "wb": { + "all": "{sw_files_path}/sw_16k4_256k.bin" + }, + "swb": { + "all": "{sw_files_path}/sw_16k4_256k.bin" + }, + "fb": { + "all": "{sw_files_path}/sw_32k_256k.bin" + } + } } }, "ISM3": { @@ -2157,6 +2301,39 @@ 384000 ] } + }, + "ISM3_b{bitrate}_{bandwidth}_rs": { + "encmodeoption": [ + "-ism", + "3" + ], + "encoptions": [ + "-max_band", + "{bandwidth}" + ], + "dec": { + "EXT": [] + }, + "in_config": "ISM3", + "table_name": "ISM3@{table_bitrate} kbps {bandwidth}", + "nummetadata": 3, + "metadatafilenames": [ + "stvISM{mdi}.csv" + ], + "rs": true, + "amr": false, + "mono": false, + "bitrates": { + "wb": { + "all": "{sw_files_path}/sw_24k4_384k.bin" + }, + "swb": { + "all": "{sw_files_path}/sw_24k4_384k.bin" + }, + "fb": { + "all": "{sw_files_path}/sw_32k_384k.bin" + } + } } }, "ISM4": { @@ -2290,6 +2467,39 @@ 512000 ] } + }, + "ISM4_b{bitrate}_{bandwidth}_rs": { + "encmodeoption": [ + "-ism", + "4" + ], + "encoptions": [ + "-max_band", + "{bandwidth}" + ], + "dec": { + "EXT": [] + }, + "in_config": "ISM4", + "table_name": "ISM4@{table_bitrate} kbps RS {bandwidth}", + "nummetadata": 4, + "metadatafilenames": [ + "stvISM{mdi}.csv" + ], + "rs": true, + "amr": false, + "mono": false, + "bitrates": { + "wb": { + "all": "{sw_files_path}/sw_24k4_384k.bin" + }, + "swb": { + "all": "{sw_files_path}/sw_24k4_384k.bin" + }, + "fb": { + "all": "{sw_files_path}/sw_32k_384k.bin" + } + } } }, "ISM+1": { diff --git a/scripts/runIvasCodec.py b/scripts/runIvasCodec.py index 070fb8e4f04da261e273fc0a1576c6ab5533cb6b..f96758e5be8d99b7fece0049e027eef277b40e4f 100755 --- a/scripts/runIvasCodec.py +++ b/scripts/runIvasCodec.py @@ -34,6 +34,7 @@ import os.path import platform import sys import logging +import shutil from pyivastest import IvasScriptsCommon, IvasModeRunner import pyivastest.constants as constants @@ -81,6 +82,11 @@ class RunIvasCodec(IvasScriptsCommon.IvasScript): help="Decoder binary name (default {})".format(default_dec), default=default_dec, ) + self.parser.add_argument( + "--fail_log_dir", + help="Move logs of failed modes to dir (default none)", + default=None, + ) def run(self): self.parse_args() @@ -137,10 +143,19 @@ class RunIvasCodec(IvasScriptsCommon.IvasScript): self.logger.console(" Encoder: {}".format(bin_enc), logging.INFO) self.logger.console(" Decoder: {}".format(bin_dec), logging.INFO) + runner.run() self.logger.console(" ") + fail_log_dir=None + if self.args["fail_log_dir"] is not None: + fail_log_dir = os.path.realpath(self.args["fail_log_dir"]) + if not(os.path.exists(fail_log_dir)): + os.makedirs(fail_log_dir) for r in runner.results: self.logger.console(r[0]) + if fail_log_dir is not None: + shutil.copy(r[3],fail_log_dir) + self.logger.console(" ") diff --git a/scripts/switchPaths/sw_13k2_128k.bin b/scripts/switchPaths/sw_13k2_128k.bin new file mode 100644 index 0000000000000000000000000000000000000000..7309ee26ab59fbbfaf4889e1163b97628a0ef565 --- /dev/null +++ b/scripts/switchPaths/sw_13k2_128k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d9ddf71b27bcd47d5f37abb6c62146ff4fb5a848cd85605d4df87a9cc4b1d1e0 +size 60000 diff --git a/scripts/switchPaths/sw_13k2_256k.bin b/scripts/switchPaths/sw_13k2_256k.bin new file mode 100644 index 0000000000000000000000000000000000000000..1d0c3fac28a5f752f12830674f1864f6ac1e971b --- /dev/null +++ b/scripts/switchPaths/sw_13k2_256k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05fd8870e43b0eb349d5e9b3bb939574b71d3e7630940a10d6767cae2c6c4a3c +size 60000 diff --git a/scripts/switchPaths/sw_16k4_128k.bin b/scripts/switchPaths/sw_16k4_128k.bin new file mode 100644 index 0000000000000000000000000000000000000000..1e85a18b77c031b534476e37465cdf5ca76a6472 --- /dev/null +++ b/scripts/switchPaths/sw_16k4_128k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e07f8c6be0e08ed96b15c9a3daa2811ef0b596dc08cc687bce1f0ca8e49969b +size 60000 diff --git a/scripts/switchPaths/sw_16k4_256k.bin b/scripts/switchPaths/sw_16k4_256k.bin new file mode 100644 index 0000000000000000000000000000000000000000..47bc9c9aa35a39376bffd6059fb41e54123f2dc0 --- /dev/null +++ b/scripts/switchPaths/sw_16k4_256k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7dedd5a20cbc5594ec869b13b3e9774efd6394ad5d5b64a4e98210447c3a75ba +size 60000 diff --git a/scripts/switchPaths/sw_24k4_256k_1.bin b/scripts/switchPaths/sw_24k4_256k_1.bin new file mode 100644 index 0000000000000000000000000000000000000000..e2852619262f36e617038034a42807364fae28ed --- /dev/null +++ b/scripts/switchPaths/sw_24k4_256k_1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf5b303299209bdd4f7e007d1190c7957b17ab3ee399570f1bb87d27f3fec092 +size 60000 diff --git a/scripts/switchPaths/sw_24k4_384k.bin b/scripts/switchPaths/sw_24k4_384k.bin new file mode 100644 index 0000000000000000000000000000000000000000..781e3023b26710b65400686883f8502e1c683253 --- /dev/null +++ b/scripts/switchPaths/sw_24k4_384k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6e3e7599638d3792d851a5bdc13b85d6b401ebc9724795562b1a5d25fc2c3bc6 +size 60000 diff --git a/scripts/switchPaths/sw_24k4_512k.bin b/scripts/switchPaths/sw_24k4_512k.bin new file mode 100644 index 0000000000000000000000000000000000000000..dcc58dbdc6a2b4801563dcbab3b87d76cb180b5c --- /dev/null +++ b/scripts/switchPaths/sw_24k4_512k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2369edc21bdf3440ceaf21de16698e38cf50c246ddf04878a5961538dded11ad +size 60000 diff --git a/scripts/switchPaths/sw_32k_128k.bin b/scripts/switchPaths/sw_32k_128k.bin new file mode 100644 index 0000000000000000000000000000000000000000..fc4b81e0c3d2f57cc7241c75c37d64fbcec9f909 --- /dev/null +++ b/scripts/switchPaths/sw_32k_128k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fdb0da661cb08cc546c3761afa1d778d2c7aa04df61b608ae4301e31867dcc2e +size 60000 diff --git a/scripts/switchPaths/sw_32k_256k.bin b/scripts/switchPaths/sw_32k_256k.bin new file mode 100644 index 0000000000000000000000000000000000000000..46b1e17cd4bb30aa1b3fd5ed82c7b1ac1702824a --- /dev/null +++ b/scripts/switchPaths/sw_32k_256k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61dacf79a7582edb83c151c300392efb719f08762a963da29f9b7665305a8c5f +size 60000 diff --git a/scripts/switchPaths/sw_32k_384k.bin b/scripts/switchPaths/sw_32k_384k.bin new file mode 100644 index 0000000000000000000000000000000000000000..088edfacbffdb508a96b89d434cf5298081a6b21 --- /dev/null +++ b/scripts/switchPaths/sw_32k_384k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:77f6e7b141b16bd21005c5169cd9bc8b7b2c96df379ce9e74788717c66b9130f +size 60000 diff --git a/scripts/switchPaths/sw_32k_512k.bin b/scripts/switchPaths/sw_32k_512k.bin new file mode 100644 index 0000000000000000000000000000000000000000..d385f3a890804eedaafdc308233954e106e9f2c4 --- /dev/null +++ b/scripts/switchPaths/sw_32k_512k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2a6eb4080fce3bc1a7ba20cfc8ef3e8ff981ebce5de7c8e45bbc12edf7f21d0c +size 60000