From 8ce4b82201e3e5461c9537c440ac0501c88f2e57 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Thu, 24 Nov 2022 12:40:30 +0100 Subject: [PATCH 01/37] Contribution 19 - mutllichannel JBM Extends JBM to support more than one audio channel. Introduces VoIP mode for decoding IVAS bitstreams. --- .gitignore | 2 + CMakeLists.txt | 3 + apps/decoder.c | 447 +++++++++++++++++++++++++++++++++++-- lib_com/bitstream.c | 16 +- lib_com/ivas_error.h | 3 + lib_com/options.h | 2 + lib_debug/debug.h | 2 + lib_debug/memory.c | 2 + lib_dec/jbm_jb4sb.h | 2 + lib_dec/jbm_pcmdsp_apa.c | 31 ++- lib_dec/jbm_pcmdsp_apa.h | 8 +- lib_dec/jbm_pcmdsp_fifo.c | 16 ++ lib_dec/jbm_pcmdsp_fifo.h | 8 + lib_dec/lib_dec.c | 228 ++++++++++++++++++- lib_dec/lib_dec.h | 21 +- lib_util/evs_rtp_payload.c | 2 + lib_util/evs_rtp_payload.h | 2 + 17 files changed, 760 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 13dd28ed34..4c03ff1833 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,8 @@ scripts/ref/ scripts/test/ scripts/out/ scripts/self_test_summary.txt +scripts/cppp/ +binary/ tests/renderer/cut tests/renderer/ref tests/dut diff --git a/CMakeLists.txt b/CMakeLists.txt index 317274ddce..37f7a5cce5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -187,3 +187,6 @@ if(COPY_EXECUTABLES_FROM_BUILD_DIR) add_custom_command(TARGET IVAS_crend_unit_test POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/ivas_pytests/tests/unit_tests/crend/") add_custom_command(TARGET renderer_standalone POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/td_object_renderer/object_renderer_standalone/") endif() + +# Allow creating packages for CMake install +install(TARGETS lib_enc lib_dec lib_rend lib_com lib_util ARCHIVE DESTINATION lib) diff --git a/apps/decoder.c b/apps/decoder.c index 6f73723af1..e5f50cec20 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -137,6 +137,9 @@ static void usage_dec( void ); static ivas_error decodeG192( DecArguments arg, BS_READER_HANDLE hBsReader, HeadRotFileReader *headRotReader, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); static ivas_error decodeVoIP( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HANDLE hIvasDec ); #ifdef DEBUGGING +#ifdef MC_JBM +static ivas_error printBitstreamInfoVoip( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HANDLE hIvasDec ); +#endif static int16_t app_own_random( int16_t *seed ); static IVAS_DEC_FORCED_REND_MODE parseForcedRendModeDec( char *forcedRendModeChar ); #endif @@ -340,7 +343,15 @@ int main( if ( arg.voipMode ) { +#ifdef MC_JBM + if ( ( error = printBitstreamInfoVoip(arg, hBsReader, hIvasDec) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error while previewing VoIP bitstream: %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } +#else IVAS_DEC_PrintConfig( hIvasDec, arg.quietModeEnabled, arg.voipMode ); +#endif } else { @@ -420,9 +431,9 @@ int main( fprintf( stdout, "FEC: %.2f %%\n", arg.FER ); } } -#else +#else /* DEBUGGING */ IVAS_DEC_PrintConfig( hIvasDec, 1, arg.voipMode ); -#endif +#endif /* DEBUGGING */ /*-------------------------------------------------------------------* * Load renderer configuration from file @@ -503,11 +514,13 @@ int main( if ( arg.voipMode ) { +#ifndef MC_JBM if ( arg.decMode != IVAS_DEC_MODE_EVS ) { fprintf( stderr, "\nError: VoIP not yet supported for decMode: %d\n\n", arg.decMode ); goto cleanup; } +#endif if ( ( error = IVAS_DEC_EnableVoIP( hIvasDec, 60, arg.inputFormat ) ) != IVAS_ERR_OK ) { @@ -1128,6 +1141,163 @@ static int16_t app_own_random( int16_t *seed ) } #endif +#ifdef MC_JBM +static ivas_error initOnFirstGoodFrame( + IVAS_DEC_HANDLE hIvasDec, /* i/o: */ + const DecArguments arg, /* i : */ + const int16_t numInitialBadFrames, /* i : */ + const uint16_t numOutSamples, /* i : */ + int16_t *pFullDelayNumSamples, /* o : */ + int16_t *pRemainingDelayNumSamples, /* o : */ + int32_t *delayTimeScale, /* o : */ + IVAS_DEC_BS_FORMAT *pBsFormat, /* i/o: */ + AudioFileWriter **ppAfWriter, /* o : */ + MasaFileWriter **ppMasaWriter, /* o : */ + IsmFileWriter *ismWriters[IVAS_MAX_NUM_OBJECTS], /* o : */ + int16_t *pNumOutChannels, /* o : */ + uint16_t *pNumObj /* o : */ +) +{ + ivas_error error = IVAS_ERR_UNKNOWN; + + /* Now delay, number of output channels and frame size are known */ + if ( arg.delayCompensationEnabled ) + { + if ( ( error = IVAS_DEC_GetDelay( hIvasDec, pFullDelayNumSamples, delayTimeScale ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to get delay of decoder: %s\n", ivas_error_to_string( error ) ); + return error; + } + } + else + { + *pFullDelayNumSamples = 0; + } + *pRemainingDelayNumSamples = *pFullDelayNumSamples; + + if ( ( error = IVAS_DEC_GetNumOutputChannels( hIvasDec, pNumOutChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetNumOutputChannels, code: %d\n", error ); + return error; + } + + int32_t pcmFrameSize; + + if ( ( error = IVAS_DEC_GetPcmFrameSize( hIvasDec, &pcmFrameSize ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetPcmFrameSize, error code: %d\n", error ); + return error; + } + + /* Open audio writer and write all previously skipped bad frames now that frame size is known */ + if ( ( error = AudioFileWriter_open( ppAfWriter, arg.outputWavFilename, arg.output_Fs, *pNumOutChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to open output file %s\n", arg.outputWavFilename ); + return error; + } + + int16_t *zeroBuf = malloc( pcmFrameSize * sizeof( int16_t ) ); + memset( zeroBuf, 0, pcmFrameSize * sizeof( int16_t ) ); + + for ( int16_t i = 0; i < numInitialBadFrames; ++i ) + { + if ( *pRemainingDelayNumSamples < numOutSamples ) + { + if ( ( error = AudioFileWriter_write( *ppAfWriter, zeroBuf, numOutSamples * *pNumOutChannels - ( *pRemainingDelayNumSamples * *pNumOutChannels ) ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nOutput audio file writer error\n" ); + return error; + } + *pRemainingDelayNumSamples = 0; + } + else + { + *pRemainingDelayNumSamples -= numOutSamples; + } + } + + free( zeroBuf ); + + /* Open other output files if EXT output config - now details about ISM or MASA are known */ + if ( arg.outputFormat == IVAS_DEC_OUTPUT_EXT ) + { + if ( ( error = IVAS_DEC_GetFormat( hIvasDec, pBsFormat ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetFormat, code: %d\n", error ); + return error; + } + + /* If outputting ISM, get number of objects, open output files and write zero metadata for initial bad frames */ + if ( *pBsFormat == IVAS_DEC_BS_OBJ ) + { + if ( ( error = IVAS_DEC_GetNumObjects( hIvasDec, pNumObj ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetNumObjects: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + return error; + } + + for ( int16_t i = 0; i < *pNumObj; ++i ) + { + if ( ( error = IsmFileWriter_open( arg.outputWavFilename, i, &ismWriters[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: Error opening ISM decoded metadata file %s\n", IsmFileWriter_getFilePath( ismWriters[i] ) ); + return error; + } + } + + for ( int16_t j = 0; j < numInitialBadFrames; ++j ) + { + /* write zero metadata */ + for ( int16_t i = 0; i < *pNumObj; ++i ) + { + IVAS_ISM_METADATA IsmMetadata; + + if ( ( error = IVAS_DEC_GetObjectMetadata( hIvasDec, &IsmMetadata, 1, i ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetObjectMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + return error; + } + + if ( ( error = IsmFileWriter_writeFrame( IsmMetadata, ismWriters[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing ISM metadata to file %s\n", IsmFileWriter_getFilePath( ismWriters[i] ) ); + return error; + } + } + } + } + /* If outputting MASA, open output file and write metadata for initial bad frames */ + else if ( *pBsFormat == IVAS_DEC_BS_MASA ) + { + if ( ( error = MasaFileWriter_open( arg.outputWavFilename, ppMasaWriter ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: Error opening MASA decoded metadata file %s\n", MasaFileWriter_getFilePath( *ppMasaWriter ) ); + return error; + } + + /* Duplicate good first frame metadata to fill the beginning of stream. */ + IVAS_MASA_QMETADATA_HANDLE qMetadata = NULL; + if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &qMetadata ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetMasaMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + return error; + } + + for ( int16_t j = 0; j < numInitialBadFrames; ++j ) + { + if ( ( error = MasaFileWriter_writeFrame( *ppMasaWriter, qMetadata ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( *ppMasaWriter ) ); + return error; + } + } + } + } + + return IVAS_ERR_OK; +} +#endif + /*---------------------------------------------------------------------* * decodeG192() * @@ -1144,7 +1314,11 @@ static ivas_error decodeG192( { bool decodingFailed = true; /* Assume failure until cleanup is reached without errors */ uint16_t bit_stream[IVAS_MAX_BITS_PER_FRAME + 4 * 8]; +#ifdef MC_JBM + int16_t i, num_bits; +#else int16_t i, j, num_bits; +#endif int16_t bfi = 0; #ifdef DEBUGGING int16_t fec_seed = 12558; /* FEC_SEED */ @@ -1156,7 +1330,9 @@ static ivas_error decodeG192( int16_t nOutChannels = 0; int16_t delayNumSamples = -1; int16_t delayNumSamples_orig = 0; +#ifndef MC_JBM int16_t zeroPad = 0; +#endif int16_t nOutSamples = 0; int32_t delayTimeScale = 0; ivas_error error = IVAS_ERR_UNKNOWN; @@ -1264,6 +1440,27 @@ static ivas_error decodeG192( /* Once good frame decoded, catch up */ if ( decodedGoodFrame ) { +#ifdef MC_JBM + error = initOnFirstGoodFrame( + hIvasDec, + arg, + numInitialBadFrames, + nOutSamples, + &delayNumSamples_orig, + &delayNumSamples, + &delayTimeScale, + &bsFormat, + &afWriter, + &masaWriter, + ismWriters, + &nOutChannels, + &numObj ); + if ( error != IVAS_ERR_OK ) + { + goto cleanup; + } +#else + /* Now number of output channels and frame size are known */ if ( ( error = IVAS_DEC_GetNumOutputChannels( hIvasDec, &nOutChannels ) ) != IVAS_ERR_OK ) { @@ -1383,6 +1580,7 @@ static ivas_error decodeG192( } } } +#endif } else { @@ -1390,6 +1588,7 @@ static ivas_error decodeG192( } } +#ifndef MC_JBM if ( delayNumSamples == -1 ) { if ( arg.delayCompensationEnabled ) @@ -1407,6 +1606,7 @@ static ivas_error decodeG192( } zeroPad = delayNumSamples; } +#endif /* Write current frame */ if ( decodedGoodFrame ) @@ -1519,12 +1719,21 @@ static ivas_error decodeG192( } /* add zeros at the end to have equal length of synthesized signals */ +#ifdef MC_JBM + memset( pcmBuf, 0, delayNumSamples_orig * nOutChannels * sizeof( int16_t ) ); + if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, delayNumSamples_orig * nOutChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing output file: %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } +#else memset( pcmBuf, 0, zeroPad * nOutChannels * sizeof( int16_t ) ); if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, zeroPad * nOutChannels ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nOutput audio file writer error\n" ); goto cleanup; } +#endif /*------------------------------------------------------------------------------------------* * Close files and deallocate resources @@ -1549,11 +1758,119 @@ cleanup: return error; } +#ifdef MC_JBM +#ifdef DEBUGGING +/*---------------------------------------------------------------------* + * printBitstreamInfoVoip() + * + * Print bitstream info of a VoIP G.192 or RTPDUMP bitstream. + *---------------------------------------------------------------------*/ +static ivas_error printBitstreamInfoVoip( + DecArguments arg, + BS_READER_HANDLE hBsReader, + IVAS_DEC_HANDLE hIvasDec ) +{ + bool previewFailed = true; + ivas_error error = IVAS_ERR_OK; + FILE *f_rtpstream = NULL; + EVS_RTPDUMP_DEPACKER rtpdumpDepacker; + EVS_RTPDUMP_DEPACKER_ERROR rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_NO_ERROR; + uint8_t au[( IVAS_MAX_BITS_PER_FRAME + 7 ) >> 3]; + int16_t auSizeBits; + uint8_t *auPtr = NULL; + bool isAMRWB_IOmode; + uint16_t frameTypeIndex; + bool qBit; + uint32_t nextPacketRcvTime_ms = 0; + uint16_t rtpSequenceNumber; + uint32_t rtpTimeStamp; + + rtpdumpDepacker.rtpdump = NULL; + switch ( arg.inputFormat ) + { + case IVAS_DEC_INPUT_FORMAT_RTPDUMP: + case IVAS_DEC_INPUT_FORMAT_RTPDUMP_HF: + f_rtpstream = fopen( arg.inputBitstreamFilename, "r" ); + + if ( f_rtpstream == NULL ) + { + fprintf( stderr, "could not open: %s\n", arg.inputBitstreamFilename ); + goto cleanup; + } + + rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_open( &rtpdumpDepacker, f_rtpstream, arg.inputFormat == IVAS_DEC_INPUT_FORMAT_RTPDUMP_HF ); + if ( rtpdumpDepackerError != EVS_RTPDUMP_DEPACKER_NO_ERROR ) + { + fprintf( stderr, "error in EVS_RTPDUMP_DEPACKER_open(): %d\n", rtpdumpDepackerError ); + goto cleanup; + } + break; + case IVAS_DEC_INPUT_FORMAT_G192: + auPtr = au; + break; + default: + fprintf( stderr, "Unsupported format of input bitstream" ); + goto cleanup; + } + + /* Keep reading until full frame is found */ + do + { + if ( arg.inputFormat == IVAS_DEC_INPUT_FORMAT_G192 ) + { + error = BS_Reader_ReadVoipFrame_compact( hBsReader, au, &auSizeBits, &rtpSequenceNumber, &rtpTimeStamp, &nextPacketRcvTime_ms ); + qBit = 1; /* good q_bit for INPUT_FORMAT_G192 */ + } + else + { + auPtr = au; /* might have been set to RTP packet in prev call */ + rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_readNextFrame( &rtpdumpDepacker, &rtpSequenceNumber, &rtpTimeStamp, + &nextPacketRcvTime_ms, + &isAMRWB_IOmode, &frameTypeIndex, &qBit, + &auPtr, (uint16_t *) &auSizeBits ); + /* EVS RTP payload format has timescale 16000, JBM uses 1000 internally */ + rtpTimeStamp = rtpTimeStamp / 16; + } + if ( error != IVAS_ERR_OK || rtpdumpDepackerError != EVS_RTPDUMP_DEPACKER_NO_ERROR ) + { + fprintf( stderr, "failed to read first RTP packet\n" ); + goto cleanup; + } +#ifdef REMOVE_SID_HARM_LEFTOVERS + } while (!qBit || auSizeBits < MIN_NUM_BITS_ACTIVE_FRAME || auSizeBits == NUM_BITS_SID_IVAS_5K2 ); +#else + } while (!qBit || auSizeBits < MIN_NUM_BITS_ACTIVE_FRAME || auSizeBits == NUM_BITS_SID_IVAS_4K4 || auSizeBits == NUM_BITS_SID_IVAS_7K8 || auSizeBits == NUM_BITS_SID_IVAS_9K3 || auSizeBits == NUM_BITS_SID_IVAS_10K2 ); +#endif + + BS_Reader_Rewind( hBsReader ); + + IVAS_DEC_PrintConfigWithVoipBitstream( hIvasDec, arg.quietModeEnabled, au, auSizeBits ); + + /*------------------------------------------------------------------------------------------* + * Close fhandles and deallocate resources + *------------------------------------------------------------------------------------------*/ + + previewFailed = false; /* This will stay set to true if cleanup is reached via a goto due to an error */ + +cleanup: + + EVS_RTPDUMP_DEPACKER_close( &rtpdumpDepacker ); + + if ( previewFailed && error == IVAS_ERR_OK ) + { + return IVAS_ERR_UNKNOWN; + } + + return IVAS_ERR_OK; +} +#endif +#endif + /*---------------------------------------------------------------------* * decodeVoIP() * - * Read G.192 bitstream and decode in VOIP + * Read G.192 or RTPDUMP bitstream and decode in VOIP *---------------------------------------------------------------------*/ static ivas_error decodeVoIP( @@ -1573,23 +1890,36 @@ static ivas_error decodeVoIP( uint16_t rtpSequenceNumber; uint32_t rtpTimeStamp; +#ifdef MC_JBM + bool decodedGoodFrame = false; + int16_t numInitialBadFrames = 0; /* Number of bad frames received until first good frame is decoded */ + int16_t nOutChannels = 0; + MasaFileWriter *masaWriter = NULL; + uint16_t numObj = 0; + + const uint32_t pcmBufSizeWithSampleBasedTimeScaling = 3 * MAX_OUTPUT_PCM_BUFFER_SIZE; + int16_t pcmBuf[3 * MAX_OUTPUT_PCM_BUFFER_SIZE]; +#else /* For now always assume output with one channel. When adding VoIP to IVAS, * initialization of the memory for jitter buffer etc. needs to happen after * first good frame has been decoded because for some configs (such as EXT * renderer) only then the number of output channels is known.*/ const int16_t nOutChannels = 1; + const uint32_t pcmBufSizeWithSampleBasedTimeScaling = 3 * MAX_FRAME_SIZE; + int16_t pcmBuf[3 * MAX_FRAME_SIZE]; +#endif AudioFileWriter *afWriter = NULL; #ifdef SUPPORT_JBM_TRACEFILE JbmTraceFileWriter *jbmTraceWriter = NULL; #endif JbmOffsetFileWriter *jbmOffsetWriter = NULL; - const uint32_t pcmBufSizeWithSampleBasedTimeScaling = 3 * MAX_FRAME_SIZE; - int16_t pcmBuf[3 * MAX_FRAME_SIZE]; int16_t delayNumSamples_orig = -1; int16_t delayNumSamples = -1; int32_t delayTimeScale = -1; +#ifndef MC_JBM int16_t zeroPad = 0; +#endif FILE *f_rtpstream = NULL; EVS_RTPDUMP_DEPACKER rtpdumpDepacker; @@ -1599,6 +1929,15 @@ static ivas_error decodeVoIP( uint16_t frameTypeIndex; bool qBit; +#ifdef MC_JBM + IVAS_DEC_BS_FORMAT bsFormat = IVAS_DEC_BS_UNKOWN; + IsmFileWriter *ismWriters[IVAS_MAX_NUM_OBJECTS]; + for ( int16_t i = 0; i < IVAS_MAX_NUM_OBJECTS; ++i ) + { + ismWriters[i] = NULL; + } +#endif + memset( pcmBuf, 0, pcmBufSizeWithSampleBasedTimeScaling ); rtpdumpDepacker.rtpdump = NULL; @@ -1629,11 +1968,13 @@ static ivas_error decodeVoIP( goto cleanup; } +#ifndef MC_JBM if ( ( error = AudioFileWriter_open( &afWriter, arg.outputWavFilename, arg.output_Fs, nOutChannels ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nUnable to open output file %s\n", arg.outputWavFilename ); goto cleanup; } +#endif #ifdef SUPPORT_JBM_TRACEFILE if ( arg.jbmTraceFilename != NULL ) @@ -1661,10 +2002,12 @@ static ivas_error decodeVoIP( if ( arg.inputFormat == IVAS_DEC_INPUT_FORMAT_G192 ) { error = BS_Reader_ReadVoipFrame_compact( hBsReader, au, &auSize, &rtpSequenceNumber, &rtpTimeStamp, &nextPacketRcvTime_ms ); +#ifndef MC_JBM if ( !evsPayload_getFrameTypeFromSize( auSize, &isAMRWB_IOmode, &frameTypeIndex ) ) { error = IVAS_ERR_BITSTREAM_READER_INVALID_DATA; } +#endif qBit = 1; /* good q_bit for INPUT_FORMAT_G192 */ } else @@ -1710,7 +2053,11 @@ static ivas_error decodeVoIP( while ( nextPacketRcvTime_ms <= systemTime_ms ) { /* feed the previous read packet into the receiver now */ +#ifdef MC_JBM + error = IVAS_DEC_VoIP_FeedFrame( hIvasDec, auPtr, auSize, rtpSequenceNumber, rtpTimeStamp, nextPacketRcvTime_ms, qBit ); +#else error = IVAS_DEC_VoIP_FeedFrame( hIvasDec, auPtr, auSize, rtpSequenceNumber, rtpTimeStamp, nextPacketRcvTime_ms, isAMRWB_IOmode, frameTypeIndex, qBit ); +#endif if ( error != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_VoIP_FeedFrame: %s\n", IVAS_DEC_GetErrorMessage( error ) ); @@ -1723,10 +2070,12 @@ static ivas_error decodeVoIP( { error = BS_Reader_ReadVoipFrame_compact( hBsReader, au, &auSize, &rtpSequenceNumber, &rtpTimeStamp, &nextPacketRcvTime_ms ); +#ifndef MC_JBM if ( !evsPayload_getFrameTypeFromSize( auSize, &isAMRWB_IOmode, &frameTypeIndex ) ) { error = IVAS_ERR_BITSTREAM_READER_INVALID_DATA; } +#endif qBit = 1; /* good q_bit for VOIP_G192_RTP */ } else @@ -1758,8 +2107,15 @@ static ivas_error decodeVoIP( break; } +#ifdef MC_JBM + nOutSamples = arg.output_Fs / 50; + + /* decode and get samples */ + if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, pcmBuf, systemTime_ms ) ) != IVAS_ERR_OK ) +#else /* decode and get samples */ if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, &nOutSamples, pcmBuf, pcmBufSizeWithSampleBasedTimeScaling, systemTime_ms ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "\nError in IVAS_DEC_VoIP_GetSamples: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -1803,6 +2159,46 @@ static ivas_error decodeVoIP( } } +#ifdef MC_JBM + /* Continue checking for first good frame until it is found */ + if ( !decodedGoodFrame ) + { + if ( ( error = IVAS_DEC_HasDecodedFirstGoodFrame( hIvasDec, &decodedGoodFrame ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error 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; + } + } +#endif + +#ifndef MC_JBM if ( delayNumSamples == -1 ) { if ( arg.delayCompensationEnabled ) @@ -1820,20 +2216,29 @@ static ivas_error decodeVoIP( } zeroPad = delayNumSamples; } +#endif - if ( delayNumSamples < nOutSamples ) + /* Write current frame */ +#ifdef MC_JBM + if ( decodedGoodFrame ) { - if ( ( error = AudioFileWriter_write( afWriter, &pcmBuf[delayNumSamples * nOutChannels], nOutSamples * nOutChannels - ( delayNumSamples * nOutChannels ) ) ) != IVAS_ERR_OK ) +#endif + if ( delayNumSamples < nOutSamples ) { - fprintf( stderr, "\nOutput audio file writer error\n" ); - goto cleanup; + 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; } - delayNumSamples = 0; - } - else - { - delayNumSamples -= nOutSamples; + else + { + delayNumSamples -= nOutSamples; + } +#ifdef MC_JBM } +#endif if ( !arg.quietModeEnabled ) { @@ -1853,10 +2258,19 @@ static ivas_error decodeVoIP( #endif } - +#ifdef MC_JBM + /* add zeros at the end to have equal length of synthesized signals */ + memset( pcmBuf, 0, delayNumSamples_orig * nOutChannels * sizeof( int16_t ) ); + if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, delayNumSamples_orig * nOutChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing output file: %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } +#else /* add zeros at the end to have equal length of synthesized signals */ memset( pcmBuf, 0, zeroPad * nOutChannels * sizeof( int16_t ) ); AudioFileWriter_write( afWriter, pcmBuf, zeroPad * nOutChannels ); +#endif /*------------------------------------------------------------------------------------------* * Printouts after decoding has finished @@ -1875,6 +2289,9 @@ static ivas_error decodeVoIP( cleanup: +#ifdef MC_JBM + EVS_RTPDUMP_DEPACKER_close( &rtpdumpDepacker ); +#endif AudioFileWriter_close( &afWriter ); JbmOffsetFileWriter_close( &jbmOffsetWriter ); #ifdef SUPPORT_JBM_TRACEFILE diff --git a/lib_com/bitstream.c b/lib_com/bitstream.c index 12f172f2a3..871981bb18 100644 --- a/lib_com/bitstream.c +++ b/lib_com/bitstream.c @@ -2020,7 +2020,11 @@ ivas_error read_indices( file_read_FECpattern( &st_ivas->bfi ); st_ivas->bfi |= bfi; +#ifdef MC_JBM + if ( bfi == FRAMEMODE_MISSING ) /* TODO(mcjbm): This fixes channel-aware mode BE. Still requires review from a bitstream reading expert */ +#else if ( bfi ) +#endif { for ( k = 0; k < num_bits; k++ ) { @@ -2185,7 +2189,11 @@ ivas_error read_indices( } /* handle bad/lost speech frame(and CS bad SID frame) in the decoders CNG synthesis settings pair (total_brate, bfi) */ - if ( ( ( *CNG != 0 ) && ( ( speech_bad != 0 ) || ( speech_lost != 0 ) ) ) || /* SP_BAD or SPEECH_LOST) --> stay in CNG */ + if ( ( +#ifdef MC_JBM + bfi != FRAMEMODE_FUTURE && /* TODO(mcjbm): This fixes channel-aware mode BE. Still requires review from a bitstream reading expert */ +#endif + ( *CNG != 0 ) && ( ( speech_bad != 0 ) || ( speech_lost != 0 ) ) ) || /* SP_BAD or SPEECH_LOST) --> stay in CNG */ ( sid_upd_bad != 0 ) ) /* SID_UPD_BAD --> start CNG */ { st_ivas->bfi = 0; /* bfi=0 needed to activate CNG code */ @@ -2228,7 +2236,11 @@ ivas_error read_indices( } /* GOOD frame */ - if ( st_ivas->bfi == 0 ) + if ( st_ivas->bfi == 0 +#ifdef MC_JBM + || st_ivas->bfi == FRAMEMODE_FUTURE /* TODO(mcjbm): This fixes channel-aware mode BE. Still requires review from a bitstream reading expert */ +#endif + ) { /* GOOD frame - convert ITU-T G.192 words to short values */ st_ivas->hDecoderConfig->ivas_total_brate = total_brate; diff --git a/lib_com/ivas_error.h b/lib_com/ivas_error.h index fdc7a1502d..397f78f277 100644 --- a/lib_com/ivas_error.h +++ b/lib_com/ivas_error.h @@ -87,6 +87,9 @@ typedef enum IVAS_ERR_INVALID_INDEX, IVAS_ERR_NOT_SUPPORTED_OPTION, IVAS_ERR_NOT_IMPLEMENTED, +#ifdef MC_JBM + IVAS_ERR_WAITING_FOR_BITSTREAM, +#endif IVAS_ERR_FILE_READER_TIMESTAMP_MISMATCH, IVAS_ERR_ISM_FILE_READER_INVALID_METADATA_FORMAT, IVAS_ERR_INVALID_MASA_FORMAT_METADATA_FILE, diff --git a/lib_com/options.h b/lib_com/options.h index 21fe824853..117c7e068d 100755 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -168,6 +168,8 @@ #define CLEANUP_185_NO_AGC_EXCEPTION /* Issue 185: Cleanup AGC EXCEPTION code */ #endif +#define MC_JBM /* FhG: extend JBM beyond mono for running IVAS in VoIP mode (contribution 19) */ + /* ################## End DEVELOPMENT switches ######################### */ /* clang-format on */ diff --git a/lib_debug/debug.h b/lib_debug/debug.h index abf246674a..ed9c2776c2 100644 --- a/lib_debug/debug.h +++ b/lib_debug/debug.h @@ -44,7 +44,9 @@ * Global variables used for debugging *------------------------------------------------------------------------------------------*/ +#ifdef DEBUGGING extern int32_t frame; +#endif #ifdef DEBUGGING extern uint16_t g_nPrintedLines; diff --git a/lib_debug/memory.c b/lib_debug/memory.c index afd292ddbc..27a6768080 100644 --- a/lib_debug/memory.c +++ b/lib_debug/memory.c @@ -47,6 +47,8 @@ #ifdef WMOPS +extern int32_t frame; + /*-------------------------------------------------------------------* * Memory counting tool *--------------------------------------------------------------------*/ diff --git a/lib_dec/jbm_jb4sb.h b/lib_dec/jbm_jb4sb.h index bc70413689..7142a6fd20 100644 --- a/lib_dec/jbm_jb4sb.h +++ b/lib_dec/jbm_jb4sb.h @@ -63,9 +63,11 @@ struct JB4_DATAUNIT uint32_t rcvTime; /** true, if the data unit contains only silence */ bool silenceIndicator; +#ifndef MC_JBM Word16 isAMRWB_IOmode; /** for EVS payload */ Word16 frameTypeIndex; +#endif /** Q bit for AMR-WB IO */ Word16 qBit; diff --git a/lib_dec/jbm_pcmdsp_apa.c b/lib_dec/jbm_pcmdsp_apa.c index 3968e38974..9057f103a5 100644 --- a/lib_dec/jbm_pcmdsp_apa.c +++ b/lib_dec/jbm_pcmdsp_apa.c @@ -70,7 +70,11 @@ struct apa_state_t uint16_t l_buf_out; /* Hann window */ +#ifdef MC_JBM + float win[APA_BUF_PER_CHANNEL]; +#else float win[APA_BUF]; +#endif uint16_t l_halfwin; /* sampling rate [Hz] */ @@ -99,8 +103,8 @@ struct apa_state_t /* search length [samples] */ uint16_t l_search; - uint16_t wss; /* waveform subsampling */ - uint16_t css; /* correlation subsampling */ + uint16_t wss; /* waveform subsampling per channel */ + uint16_t css; /* correlation subsampling per channel */ float targetQuality; uint16_t qualityred; /* quality reduction threshold */ @@ -217,6 +221,12 @@ bool apa_set_rate( ps->rate = (uint16_t) output_Fs; /* set number of channels */ +#ifdef MC_JBM + if ( num_channels > APA_MAX_NUM_CHANNELS ) + { + return 1; + } +#endif ps->num_channels = num_channels; /* @@ -235,8 +245,12 @@ bool apa_set_rate( ps->l_seg = ( ps->rate / 100 ) * ps->num_channels; /* init Hann window */ +#ifdef MC_JBM + /* Note: l_win < APA_BUF_PER_CHANNEL is required */ +#else /* Note: l_win < APA_BUF is required, which is assured */ /* because APA_MAX_RATE/100 = l_win = 441 < 2048 = APA_BUF */ +#endif /* Length of Hann window should be independent of * number of channels - same window applied to all channels */ ps->l_halfwin = ps->rate / 100; @@ -462,6 +476,11 @@ uint8_t apa_exec( statsResetThreshold = 1637; statsResetShift = 2; +#ifdef MC_JBM + /* Convert max_scaling from "per channel" to total */ + maxScaling *= ps->num_channels; +#endif + /* make sure no invalid output is used */ *l_out = 0; l_frm_out = 0; @@ -818,7 +837,11 @@ static bool logarithmic_search( do { coeff_max = -FLT_MAX; /* will always be overwritten with result of first correlation */ +#ifdef MC_JBM + for ( i = s_start; i < s_start + inlen; i += css * ps->num_channels ) +#else for ( i = s_start; i < s_start + inlen; i += css ) +#endif { if ( ( wss == 1 ) && ( ps->num_channels == 1 ) ) { @@ -929,7 +952,11 @@ static bool find_synch( /* pass last pitch to search function as prediction value */ *synch_pos = ps->last_pitch; +#ifdef MC_JBM + logarithmic_search( ps, in, s_start, s_len, offset, fixed_pos, corr_len, ps->wss, ps->css, synch_pos ); +#else logarithmic_search( ps, in, s_start, s_len, offset, fixed_pos, corr_len, ps->wss, ps->css * ps->num_channels, synch_pos ); +#endif /* assert synch_pos is cleanly divisible by number of channels */ assert( *synch_pos % ps->num_channels == 0 ); diff --git a/lib_dec/jbm_pcmdsp_apa.h b/lib_dec/jbm_pcmdsp_apa.h index 5cf4e7d8b6..e3628489ad 100644 --- a/lib_dec/jbm_pcmdsp_apa.h +++ b/lib_dec/jbm_pcmdsp_apa.h @@ -50,7 +50,13 @@ */ /* size of IO buffers (a_in[], a_out[]) for apa_exec() */ -#define APA_BUF 4096 * 3 +#ifdef MC_JBM +#define APA_BUF_PER_CHANNEL ( 960 * 3 ) +#define APA_MAX_NUM_CHANNELS 16 +#define APA_BUF ( APA_BUF_PER_CHANNEL * APA_MAX_NUM_CHANNELS ) +#else + #define APA_BUF 4096 * 3 +#endif /* min/max sampling rate [Hz] */ #define APA_MIN_RATE 1000 diff --git a/lib_dec/jbm_pcmdsp_fifo.c b/lib_dec/jbm_pcmdsp_fifo.c index 86990618fd..6c203318e4 100644 --- a/lib_dec/jbm_pcmdsp_fifo.c +++ b/lib_dec/jbm_pcmdsp_fifo.c @@ -97,15 +97,27 @@ void pcmdsp_fifo_destroy( /* Initializes the FIFO with a fixed maximum allowed number audio samples. */ int16_t pcmdsp_fifo_init( PCMDSP_FIFO_HANDLE h, +#ifdef MC_JBM + uint16_t nSamplesPerChannel, +#else uint16_t nSamples, +#endif uint16_t nChannels, uint16_t nBytesPerSample ) { +#ifdef MC_JBM + uint32_t nDataBytes; /* Must be 32-bit, otherwise overflows for multichannel */ + + h->capacity = nSamplesPerChannel; + h->nBytesPerSampleSet = nChannels * nBytesPerSample; + nDataBytes = nSamplesPerChannel * h->nBytesPerSampleSet; +#else uint16_t nDataBytes; h->capacity = nSamples; h->nBytesPerSampleSet = nChannels * nBytesPerSample; nDataBytes = nSamples * h->nBytesPerSampleSet; +#endif h->dataBegin = count_malloc( nDataBytes ); h->dataEnd = h->dataBegin + nDataBytes; h->dataWriteIterator = h->dataBegin; @@ -201,7 +213,11 @@ int16_t pcmdsp_fifo_read( /* Returns the number of samples per channel that can be read (number of currently stored samples). */ +#ifdef MC_JBM +uint16_t pcmdsp_fifo_nReadableSamplesPerChannel( +#else uint16_t pcmdsp_fifo_nReadableSamples( +#endif const PCMDSP_FIFO_HANDLE h ) { return h->size; diff --git a/lib_dec/jbm_pcmdsp_fifo.h b/lib_dec/jbm_pcmdsp_fifo.h index bdd186702e..0265f745a8 100644 --- a/lib_dec/jbm_pcmdsp_fifo.h +++ b/lib_dec/jbm_pcmdsp_fifo.h @@ -70,12 +70,20 @@ int16_t pcmdsp_fifo_create( PCMDSP_FIFO_HANDLE *ph ); void pcmdsp_fifo_destroy( PCMDSP_FIFO_HANDLE *ph ); +#ifdef MC_JBM +int16_t pcmdsp_fifo_init( PCMDSP_FIFO_HANDLE h, uint16_t nSamplesPerChannel, uint16_t nChannels, uint16_t nBytesPerSample ); +#else int16_t pcmdsp_fifo_init( PCMDSP_FIFO_HANDLE h, uint16_t nSamples, uint16_t nChannels, uint16_t nBytesPerSample ); +#endif int16_t pcmdsp_fifo_write( PCMDSP_FIFO_HANDLE h, const uint8_t *samples, uint16_t nSamplesPerChannel ); int16_t pcmdsp_fifo_read( PCMDSP_FIFO_HANDLE h, uint16_t nSamplesPerChannel, uint8_t *samples ); +#ifdef MC_JBM +uint16_t pcmdsp_fifo_nReadableSamplesPerChannel(const PCMDSP_FIFO_HANDLE h ); +#else uint16_t pcmdsp_fifo_nReadableSamples( const PCMDSP_FIFO_HANDLE h ); +#endif #endif /* JBM_PCMDSP_FIFO_H */ diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index d16d1f2494..0c0588b5aa 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -42,9 +42,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#ifdef WMOPS #include "wmops.h" -#endif /*---------------------------------------------------------------------* * Local structs @@ -52,7 +50,7 @@ struct IVAS_DEC_VOIP { - uint16_t nSamplesFrame; + 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; @@ -80,6 +78,10 @@ struct IVAS_DEC int16_t sdp_hf_only; /* RTP payload format parameter: only Header-Full format without zero padding for size collision avoidance */ int16_t prev_ft_speech; /* RXDTX handler: previous frametype flag for G.192 format AMRWB SID_FIRST detection */ int16_t CNG; /* RXDTX handler: CNG=1, nonCNG=0 */ + +#ifdef MC_JBM + JB4_DATAUNIT_HANDLE hCurrentDataUnit; +#endif }; @@ -130,6 +132,9 @@ ivas_error IVAS_DEC_Open( hIvasDec->hasBeenFedFirstGoodFrame = false; hIvasDec->hasDecodedFirstGoodFrame = false; hIvasDec->isInitialized = false; +#ifdef MC_JBM + hIvasDec->hCurrentDataUnit = NULL; +#endif hIvasDec->mode = mode; @@ -486,6 +491,7 @@ ivas_error IVAS_DEC_EnableVoIP( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } +#ifndef MC_JBM if ( !hIvasDec->isInitialized ) { if ( ( error = ivas_init_decoder( hIvasDec->st_ivas ) ) != IVAS_ERR_OK ) @@ -496,19 +502,31 @@ ivas_error IVAS_DEC_EnableVoIP( hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = ACELP_8k00; hIvasDec->isInitialized = true; } +#endif hDecoderConfig = hIvasDec->st_ivas->hDecoderConfig; hIvasDec->Opt_VOIP = 1; + +#ifdef MC_JBM + hDecoderConfig->nchan_out = audioCfg2channels( hDecoderConfig->output_config ); + assert( hDecoderConfig->nchan_out > 0 && "EXT output not yet supported in VoIP mode" ); +#else hIvasDec->st_ivas->hSCE[0]->hCoreCoder[0]->codec_mode = 0; hDecoderConfig->nchan_out = 1; /* VoIP only supported in mono */ +#endif + if ( ( error = input_format_API_to_internal( inputFormat, &hIvasDec->bitstreamformat, &hIvasDec->sdp_hf_only, true ) ) != IVAS_ERR_OK ) { return error; } hIvasDec->hVoIP = count_malloc( sizeof( IVAS_DEC_VOIP ) ); hIvasDec->hVoIP->lastDecodedWasActive = 0; +#ifdef MC_JBM + hIvasDec->hVoIP->nSamplesFrame = (uint16_t) ( hDecoderConfig->output_Fs * hDecoderConfig->nchan_out / FRAMES_PER_SEC ); +#else hIvasDec->hVoIP->nSamplesFrame = (uint16_t) ( hDecoderConfig->output_Fs / FRAMES_PER_SEC ); +#endif /* Copy updated configuration to core coder */ @@ -575,7 +593,7 @@ ivas_error IVAS_DEC_FeedFrame_Serial( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ uint16_t *serial, /* i : buffer containing serial input bitstream. Each bit should be stored as a single uint16_t value */ const uint16_t num_bits, /* i : number of bits in input bitstream */ - const int16_t bfi /* i : bad frame indicator flag */ + int16_t bfi /* i : bad frame indicator flag */ ) { ivas_error error; @@ -593,19 +611,68 @@ ivas_error IVAS_DEC_FeedFrame_Serial( return error; } +#ifdef MC_JBM + if ( hIvasDec->hCurrentDataUnit != NULL ) + { + DEC_CORE_HANDLE st = hIvasDec->st_ivas->hSCE[0]->hCoreCoder[0]; + st->ini_frame = 0; + st->prev_use_partial_copy = 0; + hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = hIvasDec->hCurrentDataUnit->dataSize * FRAMES_PER_SEC; + } + else + { + hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = ACELP_8k00; + } +#else hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = ACELP_8k00; +#endif } hIvasDec->isInitialized = true; } - if ( !bfi ) + if ( !bfi ) /* TODO(mcjbm): Is this ok for bfi == 2 (partial frame)? Is there enough info to fully configure decoder? */ { hIvasDec->hasBeenFedFirstGoodFrame = true; } +#ifdef MC_JBM + /* Update redundant frame information in EVS (pre- read indices) */ + if ( hIvasDec->mode == IVAS_DEC_MODE_EVS && hIvasDec->hCurrentDataUnit != NULL ) + { + DEC_CORE_HANDLE st = hIvasDec->st_ivas->hSCE[0]->hCoreCoder[0]; + st->bit_stream = serial; + + if ( hIvasDec->hCurrentDataUnit->partial_frame || st->prev_use_partial_copy ) + { + st->next_coder_type = hIvasDec->hCurrentDataUnit->nextCoderType; + } + else + { + st->next_coder_type = INACTIVE; + } + + if ( hIvasDec->hCurrentDataUnit->partial_frame == 1 && bfi != 1 ) + { + bfi = 2; + } + } +#endif + error = read_indices( hIvasDec->st_ivas, serial, num_bits, &hIvasDec->prev_ft_speech, &hIvasDec->CNG, bfi ); +#ifdef MC_JBM + /* Update redundant frame information in EVS (post- read indices) */ + if ( hIvasDec->mode == IVAS_DEC_MODE_EVS && + hIvasDec->hCurrentDataUnit != NULL && + hIvasDec->hCurrentDataUnit->partial_frame != 0 ) + { + DEC_CORE_HANDLE st = hIvasDec->st_ivas->hSCE[0]->hCoreCoder[0]; + st->codec_mode = MODE2; + st->use_partial_copy = 1; + } +#endif + return error; } @@ -619,7 +686,7 @@ ivas_error IVAS_DEC_FeedFrame_Serial( ivas_error IVAS_DEC_GetSamples( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ 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 */ - int16_t *nOutSamples /* o : number of samples written to output buffer */ + int16_t *nOutSamples /* o : number of samples per channel written to output buffer */ ) { Decoder_Struct *st_ivas; @@ -1052,6 +1119,14 @@ ivas_error IVAS_DEC_GetDelay( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } +#ifdef MC_JBM + if ( !hIvasDec->hasDecodedFirstGoodFrame ) + { + /* Delay depends on IVAS format, which is unknown until first frame has been decoded */ + return IVAS_ERR_WAITING_FOR_BITSTREAM; + } +#endif + st_ivas = hIvasDec->st_ivas; hDecoderConfig = st_ivas->hDecoderConfig; @@ -1139,11 +1214,32 @@ static bool isSidFrame( return false; } +#ifdef MC_JBM +static void bsCompactToSerial( const uint8_t *compact, uint16_t *serial, uint16_t num_bits ) +{ + uint32_t i; + uint8_t byte; + const uint8_t mask = 0x80; + + for ( i = 0; i < num_bits; ++i ) + { + if ( i % 8 == 0 ) + { + byte = compact[i / 8]; + } + + serial[i] = ( byte & mask ) >> 7; + + byte <<= 1; + } +} +#endif + /*---------------------------------------------------------------------* * IVAS_DEC_VoIP_FeedFrame( ) * - * + * Feed RTP packet into internal jitter buffer *---------------------------------------------------------------------*/ ivas_error IVAS_DEC_VoIP_FeedFrame( @@ -1153,9 +1249,11 @@ ivas_error IVAS_DEC_VoIP_FeedFrame( const uint16_t rtpSequenceNumber, /* i : RTP sequence number (16 bits) */ const uint32_t rtpTimeStamp, /* i : RTP timestamp (32 bits) */ const uint32_t rcvTime_ms, /* i : receive time of the RTP packet in milliseconds */ - const bool isAMRWB_IOmode, /* i : AMRWB flag */ - const uint16_t frameTypeIndex, /* i : core mode for frame */ - const bool qBit /* i : Q bit for AMR-WB IO */ +#ifndef MC_JBM + const bool isAMRWB_IOmode, /* i : AMRWB flag */ + const uint16_t frameTypeIndex, /* i : core mode for frame */ +#endif + const bool qBit /* i : Q bit for AMR-WB IO */ ) { JB4_DATAUNIT_HANDLE dataUnit; @@ -1186,8 +1284,10 @@ ivas_error IVAS_DEC_VoIP_FeedFrame( dataUnit->timeStamp = rtpTimeStamp; dataUnit->partial_frame = 0; dataUnit->partialCopyOffset = partialCopyOffset; +#ifndef MC_JBM dataUnit->isAMRWB_IOmode = isAMRWB_IOmode; dataUnit->frameTypeIndex = frameTypeIndex; +#endif dataUnit->qBit = qBit; /* add the frame to the JBM */ @@ -1211,8 +1311,10 @@ ivas_error IVAS_DEC_VoIP_FeedFrame( dataUnit->timeStamp = rtpTimeStamp - partialCopyOffset * dataUnit->duration; dataUnit->partial_frame = 1; dataUnit->partialCopyOffset = partialCopyOffset; +#ifndef MC_JBM dataUnit->isAMRWB_IOmode = isAMRWB_IOmode; dataUnit->frameTypeIndex = frameTypeIndex; +#endif dataUnit->qBit = qBit; /* add the frame to the JBM */ @@ -1235,45 +1337,77 @@ ivas_error IVAS_DEC_VoIP_FeedFrame( ivas_error IVAS_DEC_VoIP_GetSamples( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ +#ifdef MC_JBM + 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 */ +#else int16_t *nOutSamples, /* o : number of samples 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 pcmBufSize, /* i : size of the PCM output buffer */ +#endif const uint32_t systemTimestamp_ms /* i : current system timestamp */ ) { Decoder_Struct *st_ivas; DECODER_CONFIG_HANDLE hDecoderConfig; +#ifndef MC_JBM Decoder_State *st; +#endif IVAS_DEC_VOIP *hVoIP; uint32_t extBufferedTime_ms, scale, maxScaling; uint16_t nTimeScalerOutSamples; JB4_DATAUNIT_HANDLE dataUnit; uint16_t bit_stream[MAX_BITS_PER_FRAME + 4 * 8]; int16_t nOutSamplesElse; +#ifndef MC_JBM uint16_t soundCardFrameSize; +#endif uint16_t extBufferedSamples; int16_t timeScalingDone; int16_t result; ivas_error error; + +#ifdef MC_JBM + /* scratch buffer */ + int16_t apaExecBuffer[APA_BUF]; +#endif error = IVAS_ERR_OK; st_ivas = hIvasDec->st_ivas; hDecoderConfig = st_ivas->hDecoderConfig; - st = st_ivas->hSCE[0]->hCoreCoder[0]; hVoIP = hIvasDec->hVoIP; +#ifndef MC_JBM + st = st_ivas->hSCE[0]->hCoreCoder[0]; soundCardFrameSize = hVoIP->nSamplesFrame; +#endif timeScalingDone = 0; +#ifdef MC_JBM + /* TODO(mcjbm): ringbuffer capacity should be configurable by user */ + if( nSamplesPerChannel > hVoIP->hFifoAfterTimeScaler->capacity || nSamplesPerChannel == 0 ) + { + return IVAS_ERR_WRONG_PARAMS; + } +#else assert( hVoIP->nSamplesFrame <= pcmBufSize ); assert( hVoIP->nSamplesFrame <= APA_BUF ); st_ivas->hSCE[0]->hCoreCoder[0]->bit_stream = bit_stream; +#endif /* make sure that the FIFO after decoder/scaler contains at least one sound card frame (i.e. 20ms) */ +#ifdef MC_JBM + while ( pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoAfterTimeScaler ) < nSamplesPerChannel ) +#else while ( pcmdsp_fifo_nReadableSamples( hVoIP->hFifoAfterTimeScaler ) < soundCardFrameSize ) +#endif { +#ifdef MC_JBM + extBufferedSamples = pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoAfterTimeScaler ); +#else extBufferedSamples = pcmdsp_fifo_nReadableSamples( hVoIP->hFifoAfterTimeScaler ); +#endif extBufferedTime_ms = extBufferedSamples * 1000 / hDecoderConfig->output_Fs; dataUnit = NULL; /* pop one access unit from the jitter buffer */ @@ -1300,6 +1434,12 @@ ivas_error IVAS_DEC_VoIP_GetSamples( /* copy bitstream into decoder state */ if ( dataUnit ) { +#ifdef MC_JBM + hIvasDec->hCurrentDataUnit = dataUnit; + + bsCompactToSerial( dataUnit->data, bit_stream, dataUnit->dataSize ); + IVAS_DEC_FeedFrame_Serial( hIvasDec, bit_stream, dataUnit->dataSize, 0 ); +#else if ( st->codec_mode != 0 ) { read_indices_from_djb( st, dataUnit->data, &hIvasDec->CNG, dataUnit->dataSize, @@ -1323,29 +1463,50 @@ ivas_error IVAS_DEC_VoIP_GetSamples( dataUnit->isAMRWB_IOmode, dataUnit->frameTypeIndex, dataUnit->qBit, hIvasDec->bitstreamformat, hIvasDec->amrwb_rfc4867_flag, 0, 0 ); } +#endif } +#ifdef MC_JBM + else if ( hIvasDec->hasDecodedFirstGoodFrame ) + { + /* Decoder has been initialized with first good frame - do PLC */ + IVAS_DEC_FeedFrame_Serial( hIvasDec, bit_stream, 0, 1 ); +#else else if ( st->codec_mode != 0 ) { read_indices_from_djb( st, NULL, &hIvasDec->CNG, 0, 0, 0, 0, hIvasDec->bitstreamformat, 0, 0, 0 ); +#endif } /* decode */ +#ifdef MC_JBM + if ( !hIvasDec->hasBeenFedFirstGoodFrame ) + { + /* codec mode to use not known yet - simply output silence */ + set_s( apaExecBuffer, 0, hVoIP->nSamplesFrame ); /* TODO(sgi): Could be optimized: just write directly to output buffer */ +#else if ( st->codec_mode == 0 ) { /* codec mode to use not known yet */ set_s( pcmBuf, 0, hVoIP->nSamplesFrame ); +#endif } else { +#ifndef MC_JBM if ( hIvasDec->mode == IVAS_DEC_MODE_EVS ) { /* Update total bitrate after reading indices */ hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = st->total_brate; } +#endif +#ifdef MC_JBM + if ( ( error = IVAS_DEC_GetSamples( hIvasDec, apaExecBuffer, &nOutSamplesElse ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_DEC_GetSamples( hIvasDec, pcmBuf, &nOutSamplesElse ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1380,16 +1541,26 @@ ivas_error IVAS_DEC_VoIP_GetSamples( { return IVAS_ERR_UNKNOWN; } +#ifdef MC_JBM + result = apa_exec( hVoIP->hTimeScaler, apaExecBuffer, hVoIP->nSamplesFrame, (uint16_t) maxScaling, apaExecBuffer, &nTimeScalerOutSamples ); +#else result = apa_exec( hVoIP->hTimeScaler, pcmBuf, (uint16_t) ( hVoIP->nSamplesFrame * hDecoderConfig->nchan_out ), (uint16_t) maxScaling, pcmBuf, &nTimeScalerOutSamples ); +#endif if ( result != 0 ) { return IVAS_ERR_UNKNOWN; } +#ifndef MC_JBM assert( nTimeScalerOutSamples <= pcmBufSize ); +#endif assert( nTimeScalerOutSamples <= APA_BUF ); /* append scaled samples to FIFO */ + #ifdef MC_JBM + if ( pcmdsp_fifo_write( hVoIP->hFifoAfterTimeScaler, (uint8_t *) apaExecBuffer, (uint16_t) ( nTimeScalerOutSamples / hDecoderConfig->nchan_out ) ) != 0 ) + #else if ( pcmdsp_fifo_write( hVoIP->hFifoAfterTimeScaler, (uint8_t *) pcmBuf, (uint16_t) ( nTimeScalerOutSamples / hDecoderConfig->nchan_out ) ) != 0 ) + #endif { return IVAS_ERR_UNKNOWN; } @@ -1400,9 +1571,14 @@ ivas_error IVAS_DEC_VoIP_GetSamples( #endif } +#ifdef MC_JBM + /* fetch a user-specified number of samples from FIFO */ + if ( pcmdsp_fifo_read( hVoIP->hFifoAfterTimeScaler, nSamplesPerChannel, (uint8_t *) pcmBuf ) != 0 ) +#else /* fetch one frame for the sound card from FIFO */ *nOutSamples = (int16_t) soundCardFrameSize; if ( pcmdsp_fifo_read( hVoIP->hFifoAfterTimeScaler, *nOutSamples, (uint8_t *) pcmBuf ) != 0 ) +#endif { return IVAS_ERR_UNKNOWN; } @@ -1798,7 +1974,6 @@ static ivas_error printConfigInfo_dec( return IVAS_ERR_OK; } - /*---------------------------------------------------------------------* * IVAS_DEC_PrintConfig( ) * @@ -1840,6 +2015,35 @@ void IVAS_DEC_PrintConfigWithBitstream( return; } + +#ifdef MC_JBM +void IVAS_DEC_PrintConfigWithVoipBitstream( + IVAS_DEC_HANDLE hIvasDec, + const bool quietModeEnabled, + uint8_t *au, + const uint16_t auSizeBits +) +{ + Decoder_Struct *st_ivas; + uint16_t bit_stream[MAX_BITS_PER_FRAME + 4 * 8]; + + /* Create a copy of decoder struct that will be modified by preview_indices(), + * leaving the original decoder struct unchanged. The additional memory used here + * should not be counted towards memory footprint of the decoder. */ + st_ivas = dynamic_malloc( sizeof( Decoder_Struct ) ); + memcpy( st_ivas, hIvasDec->st_ivas, sizeof( Decoder_Struct ) ); + + bsCompactToSerial( au, bit_stream, auSizeBits ); + preview_indices( st_ivas, bit_stream, auSizeBits ); + + /* Print config from modified decoder struct */ + printConfigInfo_dec( st_ivas, hIvasDec->bitstreamformat, hIvasDec->Opt_VOIP, quietModeEnabled ); + + dynamic_free( st_ivas ); + + return; +} +#endif #endif diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index f43034c885..3b3c5620bc 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -145,14 +145,14 @@ ivas_error IVAS_DEC_FeedFrame_Serial( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ uint16_t *serial, /* i : buffer containing serial input bitstream. Each bit should be stored as a single uint16_t value */ const uint16_t num_bits, /* i : number of bits in input bitstream */ - const int16_t bfi /* i : bad frame indicator flag */ + int16_t bfi /* i : bad frame indicator flag */ ); /*! r: decoder error code */ ivas_error IVAS_DEC_GetSamples( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ 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 */ - int16_t *nOutSamples /* o : number of samples written to output buffer */ + int16_t *nOutSamples /* o : number of samples per channel written to output buffer */ ); /*! r: error code */ @@ -183,17 +183,24 @@ ivas_error IVAS_DEC_VoIP_FeedFrame( const uint16_t rtpSequenceNumber, /* i : RTP sequence number (16 bits) */ const uint32_t rtpTimeStamp, /* i : RTP timestamp (32 bits) */ const uint32_t rcvTime_ms, /* i : receive time of the RTP packet in milliseconds */ +#ifndef MC_JBM const bool isAMRWB_IOmode, /* i : AMRWB flag */ const uint16_t frameTypeIndex, /* i : core mode for frame */ +#endif const bool qBit /* i : Q bit for AMR-WB IO */ ); /*! r: error code */ ivas_error IVAS_DEC_VoIP_GetSamples( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ +#ifdef MC_JBM + 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 */ +#else int16_t *nOutSamples, /* o : number of samples 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 pcmBufSize, /* i : size of the PCM output buffer */ +#endif const uint32_t systemTimestamp_ms /* i : current system timestamp */ ); @@ -334,7 +341,6 @@ const char *IVAS_DEC_GetErrorMessage( ivas_error error /* i : decoder error code enum */ ); - void IVAS_DEC_PrintConfig( const IVAS_DEC_HANDLE hIvasDec, /* i : IVAS decoder handle */ const bool quietModeEnabled, /* i : quiet mode flag: if true, reduces the amount of config info printed */ @@ -348,6 +354,15 @@ void IVAS_DEC_PrintConfigWithBitstream( uint16_t bit_stream[], /* i : bitstream buffer */ const int16_t num_bits /* i : number of bits in bitstream */ ); + +#ifdef MC_JBM +void IVAS_DEC_PrintConfigWithVoipBitstream( + IVAS_DEC_HANDLE hIvasDec, /* i : IVAS decoder handle */ + const bool quietModeEnabled, /* i : quiet mode flag: if true, reduces the amount of config info printed */ + uint8_t *au, /* i : buffer containing input access unit */ + const uint16_t auSizeBits /* i : size of the access unit in bits */ +); +#endif #endif void IVAS_DEC_PrintDisclaimer( diff --git a/lib_util/evs_rtp_payload.c b/lib_util/evs_rtp_payload.c index 67dcaa6f36..5adb67d1af 100644 --- a/lib_util/evs_rtp_payload.c +++ b/lib_util/evs_rtp_payload.c @@ -141,6 +141,7 @@ static void evsHeaderFullPayload_parseToc( uint8_t toc, bool *isAMRWB_IOmode, bo } } +#ifndef MC_JBM bool evsPayload_getFrameTypeFromSize( int16_t frameSizeBits, bool *isAMRWB_IOmode, uint16_t *frameTypeIndex ) { int16_t i; @@ -171,6 +172,7 @@ bool evsPayload_getFrameTypeFromSize( int16_t frameSizeBits, bool *isAMRWB_IOmod } return false; } +#endif bool evsHeaderFullPayload_unpackFrame( char *payload, uint16_t payloadSizeBytes, uint16_t frameIndex, bool *isAMRWB_IOmode, bool *frameFollowing, uint16_t *frameTypeIndex, bool *qBit, unsigned char **frame, uint16_t *frameSizeInBits ) { diff --git a/lib_util/evs_rtp_payload.h b/lib_util/evs_rtp_payload.h index 55073a7fa5..a39811c1f2 100644 --- a/lib_util/evs_rtp_payload.h +++ b/lib_util/evs_rtp_payload.h @@ -160,7 +160,9 @@ extern "C" bool evsPayload_unpackFrame( bool hf_only, char *payload, uint16_t payloadSizeBytes, uint16_t frameIndex, bool *isAMRWB_IOmode, bool *frameFollowing, uint16_t *frameTypeIndex, bool *qBit, unsigned char **framePtr, uint16_t *frameSizeBits ); +#ifndef MC_JBM bool evsPayload_getFrameTypeFromSize( int16_t frameSizeBits, bool *isAMRWB_IOmode, uint16_t *frameTypeIndex ); +#endif bool evsHeaderFullPayload_unpackFrame( char *payload, uint16_t payloadSizeBytes, uint16_t frameIndex, bool *isAMRWB_IOmode, bool *frameFollowing, uint16_t *frameTypeIndex, bool *qBit, unsigned char **frame, uint16_t *frameSizeBits ); -- GitLab From 2c319898d818728fa4ded325d5a7614710821071 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Thu, 24 Nov 2022 13:22:56 +0100 Subject: [PATCH 02/37] Fix formatting --- apps/decoder.c | 10 +++++----- lib_com/bitstream.c | 10 +++++----- lib_dec/jbm_pcmdsp_apa.h | 2 +- lib_dec/jbm_pcmdsp_fifo.h | 2 +- lib_dec/lib_dec.c | 33 ++++++++++++++++----------------- 5 files changed, 28 insertions(+), 29 deletions(-) diff --git a/apps/decoder.c b/apps/decoder.c index e5f50cec20..f8eb9a6a3e 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -344,7 +344,7 @@ int main( if ( arg.voipMode ) { #ifdef MC_JBM - if ( ( error = printBitstreamInfoVoip(arg, hBsReader, hIvasDec) ) != IVAS_ERR_OK ) + if ( ( error = printBitstreamInfoVoip( arg, hBsReader, hIvasDec ) ) != IVAS_ERR_OK ) { fprintf( stderr, "Error while previewing VoIP bitstream: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -431,7 +431,7 @@ int main( fprintf( stdout, "FEC: %.2f %%\n", arg.FER ); } } -#else /* DEBUGGING */ +#else /* DEBUGGING */ IVAS_DEC_PrintConfig( hIvasDec, 1, arg.voipMode ); #endif /* DEBUGGING */ @@ -1149,7 +1149,7 @@ static ivas_error initOnFirstGoodFrame( const uint16_t numOutSamples, /* i : */ int16_t *pFullDelayNumSamples, /* o : */ int16_t *pRemainingDelayNumSamples, /* o : */ - int32_t *delayTimeScale, /* o : */ + int32_t *delayTimeScale, /* o : */ IVAS_DEC_BS_FORMAT *pBsFormat, /* i/o: */ AudioFileWriter **ppAfWriter, /* o : */ MasaFileWriter **ppMasaWriter, /* o : */ @@ -1837,9 +1837,9 @@ static ivas_error printBitstreamInfoVoip( goto cleanup; } #ifdef REMOVE_SID_HARM_LEFTOVERS - } while (!qBit || auSizeBits < MIN_NUM_BITS_ACTIVE_FRAME || auSizeBits == NUM_BITS_SID_IVAS_5K2 ); + } while ( !qBit || auSizeBits < MIN_NUM_BITS_ACTIVE_FRAME || auSizeBits == NUM_BITS_SID_IVAS_5K2 ); #else - } while (!qBit || auSizeBits < MIN_NUM_BITS_ACTIVE_FRAME || auSizeBits == NUM_BITS_SID_IVAS_4K4 || auSizeBits == NUM_BITS_SID_IVAS_7K8 || auSizeBits == NUM_BITS_SID_IVAS_9K3 || auSizeBits == NUM_BITS_SID_IVAS_10K2 ); + } while ( !qBit || auSizeBits < MIN_NUM_BITS_ACTIVE_FRAME || auSizeBits == NUM_BITS_SID_IVAS_4K4 || auSizeBits == NUM_BITS_SID_IVAS_7K8 || auSizeBits == NUM_BITS_SID_IVAS_9K3 || auSizeBits == NUM_BITS_SID_IVAS_10K2 ); #endif BS_Reader_Rewind( hBsReader ); diff --git a/lib_com/bitstream.c b/lib_com/bitstream.c index 871981bb18..8b6516f603 100644 --- a/lib_com/bitstream.c +++ b/lib_com/bitstream.c @@ -2189,12 +2189,12 @@ ivas_error read_indices( } /* handle bad/lost speech frame(and CS bad SID frame) in the decoders CNG synthesis settings pair (total_brate, bfi) */ - if ( ( + if ( ( #ifdef MC_JBM - bfi != FRAMEMODE_FUTURE && /* TODO(mcjbm): This fixes channel-aware mode BE. Still requires review from a bitstream reading expert */ + bfi != FRAMEMODE_FUTURE && /* TODO(mcjbm): This fixes channel-aware mode BE. Still requires review from a bitstream reading expert */ #endif - ( *CNG != 0 ) && ( ( speech_bad != 0 ) || ( speech_lost != 0 ) ) ) || /* SP_BAD or SPEECH_LOST) --> stay in CNG */ - ( sid_upd_bad != 0 ) ) /* SID_UPD_BAD --> start CNG */ + ( *CNG != 0 ) && ( ( speech_bad != 0 ) || ( speech_lost != 0 ) ) ) || /* SP_BAD or SPEECH_LOST) --> stay in CNG */ + ( sid_upd_bad != 0 ) ) /* SID_UPD_BAD --> start CNG */ { st_ivas->bfi = 0; /* bfi=0 needed to activate CNG code */ total_brate = FRAME_NO_DATA; @@ -2238,7 +2238,7 @@ ivas_error read_indices( /* GOOD frame */ if ( st_ivas->bfi == 0 #ifdef MC_JBM - || st_ivas->bfi == FRAMEMODE_FUTURE /* TODO(mcjbm): This fixes channel-aware mode BE. Still requires review from a bitstream reading expert */ + || st_ivas->bfi == FRAMEMODE_FUTURE /* TODO(mcjbm): This fixes channel-aware mode BE. Still requires review from a bitstream reading expert */ #endif ) { diff --git a/lib_dec/jbm_pcmdsp_apa.h b/lib_dec/jbm_pcmdsp_apa.h index e3628489ad..aa8c931f5c 100644 --- a/lib_dec/jbm_pcmdsp_apa.h +++ b/lib_dec/jbm_pcmdsp_apa.h @@ -55,7 +55,7 @@ #define APA_MAX_NUM_CHANNELS 16 #define APA_BUF ( APA_BUF_PER_CHANNEL * APA_MAX_NUM_CHANNELS ) #else - #define APA_BUF 4096 * 3 +#define APA_BUF 4096 * 3 #endif /* min/max sampling rate [Hz] */ diff --git a/lib_dec/jbm_pcmdsp_fifo.h b/lib_dec/jbm_pcmdsp_fifo.h index 0265f745a8..85312ace99 100644 --- a/lib_dec/jbm_pcmdsp_fifo.h +++ b/lib_dec/jbm_pcmdsp_fifo.h @@ -81,7 +81,7 @@ int16_t pcmdsp_fifo_write( PCMDSP_FIFO_HANDLE h, const uint8_t *samples, uint16_ int16_t pcmdsp_fifo_read( PCMDSP_FIFO_HANDLE h, uint16_t nSamplesPerChannel, uint8_t *samples ); #ifdef MC_JBM -uint16_t pcmdsp_fifo_nReadableSamplesPerChannel(const PCMDSP_FIFO_HANDLE h ); +uint16_t pcmdsp_fifo_nReadableSamplesPerChannel( const PCMDSP_FIFO_HANDLE h ); #else uint16_t pcmdsp_fifo_nReadableSamples( const PCMDSP_FIFO_HANDLE h ); #endif diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 0c0588b5aa..98862e6b43 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -1336,14 +1336,14 @@ ivas_error IVAS_DEC_VoIP_FeedFrame( *---------------------------------------------------------------------*/ ivas_error IVAS_DEC_VoIP_GetSamples( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ #ifdef MC_JBM - 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 */ + 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 */ #else - int16_t *nOutSamples, /* o : number of samples 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 pcmBufSize, /* i : size of the PCM output buffer */ + int16_t *nOutSamples, /* o : number of samples 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 pcmBufSize, /* i : size of the PCM output buffer */ #endif const uint32_t systemTimestamp_ms /* i : current system timestamp */ ) @@ -1366,7 +1366,7 @@ ivas_error IVAS_DEC_VoIP_GetSamples( int16_t timeScalingDone; int16_t result; ivas_error error; - + #ifdef MC_JBM /* scratch buffer */ int16_t apaExecBuffer[APA_BUF]; @@ -1385,7 +1385,7 @@ ivas_error IVAS_DEC_VoIP_GetSamples( #ifdef MC_JBM /* TODO(mcjbm): ringbuffer capacity should be configurable by user */ - if( nSamplesPerChannel > hVoIP->hFifoAfterTimeScaler->capacity || nSamplesPerChannel == 0 ) + if ( nSamplesPerChannel > hVoIP->hFifoAfterTimeScaler->capacity || nSamplesPerChannel == 0 ) { return IVAS_ERR_WRONG_PARAMS; } @@ -1555,12 +1555,12 @@ ivas_error IVAS_DEC_VoIP_GetSamples( #endif assert( nTimeScalerOutSamples <= APA_BUF ); - /* append scaled samples to FIFO */ - #ifdef MC_JBM +/* append scaled samples to FIFO */ +#ifdef MC_JBM if ( pcmdsp_fifo_write( hVoIP->hFifoAfterTimeScaler, (uint8_t *) apaExecBuffer, (uint16_t) ( nTimeScalerOutSamples / hDecoderConfig->nchan_out ) ) != 0 ) - #else +#else if ( pcmdsp_fifo_write( hVoIP->hFifoAfterTimeScaler, (uint8_t *) pcmBuf, (uint16_t) ( nTimeScalerOutSamples / hDecoderConfig->nchan_out ) ) != 0 ) - #endif +#endif { return IVAS_ERR_UNKNOWN; } @@ -2018,11 +2018,10 @@ void IVAS_DEC_PrintConfigWithBitstream( #ifdef MC_JBM void IVAS_DEC_PrintConfigWithVoipBitstream( - IVAS_DEC_HANDLE hIvasDec, - const bool quietModeEnabled, - uint8_t *au, - const uint16_t auSizeBits -) + IVAS_DEC_HANDLE hIvasDec, + const bool quietModeEnabled, + uint8_t *au, + const uint16_t auSizeBits ) { Decoder_Struct *st_ivas; uint16_t bit_stream[MAX_BITS_PER_FRAME + 4 * 8]; -- GitLab From 0daa897a894fcba963df274bcb0b5fce1b12d963 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Mon, 28 Nov 2022 12:05:37 +0100 Subject: [PATCH 03/37] Fix conversion warning --- apps/decoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/decoder.c b/apps/decoder.c index f8eb9a6a3e..2f16b67df4 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -2108,7 +2108,7 @@ static ivas_error decodeVoIP( } #ifdef MC_JBM - nOutSamples = arg.output_Fs / 50; + nOutSamples = (int16_t) ( arg.output_Fs / 50 ); /* decode and get samples */ if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, pcmBuf, systemTime_ms ) ) != IVAS_ERR_OK ) -- GitLab From aec722f9437ea68cf89439f22827fd98cf4c0f3c Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Mon, 28 Nov 2022 12:18:41 +0100 Subject: [PATCH 04/37] Wrap unused function in MC_JBM switch --- lib_com/bitstream.c | 2 ++ lib_com/prot.h | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib_com/bitstream.c b/lib_com/bitstream.c index 8b6516f603..0394887d94 100644 --- a/lib_com/bitstream.c +++ b/lib_com/bitstream.c @@ -2743,6 +2743,7 @@ void get_NextCoderType( return; } +#ifndef MC_JBM /*-------------------------------------------------------------------* * read_indices_from_djb() * @@ -2853,6 +2854,7 @@ void read_indices_from_djb( return; } +#endif /*-------------------------------------------------------------------* * get_indice_preview() diff --git a/lib_com/prot.h b/lib_com/prot.h index 2d6527fe59..61e16ac36e 100755 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -665,7 +665,7 @@ void evs_dec_previewFrame( int16_t *partialCopyOffset /* o : offset of the partial copy relative to the primary copy */ ); - +#ifndef MC_JBM void read_indices_from_djb( Decoder_State *st, /* i/o: decoder state structure */ uint8_t *pt_stream, /* i : bitstream file */ @@ -679,6 +679,7 @@ void read_indices_from_djb( const int16_t partialframe, /* i : partial frame information */ const int16_t next_coder_type /* i : next coder type information */ ); +#endif void getPartialCopyInfo( Decoder_State *st, /* i : decoder state structure */ -- GitLab From 4c8fb73d20f02dd62e0ed28d77df4f7e802d0257 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Wed, 7 Dec 2022 15:48:21 +0100 Subject: [PATCH 05/37] Update MC JBM contribution Includes following changes: - reduce decoder memory usage in VoIP mode - update JBM tracefile writing - add VoIP conditions to self_test.prm - add script for ensuring BE between decoder in VoIP and non-VoIP mode (not yet used in CI) - fix bug in IvasModeRunner.py when running decoder in VoIP mode --- apps/decoder.c | 15 +- ci/jbm_be_test.sh | 105 +++++++++++++ lib_com/common_api_types.h | 13 ++ lib_dec/jbm_pcmdsp_apa.c | 47 +++++- lib_dec/jbm_pcmdsp_apa.h | 14 +- lib_dec/lib_dec.c | 141 +++++++++++++----- lib_dec/lib_dec.h | 10 ++ lib_util/jbm_file_writer.c | 33 +++- scripts/config/self_test.prm | 21 +++ .../dly_error_profile_0.dat | 3 + scripts/pyaudio3dtools/audiofile.py | 43 ++++++ scripts/pyivastest/IvasModeRunner.py | 4 +- 12 files changed, 396 insertions(+), 53 deletions(-) create mode 100755 ci/jbm_be_test.sh create mode 100644 scripts/dly_error_profiles/dly_error_profile_0.dat diff --git a/apps/decoder.c b/apps/decoder.c index 2f16b67df4..c6fc6e4ae1 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -1897,8 +1897,7 @@ static ivas_error decodeVoIP( MasaFileWriter *masaWriter = NULL; uint16_t numObj = 0; - const uint32_t pcmBufSizeWithSampleBasedTimeScaling = 3 * MAX_OUTPUT_PCM_BUFFER_SIZE; - int16_t pcmBuf[3 * MAX_OUTPUT_PCM_BUFFER_SIZE]; + int16_t pcmBuf[MAX_OUTPUT_PCM_BUFFER_SIZE]; #else /* For now always assume output with one channel. When adding VoIP to IVAS, * initialization of the memory for jitter buffer etc. needs to happen after @@ -1936,9 +1935,10 @@ static ivas_error decodeVoIP( { ismWriters[i] = NULL; } +#else + memset( pcmBuf, 0, pcmBufSizeWithSampleBasedTimeScaling ); #endif - memset( pcmBuf, 0, pcmBufSizeWithSampleBasedTimeScaling ); rtpdumpDepacker.rtpdump = NULL; switch ( arg.inputFormat ) @@ -2111,7 +2111,12 @@ static ivas_error decodeVoIP( nOutSamples = (int16_t) ( arg.output_Fs / 50 ); /* decode and get samples */ - if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, pcmBuf, systemTime_ms ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, pcmBuf, systemTime_ms +#ifdef SUPPORT_JBM_TRACEFILE + , + jbmTraceWriter +#endif + ) ) != IVAS_ERR_OK ) #else /* decode and get samples */ if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, &nOutSamples, pcmBuf, pcmBufSizeWithSampleBasedTimeScaling, systemTime_ms ) ) != IVAS_ERR_OK ) @@ -2121,6 +2126,7 @@ static ivas_error decodeVoIP( goto cleanup; } +#ifndef MC_JBM #ifdef SUPPORT_JBM_TRACEFILE /* write JBM trace file entry - only done for EVS testing */ if ( jbmTraceWriter != NULL ) @@ -2139,6 +2145,7 @@ static ivas_error decodeVoIP( goto cleanup; } } +#endif #endif /* write JBM Offset file entry */ diff --git a/ci/jbm_be_test.sh b/ci/jbm_be_test.sh new file mode 100755 index 0000000000..38253a205f --- /dev/null +++ b/ci/jbm_be_test.sh @@ -0,0 +1,105 @@ +#! /usr/local/bin/bash + +# (C) 2022 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. + +# Configuration +modes=('SBA_b128_wb_cbr' 'MC_7_1_b96_fb_cbr' 'ISM2_b48_fb_cbr') # 'stereo_b32_128_fb_rs') # stereo mode sems broken in decoder +output_formats=('STEREO' 'FOA' '7_1' 'HOA3') +limit_input_to_x_seconds=30 + +network_profile_path="scripts/dly_error_profiles/dly_error_profile_0.dat" + +output_dir_default="out" +output_dir_voip="out_voip" + +# Build IVAS +make clean +make all -j 8 + +# Run the same modes in VoIP and non-VoIP mode with a neutral delay profile +./scripts/runIvasCodec.py -p ./scripts/config/ci_linux.json -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_default | tee jbm_be_test_output.txt +./scripts/runIvasCodec.py -p ./scripts/config/ci_linux.json -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_voip -J "$network_profile_path" | tee -a jbm_be_test_output.txt + +# Set up Python path +python_audio_module_path=$(pwd)/scripts +export PYTHONPATH=$python_audio_module_path:$PYTHONPATH +python_audiofile_script_path=$python_audio_module_path/pyaudio3dtools/audiofile.py + +# Trim JBM delay from VoIP output files +output_dir_voip_dec="$output_dir_voip"/dec +output_dir_voip_dec_trimmed="$output_dir_voip"/dec_trimmed + +if [[ ! -d $output_dir_voip_dec_trimmed ]]; then + mkdir $output_dir_voip_dec_trimmed +fi + +for cut in "$output_dir_voip_dec"/*.wav; do + output_path=${cut/$output_dir_voip_dec/$output_dir_voip_dec_trimmed} + output_path=${output_path/".wav"/".raw"} + python3 "$python_audiofile_script_path" pre-trim 60 "$cut" "$output_path" | tee -a jbm_be_test_output.txt +done + +# Convert non-VoIP output from wav to pcm (comparison script doesn't support wav) +output_dir_default_dec="$output_dir_default"/dec +output_dir_default_dec_pcm="$output_dir_default"/dec_pcm + +if [[ ! -d $output_dir_default_dec_pcm ]]; then + mkdir $output_dir_default_dec_pcm +fi + +for ref in "$output_dir_default_dec"/*.wav; do + output_path=${ref/$output_dir_default_dec/$output_dir_default_dec_pcm} + output_path=${output_path/".wav"/".raw"} + python3 "$python_audiofile_script_path" convert "$ref" "$output_path" | tee -a jbm_be_test_output.txt +done + +# Assert BE between non-VoIP and VoIP modes +all_be=1 + +cmp_custom_path=$(pwd)/tests/cmp_custom.py + +for ref in "$output_dir_default_dec_pcm"/*; do + cut=${ref/$output_dir_default_dec_pcm/$output_dir_voip_dec_trimmed} + cut=${cut/".dec."/"_jbm_dly_error_profile_0_dat.dec."} + + # Print paths of compared files, since the script doesn't do it + printf "\nComparing %s and %s\n" "$ref" "$cut" | tee -a jbm_be_test_output.txt + printout=$($cmp_custom_path "$ref" "$cut" 2 0) + if [ $? -ne 0 ]; then + all_be=0 + fi + printf "%s\n" "$printout" | tee -a jbm_be_test_output.txt +done + +if [ $all_be -eq 1 ]; then + printf "\n\nAll tested conditions are bit-exact\n" | tee -a jbm_be_test_output.txt +else + printf "\n\nBitexactness problems found!\n" | tee -a jbm_be_test_output.txt + exit 255; +fi diff --git a/lib_com/common_api_types.h b/lib_com/common_api_types.h index 0fd3e7c552..1b9d60637a 100644 --- a/lib_com/common_api_types.h +++ b/lib_com/common_api_types.h @@ -140,15 +140,28 @@ typedef struct ivas_LS_setup_custom IVAS_LSSETUP_CUSTOM_STRUCT; typedef struct _IVAS_JBM_TRACE_DATA { +#ifdef MC_JBM + uint32_t systemTimestamp_ms; + uint16_t extBufferedSamples; + uint16_t lastDecodedWasActive; + int32_t output_Fs; + int16_t dataUnit_flag; +#else double playTime; int16_t partialCopyOffset; +#endif uint16_t sequenceNumber; uint32_t timeStamp; uint32_t rcvTime; +#ifdef MC_JBM + int16_t partial_frame; + int16_t partialCopyOffset; +#else int16_t lastDecodedWasActive; int16_t partial_frame_flag; int16_t dataUnit_flag; +#endif } IVAS_JBM_TRACE_DATA; diff --git a/lib_dec/jbm_pcmdsp_apa.c b/lib_dec/jbm_pcmdsp_apa.c index 9057f103a5..a1da5b6b66 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 MC_JBM + int16_t *buf_out; + uint16_t buf_out_capacity; +#else int16_t buf_out[APA_BUF]; +#endif uint16_t l_buf_out; /* Hann window */ @@ -143,7 +148,11 @@ static bool extend_frm( apa_state_t *ps, const int16_t frm_in[], int16_t frm_out /* Allocates memory for state struct and initializes elements. */ uint8_t apa_init( - apa_state_t **pps ) + apa_state_t **pps +#ifdef MC_JBM + ,int32_t num_channels +#endif +) { apa_state_t *ps = NULL; @@ -159,6 +168,15 @@ uint8_t apa_init( { return 2; } +#ifdef MC_JBM + ps->num_channels = num_channels; + ps->buf_out_capacity = APA_BUF_PER_CHANNEL * num_channels; + ps->buf_out = count_malloc( sizeof( float ) * ps->buf_out_capacity ); + if ( !ps->buf_out ) + { + return 2; + } +#endif apa_reset( ps ); *pps = ps; @@ -190,7 +208,9 @@ void apa_reset( ps->last_pitch = 0; ps->bad_frame_count = 0; ps->good_frame_count = 0; +#ifndef MC_JBM ps->num_channels = 0; +#endif return; } @@ -199,8 +219,11 @@ void apa_reset( /* Sets the audio configuration. */ bool apa_set_rate( apa_state_t *ps, - const int32_t output_Fs, - const int16_t num_channels ) + const int32_t output_Fs +#ifndef MC_JBM + ,const int16_t num_channels +#endif + ) { /* make sure pointer is valid */ if ( ps == NULL ) @@ -222,12 +245,11 @@ bool apa_set_rate( /* set number of channels */ #ifdef MC_JBM - if ( num_channels > APA_MAX_NUM_CHANNELS ) + if ( ps->num_channels > APA_MAX_NUM_CHANNELS ) { return 1; } #endif - ps->num_channels = num_channels; /* * several other parameters depend on the sampling rate @@ -415,6 +437,11 @@ bool apa_exit( return 0; } +#ifdef MC_JBM + /* deallocate state struct members */ + count_free( (*pps)->buf_out ); +#endif + /* deallocate state struct */ count_free( *pps ); @@ -466,7 +493,7 @@ uint8_t apa_exec( ) { uint16_t i; - int16_t frm_in[APA_BUF]; + int16_t frm_in[APA_BUF]; /* TODO(mcjbm): this buffer could be smaller - always allocates space for 16 channels */ uint16_t l_frm_out; int16_t l_rem; int32_t dl_scaled, dl_copied, l_frm_out_target; @@ -584,7 +611,11 @@ uint8_t apa_exec( /* copy output to internal buffer */ /* avoid buffer overflow: */ /* discard old samples; always keep at least most recent l_frm samples */ +#ifdef MC_JBM + if ( ( ps->l_buf_out + l_frm_out ) > ps->buf_out_capacity ) +#else if ( ( ps->l_buf_out + l_frm_out ) > APA_BUF ) +#endif { int16_t *buf_out_ptr1 = ps->buf_out; int16_t *buf_out_ptr2; @@ -602,7 +633,11 @@ uint8_t apa_exec( ps->l_buf_out = l_rem; } /* append new output samples */ +#ifdef MC_JBM + if ( ( ps->l_buf_out + l_frm_out ) > ps->buf_out_capacity ) +#else if ( ( ps->l_buf_out + l_frm_out ) > APA_BUF ) +#endif { return 5; } diff --git a/lib_dec/jbm_pcmdsp_apa.h b/lib_dec/jbm_pcmdsp_apa.h index aa8c931f5c..ab2cbdcb30 100644 --- a/lib_dec/jbm_pcmdsp_apa.h +++ b/lib_dec/jbm_pcmdsp_apa.h @@ -95,7 +95,12 @@ typedef struct apa_state_t *PCMDSP_APA_HANDLE; /*! Allocates memory for state struct and initializes elements. * @return 0 on success, 1 on failure */ -uint8_t apa_init( apa_state_t **s ); +uint8_t apa_init( apa_state_t **s +#ifdef MC_JBM + , + int32_t num_channels +#endif +); /*! Sets state variables to initial value. */ void apa_reset( apa_state_t *s ); @@ -109,7 +114,12 @@ void apa_reset( apa_state_t *s ); * @param[in] output_Fs sample rate [Hz] * @param[in] num_channels number of channels * @return 0 on success, 1 on failure */ -bool apa_set_rate( apa_state_t *ps, const int32_t output_Fs, const int16_t num_channels ); +bool apa_set_rate( apa_state_t *ps, const int32_t output_Fs +#ifndef MC_JBM + , + const int16_t num_channels +#endif +); /*! Set scaling. * The scale is given in % and will be valid until changed again. diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 98862e6b43..fc450d27a4 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -55,6 +55,11 @@ struct IVAS_DEC_VOIP PCMDSP_APA_HANDLE hTimeScaler; PCMDSP_FIFO_HANDLE hFifoAfterTimeScaler; uint16_t lastDecodedWasActive; +#ifdef MC_JBM + int16_t *apaExecBuffer; /* Buffer for APA scaling */ + JB4_DATAUNIT_HANDLE hCurrentDataUnit; /* Points to the currently processed data unit */ + uint16_t *bs_conversion_buf; /* Buffer for bitstream conversion from packed to serial */ +#endif #ifdef SUPPORT_JBM_TRACEFILE IVAS_JBM_TRACE_DATA JbmTraceData; #endif @@ -78,10 +83,6 @@ struct IVAS_DEC int16_t sdp_hf_only; /* RTP payload format parameter: only Header-Full format without zero padding for size collision avoidance */ int16_t prev_ft_speech; /* RXDTX handler: previous frametype flag for G.192 format AMRWB SID_FIRST detection */ int16_t CNG; /* RXDTX handler: CNG=1, nonCNG=0 */ - -#ifdef MC_JBM - JB4_DATAUNIT_HANDLE hCurrentDataUnit; -#endif }; @@ -132,9 +133,6 @@ ivas_error IVAS_DEC_Open( hIvasDec->hasBeenFedFirstGoodFrame = false; hIvasDec->hasDecodedFirstGoodFrame = false; hIvasDec->isInitialized = false; -#ifdef MC_JBM - hIvasDec->hCurrentDataUnit = NULL; -#endif hIvasDec->mode = mode; @@ -521,19 +519,33 @@ ivas_error IVAS_DEC_EnableVoIP( return error; } hIvasDec->hVoIP = count_malloc( sizeof( IVAS_DEC_VOIP ) ); + if ( hIvasDec->hVoIP == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate VoIP handle" ); + } + hIvasDec->hVoIP->lastDecodedWasActive = 0; #ifdef MC_JBM + hIvasDec->hVoIP->hCurrentDataUnit = NULL; hIvasDec->hVoIP->nSamplesFrame = (uint16_t) ( hDecoderConfig->output_Fs * hDecoderConfig->nchan_out / FRAMES_PER_SEC ); #else hIvasDec->hVoIP->nSamplesFrame = (uint16_t) ( hDecoderConfig->output_Fs / FRAMES_PER_SEC ); #endif - /* Copy updated configuration to core coder */ - - if ( hIvasDec->hVoIP == NULL ) +#ifdef MC_JBM + hIvasDec->hVoIP->apaExecBuffer = count_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" ); } + /* Bitstream conversion is not counted towards complexity and memory usage */ + hIvasDec->hVoIP->bs_conversion_buf = dynamic_malloc( sizeof( uint16_t ) * MAX_BITS_PER_FRAME + 4 * 8 ); + if ( hIvasDec->hVoIP->bs_conversion_buf == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate VoIP handle" ); + } +#endif + /* initialize JBM */ if ( ( error = JB4_Create( &hIvasDec->hVoIP->hJBM ) != IVAS_ERR_OK ) != IVAS_ERR_OK ) { @@ -569,8 +581,18 @@ ivas_error IVAS_DEC_EnableVoIP( return IVAS_ERR_INIT_ERROR; } - if ( apa_init( &hIvasDec->hVoIP->hTimeScaler ) != 0 || - apa_set_rate( hIvasDec->hVoIP->hTimeScaler, hDecoderConfig->output_Fs, hDecoderConfig->nchan_out ) != 0 || + if ( apa_init( &hIvasDec->hVoIP->hTimeScaler +#ifdef MC_JBM + , + hDecoderConfig->nchan_out +#endif + ) != 0 || + apa_set_rate( hIvasDec->hVoIP->hTimeScaler, hDecoderConfig->output_Fs +#ifndef MC_JBM + , + hDecoderConfig->nchan_out +#endif + ) != 0 || apa_set_complexity_options( hIvasDec->hVoIP->hTimeScaler, wss, css ) != 0 || apa_set_quality( hIvasDec->hVoIP->hTimeScaler, 1, 4, 4 ) != 0 || pcmdsp_fifo_create( &hIvasDec->hVoIP->hFifoAfterTimeScaler ) != 0 || @@ -612,12 +634,12 @@ ivas_error IVAS_DEC_FeedFrame_Serial( } #ifdef MC_JBM - if ( hIvasDec->hCurrentDataUnit != NULL ) + if ( hIvasDec->hVoIP != NULL && hIvasDec->hVoIP->hCurrentDataUnit != NULL ) { DEC_CORE_HANDLE st = hIvasDec->st_ivas->hSCE[0]->hCoreCoder[0]; st->ini_frame = 0; st->prev_use_partial_copy = 0; - hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = hIvasDec->hCurrentDataUnit->dataSize * FRAMES_PER_SEC; + hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = hIvasDec->hVoIP->hCurrentDataUnit->dataSize * FRAMES_PER_SEC; } else { @@ -638,21 +660,21 @@ ivas_error IVAS_DEC_FeedFrame_Serial( #ifdef MC_JBM /* Update redundant frame information in EVS (pre- read indices) */ - if ( hIvasDec->mode == IVAS_DEC_MODE_EVS && hIvasDec->hCurrentDataUnit != NULL ) + if ( hIvasDec->mode == IVAS_DEC_MODE_EVS && hIvasDec->hVoIP != NULL && hIvasDec->hVoIP->hCurrentDataUnit != NULL ) { DEC_CORE_HANDLE st = hIvasDec->st_ivas->hSCE[0]->hCoreCoder[0]; st->bit_stream = serial; - if ( hIvasDec->hCurrentDataUnit->partial_frame || st->prev_use_partial_copy ) + if ( hIvasDec->hVoIP->hCurrentDataUnit->partial_frame || st->prev_use_partial_copy ) { - st->next_coder_type = hIvasDec->hCurrentDataUnit->nextCoderType; + st->next_coder_type = hIvasDec->hVoIP->hCurrentDataUnit->nextCoderType; } else { st->next_coder_type = INACTIVE; } - if ( hIvasDec->hCurrentDataUnit->partial_frame == 1 && bfi != 1 ) + if ( hIvasDec->hVoIP->hCurrentDataUnit->partial_frame == 1 && bfi != 1 ) { bfi = 2; } @@ -664,8 +686,9 @@ ivas_error IVAS_DEC_FeedFrame_Serial( #ifdef MC_JBM /* Update redundant frame information in EVS (post- read indices) */ if ( hIvasDec->mode == IVAS_DEC_MODE_EVS && - hIvasDec->hCurrentDataUnit != NULL && - hIvasDec->hCurrentDataUnit->partial_frame != 0 ) + hIvasDec->hVoIP != NULL && + hIvasDec->hVoIP->hCurrentDataUnit != NULL && + hIvasDec->hVoIP->hCurrentDataUnit->partial_frame != 0 ) { DEC_CORE_HANDLE st = hIvasDec->st_ivas->hSCE[0]->hCoreCoder[0]; st->codec_mode = MODE2; @@ -1217,6 +1240,8 @@ static bool isSidFrame( #ifdef MC_JBM static void bsCompactToSerial( const uint8_t *compact, uint16_t *serial, uint16_t num_bits ) { +/* Bitstream conversion is not counted towards complexity and memory usage */ +#define WMC_TOOL_MAN uint32_t i; uint8_t byte; const uint8_t mask = 0x80; @@ -1232,6 +1257,7 @@ static void bsCompactToSerial( const uint8_t *compact, uint16_t *serial, uint16_ byte <<= 1; } +#undef WMC_TOOL_MAN } #endif @@ -1346,6 +1372,12 @@ ivas_error IVAS_DEC_VoIP_GetSamples( const uint32_t pcmBufSize, /* i : size of the PCM output buffer */ #endif const uint32_t systemTimestamp_ms /* i : current system timestamp */ +#ifdef MC_JBM +#ifdef SUPPORT_JBM_TRACEFILE + , + JbmTraceFileWriter *jbmTraceFileWriter +#endif +#endif ) { Decoder_Struct *st_ivas; @@ -1357,7 +1389,9 @@ ivas_error IVAS_DEC_VoIP_GetSamples( uint32_t extBufferedTime_ms, scale, maxScaling; uint16_t nTimeScalerOutSamples; JB4_DATAUNIT_HANDLE dataUnit; +#ifndef MC_JBM uint16_t bit_stream[MAX_BITS_PER_FRAME + 4 * 8]; +#endif int16_t nOutSamplesElse; #ifndef MC_JBM uint16_t soundCardFrameSize; @@ -1367,11 +1401,6 @@ ivas_error IVAS_DEC_VoIP_GetSamples( int16_t result; ivas_error error; -#ifdef MC_JBM - /* scratch buffer */ - int16_t apaExecBuffer[APA_BUF]; -#endif - error = IVAS_ERR_OK; st_ivas = hIvasDec->st_ivas; @@ -1435,10 +1464,10 @@ ivas_error IVAS_DEC_VoIP_GetSamples( if ( dataUnit ) { #ifdef MC_JBM - hIvasDec->hCurrentDataUnit = dataUnit; + hIvasDec->hVoIP->hCurrentDataUnit = dataUnit; - bsCompactToSerial( dataUnit->data, bit_stream, dataUnit->dataSize ); - IVAS_DEC_FeedFrame_Serial( hIvasDec, bit_stream, dataUnit->dataSize, 0 ); + 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 ( st->codec_mode != 0 ) { @@ -1469,7 +1498,7 @@ ivas_error IVAS_DEC_VoIP_GetSamples( else if ( hIvasDec->hasDecodedFirstGoodFrame ) { /* Decoder has been initialized with first good frame - do PLC */ - IVAS_DEC_FeedFrame_Serial( hIvasDec, bit_stream, 0, 1 ); + IVAS_DEC_FeedFrame_Serial( hIvasDec, hIvasDec->hVoIP->bs_conversion_buf, 0, 1 ); #else else if ( st->codec_mode != 0 ) { @@ -1484,7 +1513,7 @@ ivas_error IVAS_DEC_VoIP_GetSamples( if ( !hIvasDec->hasBeenFedFirstGoodFrame ) { /* codec mode to use not known yet - simply output silence */ - set_s( apaExecBuffer, 0, hVoIP->nSamplesFrame ); /* TODO(sgi): Could be optimized: just write directly to output buffer */ + set_s( hVoIP->apaExecBuffer, 0, hVoIP->nSamplesFrame ); /* TODO(mcjbm): Could be optimized: just write directly to output buffer */ #else if ( st->codec_mode == 0 ) { @@ -1503,7 +1532,7 @@ ivas_error IVAS_DEC_VoIP_GetSamples( #endif #ifdef MC_JBM - if ( ( error = IVAS_DEC_GetSamples( hIvasDec, apaExecBuffer, &nOutSamplesElse ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_GetSamples( hIvasDec, hVoIP->apaExecBuffer, &nOutSamplesElse ) ) != IVAS_ERR_OK ) #else if ( ( error = IVAS_DEC_GetSamples( hIvasDec, pcmBuf, &nOutSamplesElse ) ) != IVAS_ERR_OK ) #endif @@ -1542,7 +1571,7 @@ ivas_error IVAS_DEC_VoIP_GetSamples( return IVAS_ERR_UNKNOWN; } #ifdef MC_JBM - result = apa_exec( hVoIP->hTimeScaler, apaExecBuffer, hVoIP->nSamplesFrame, (uint16_t) maxScaling, apaExecBuffer, &nTimeScalerOutSamples ); + result = apa_exec( hVoIP->hTimeScaler, hVoIP->apaExecBuffer, hVoIP->nSamplesFrame, (uint16_t) maxScaling, hVoIP->apaExecBuffer, &nTimeScalerOutSamples ); #else result = apa_exec( hVoIP->hTimeScaler, pcmBuf, (uint16_t) ( hVoIP->nSamplesFrame * hDecoderConfig->nchan_out ), (uint16_t) maxScaling, pcmBuf, &nTimeScalerOutSamples ); #endif @@ -1557,7 +1586,7 @@ ivas_error IVAS_DEC_VoIP_GetSamples( /* append scaled samples to FIFO */ #ifdef MC_JBM - if ( pcmdsp_fifo_write( hVoIP->hFifoAfterTimeScaler, (uint8_t *) apaExecBuffer, (uint16_t) ( nTimeScalerOutSamples / hDecoderConfig->nchan_out ) ) != 0 ) + if ( pcmdsp_fifo_write( hVoIP->hFifoAfterTimeScaler, (uint8_t *) hVoIP->apaExecBuffer, (uint16_t) ( nTimeScalerOutSamples / hDecoderConfig->nchan_out ) ) != 0 ) #else if ( pcmdsp_fifo_write( hVoIP->hFifoAfterTimeScaler, (uint8_t *) pcmBuf, (uint16_t) ( nTimeScalerOutSamples / hDecoderConfig->nchan_out ) ) != 0 ) #endif @@ -1565,9 +1594,25 @@ ivas_error IVAS_DEC_VoIP_GetSamples( return IVAS_ERR_UNKNOWN; } +#ifdef MC_JBM +#ifdef SUPPORT_JBM_TRACEFILE + /* jbmTraceFileWriter may be NULL if tracefile writing was not requested on CLI */ + if ( jbmTraceFileWriter != NULL ) + { + /* write JBM trace data entry */ + store_JbmData( hVoIP, dataUnit, systemTimestamp_ms, extBufferedSamples, hDecoderConfig->output_Fs ); + if ( ( JbmTraceFileWriter_writeFrame( &hVoIP->JbmTraceData, jbmTraceFileWriter ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing JBM Trace data to file\n" ); + return IVAS_ERR_UNKNOWN; + } + } +#endif +#else #ifdef SUPPORT_JBM_TRACEFILE /* store JBM trace data entry */ store_JbmData( hVoIP, dataUnit, systemTimestamp_ms, extBufferedSamples, hDecoderConfig->output_Fs ); +#endif #endif } @@ -1640,6 +1685,18 @@ static void IVAS_DEC_Close_VoIP( pcmdsp_fifo_destroy( &hVoIP->hFifoAfterTimeScaler ); +#ifdef MC_JBM + if ( hVoIP->apaExecBuffer != NULL ) + { + count_free( hVoIP->apaExecBuffer ); + } + if ( hVoIP->bs_conversion_buf != NULL ) + { + /* Bitstream conversion is not counted towards complexity and memory usage */ + dynamic_free( hVoIP->bs_conversion_buf ); + } +#endif + count_free( hVoIP ); return; @@ -1669,6 +1726,21 @@ static void store_JbmData( JbmTraceData = &hVoIP->JbmTraceData; +#ifdef MC_JBM + JbmTraceData->systemTimestamp_ms = systemTimestamp_ms; + JbmTraceData->extBufferedSamples = extBufferedSamples; + JbmTraceData->lastDecodedWasActive = hVoIP->lastDecodedWasActive; + JbmTraceData->output_Fs = output_Fs; + JbmTraceData->dataUnit_flag = dataUnit != NULL; + if ( dataUnit != NULL ) + { + JbmTraceData->sequenceNumber = dataUnit->sequenceNumber; + JbmTraceData->timeStamp = dataUnit->timeStamp; + JbmTraceData->rcvTime = dataUnit->rcvTime; + JbmTraceData->partial_frame = dataUnit->partial_frame; + JbmTraceData->partialCopyOffset = dataUnit->partialCopyOffset; + } +#else /* the first sample of the decoded/concealed frame will be played after the samples in the ring buffer */ JbmTraceData->playTime = systemTimestamp_ms + extBufferedSamples * 1000.0 / output_Fs; @@ -1695,8 +1767,9 @@ static void store_JbmData( { JbmTraceData->dataUnit_flag = 0; } +#endif - return; + return; } diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index 3b3c5620bc..a594076925 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -35,6 +35,11 @@ #include "common_api_types.h" #include "ivas_error.h" +#ifdef MC_JBM +#ifdef SUPPORT_JBM_TRACEFILE +#include "jbm_file_writer.h" +#endif +#endif #include #include @@ -202,6 +207,11 @@ ivas_error IVAS_DEC_VoIP_GetSamples( const uint32_t pcmBufSize, /* i : size of the PCM output buffer */ #endif const uint32_t systemTimestamp_ms /* i : current system timestamp */ +#ifdef MC_JBM +#ifdef SUPPORT_JBM_TRACEFILE + , JbmTraceFileWriter *jbmWriter +#endif +#endif ); /* Setter functions - apply changes to decoder configuration */ diff --git a/lib_util/jbm_file_writer.c b/lib_util/jbm_file_writer.c index bf34c51872..cb5e16e14b 100644 --- a/lib_util/jbm_file_writer.c +++ b/lib_util/jbm_file_writer.c @@ -78,7 +78,7 @@ ivas_error JbmOffsetFileWriter_open( return IVAS_ERR_FAILED_FILE_OPEN; } - self = calloc( sizeof( JbmTraceFileWriter ), 1 ); + self = calloc( sizeof( JbmOffsetFileWriter ), 1 ); self->file = file; self->file_path = calloc( sizeof( char ), strlen( jbmOffsetFilename ) + 1 ); strcpy( self->file_path, jbmOffsetFilename ); @@ -191,9 +191,6 @@ ivas_error JbmTraceFileWriter_open( JbmTraceFileWriter *self; FILE *file; -#ifdef SUPPORT_JBM_TRACEFILE -#endif - if ( strlen( jbmTraceFilename ) < 1 ) { return IVAS_ERR_FAILED_FILE_OPEN; @@ -227,8 +224,12 @@ ivas_error JbmTraceFileWriter_open( /*! r: error code */ ivas_error JbmTraceFileWriter_writeFrame( +#ifdef MC_JBM + const IVAS_JBM_TRACE_DATA *data, /* i : JBM trace data */ +#else const IVAS_JBM_TRACE_DATA *JbmTraceData, /* i : JBM trace data */ - JbmTraceFileWriter *jbmTraceWriter /* o : JbmTraceFileWriter handle */ +#endif + JbmTraceFileWriter *jbmTraceWriter /* o : JbmTraceFileWriter handle */ ) { FILE *file; @@ -242,21 +243,43 @@ ivas_error JbmTraceFileWriter_writeFrame( if ( file ) { +#ifdef MC_JBM + /* the first sample of the decoded/concealed frame will be played after the samples in the ring buffer */ + double playTime = data->systemTimestamp_ms + data->extBufferedSamples * 1000.0 / data->output_Fs; +#endif /* rtpSeqNo;rtpTs;rcvTime;playTime;active\n */ +#ifdef MC_JBM + if ( data->dataUnit_flag ) + { + if ( data->partial_frame == 1 ) +#else if ( JbmTraceData->dataUnit_flag ) { if ( JbmTraceData->partial_frame_flag == 1 ) +#endif { +#ifdef MC_JBM + fprintf( file, "%d;%d;%d;%f;%d;%d\n", -1, -1, -1, playTime, data->lastDecodedWasActive, data->partialCopyOffset ); +#else fprintf( file, "%d;%d;%d;%f;%d;%d\n", -1, -1, -1, JbmTraceData->playTime, JbmTraceData->lastDecodedWasActive, JbmTraceData->partialCopyOffset ); +#endif } else { +#ifdef MC_JBM + fprintf( file, "%u;%u;%u;%f;%d\n", data->sequenceNumber, data->timeStamp, data->rcvTime, playTime, data->lastDecodedWasActive ); +#else fprintf( file, "%u;%u;%u;%f;%d\n", JbmTraceData->sequenceNumber, JbmTraceData->timeStamp, JbmTraceData->rcvTime, JbmTraceData->playTime, JbmTraceData->lastDecodedWasActive ); +#endif } } else { +#ifdef MC_JBM + fprintf( file, "%d;%d;%d;%f;%d\n", -1, -1, -1, playTime, data->lastDecodedWasActive ); +#else fprintf( file, "%d;%d;%d;%f;%d\n", -1, -1, -1, JbmTraceData->playTime, JbmTraceData->lastDecodedWasActive ); +#endif } } else diff --git a/scripts/config/self_test.prm b/scripts/config/self_test.prm index 15e0be1ab5..ddf4ef386b 100644 --- a/scripts/config/self_test.prm +++ b/scripts/config/self_test.prm @@ -894,3 +894,24 @@ // Stereo downmix to bit-exact EVS at 24400 kbps, 48kHz in, 48kHz out ../IVAS_cod -stereo_dmx_evs 24400 48 testv/stvST48c.pcm bit ../IVAS_dec 48 bit testv/stvST48c.pcm_StereoDmxEVS_24400_48-48.tst + + +// MDCT stereo at 48 kbps, 16 kHz in, 16 kHz out, DTX on, JBM Prof 5 +../IVAS_cod -stereo -dtx 48000 16 testv/stvST16n.pcm bit +networkSimulator_g192 ../scripts/dly_error_profiles/dly_error_profile_5.dat bit netsimoutput tracefile_sim 2 0 +../IVAS_dec -Tracefile tracefile_dec -VOIP STEREO 16 netsimoutput testv/stvST16n.pcm_MDCT_48000_16-16_DTX_JBM5.tst + +// 4 ISm with metadata at 32 kbps, 48 kHz in, 48 kHz out, FOA out, JBM Prof 5 +../IVAS_cod -ism 4 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stvISM4.csv 32000 48 testv/stv4ISM48s.pcm bit +networkSimulator_g192 ../scripts/dly_error_profiles/dly_error_profile_5.dat bit netsimoutput tracefile_sim 2 0 +../IVAS_dec -Tracefile tracefile_dec -VOIP FOA 48 netsimoutput testv/stv4ISM48s.pcm_32000_48-48_FOA_JBM5.tst + +// SBA at 80 kbps, 32kHz in, 32kHz out, HOA3 out, JBM Prof 5 +../IVAS_cod -sba 3 80000 32 testv/stv3OA32c.pcm bit +networkSimulator_g192 ../scripts/dly_error_profiles/dly_error_profile_5.dat bit netsimoutput tracefile_sim 2 0 +../IVAS_dec -Tracefile tracefile_dec -VOIP HOA3 32 netsimoutput testv/stv3OA32c.pcm_SBA_80000_32-32_HOA3_JBM5.tst + +// Multi-channel 5_1 at 384 kbps, 48kHz in, 48kHz out, 7_1_4 out, JBM Prof 5 +../IVAS_cod -mc 5_1 384000 48 testv/stv51MC48c.pcm bit +networkSimulator_g192 ../scripts/dly_error_profiles/dly_error_profile_5.dat bit netsimoutput tracefile_sim 2 0 +../IVAS_dec -Tracefile tracefile_dec -VOIP 7_1_4 48 netsimoutput testv/stv51MC48c.pcm_MC51_384000_48-48_7_1_4_JBM5.tst \ No newline at end of file diff --git a/scripts/dly_error_profiles/dly_error_profile_0.dat b/scripts/dly_error_profiles/dly_error_profile_0.dat new file mode 100644 index 0000000000..804fcc90e9 --- /dev/null +++ b/scripts/dly_error_profiles/dly_error_profile_0.dat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa +size 2 diff --git a/scripts/pyaudio3dtools/audiofile.py b/scripts/pyaudio3dtools/audiofile.py index b03b472ae9..37367a49f5 100755 --- a/scripts/pyaudio3dtools/audiofile.py +++ b/scripts/pyaudio3dtools/audiofile.py @@ -764,3 +764,46 @@ def get_wav_file_info(filename: str) -> dict: "ext_param_size": ext_param_size, "ext_param": ext_param, } + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Tool for basic operations on audio files") + subparsers = parser.add_subparsers() + + def pre_trim_wrapper(pre_trim_args): + if pre_trim_args.input_file.endswith(".wav"): + input_file_properties = get_wav_file_info(pre_trim_args.input_file) + else: + print("Delay currently only supported with WAV file input") + exit(-1) + + x, _ = readfile(pre_trim_args.input_file, fs=input_file_properties["fs"], nchannels=input_file_properties["channels"]) + trim = int(pre_trim_args.amount_in_ms * input_file_properties["fs"] / 1000) + x = x[trim:] + writefile(pre_trim_args.output_file, x, fs=input_file_properties["fs"]) + + + parser_delay = subparsers.add_parser("pre-trim", help="Trim a given amount of content from the beginning of the file") + parser_delay.add_argument("amount_in_ms", type=float, help="Trim amount milliseconds.") + parser_delay.add_argument("input_file") + parser_delay.add_argument("output_file") + parser_delay.set_defaults(func=pre_trim_wrapper) + + def convert_wrapper(convert_args): + if not convert_args.input_file.endswith(".wav"): + print("Convert currently only supported with WAV file input") + exit(-1) + + convertfile(convert_args.input_file, convert_args.output_file) + + parser_convert = subparsers.add_parser( + "convert", help="Convert file format (output file extension determines output format)" + ) + parser_convert.add_argument("input_file") + parser_convert.add_argument("output_file") + parser_convert.set_defaults(func=convert_wrapper) + + args = parser.parse_args() + args.func(args) diff --git a/scripts/pyivastest/IvasModeRunner.py b/scripts/pyivastest/IvasModeRunner.py index 1c91c3f39f..e8ccfa6a0b 100755 --- a/scripts/pyivastest/IvasModeRunner.py +++ b/scripts/pyivastest/IvasModeRunner.py @@ -925,11 +925,11 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): ) if isinstance(dec_options, dict): if "dec_options" in dec_options: - dec_options["dec_options"].append(addl_dec_options) + dec_options["dec_options"].extend(addl_dec_options) else: dec_options["dec_options"] = addl_dec_options else: - dec_options.append(addl_dec_options) + dec_options.extend(addl_dec_options) dec_config = { "ivas_format": mode, "config": config, -- GitLab From fa289a3868926d0b6e7c5c1f5210de66f41f6b28 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Thu, 8 Dec 2022 11:47:32 +0100 Subject: [PATCH 06/37] Fix build after REMOVE_SID_HARM_LEFTOVERS was accepted --- apps/decoder.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/decoder.c b/apps/decoder.c index ec6073b7a4..f031aca018 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -1824,11 +1824,7 @@ static ivas_error printBitstreamInfoVoip( fprintf( stderr, "failed to read first RTP packet\n" ); goto cleanup; } -#ifdef REMOVE_SID_HARM_LEFTOVERS } while ( !qBit || auSizeBits < MIN_NUM_BITS_ACTIVE_FRAME || auSizeBits == NUM_BITS_SID_IVAS_5K2 ); -#else - } while ( !qBit || auSizeBits < MIN_NUM_BITS_ACTIVE_FRAME || auSizeBits == NUM_BITS_SID_IVAS_4K4 || auSizeBits == NUM_BITS_SID_IVAS_7K8 || auSizeBits == NUM_BITS_SID_IVAS_9K3 || auSizeBits == NUM_BITS_SID_IVAS_10K2 ); -#endif BS_Reader_Rewind( hBsReader ); -- GitLab From 8a9fa2c2a8114984a97f792dae7707451ca50f2c Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Thu, 8 Dec 2022 12:29:58 +0100 Subject: [PATCH 07/37] Fix formatting --- lib_dec/jbm_pcmdsp_apa.c | 12 +++++++----- lib_dec/lib_dec.c | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib_dec/jbm_pcmdsp_apa.c b/lib_dec/jbm_pcmdsp_apa.c index a1da5b6b66..6aa00344a1 100644 --- a/lib_dec/jbm_pcmdsp_apa.c +++ b/lib_dec/jbm_pcmdsp_apa.c @@ -150,7 +150,8 @@ static bool extend_frm( apa_state_t *ps, const int16_t frm_in[], int16_t frm_out uint8_t apa_init( apa_state_t **pps #ifdef MC_JBM - ,int32_t num_channels + , + int32_t num_channels #endif ) { @@ -221,9 +222,10 @@ bool apa_set_rate( apa_state_t *ps, const int32_t output_Fs #ifndef MC_JBM - ,const int16_t num_channels + , + const int16_t num_channels #endif - ) +) { /* make sure pointer is valid */ if ( ps == NULL ) @@ -439,7 +441,7 @@ bool apa_exit( #ifdef MC_JBM /* deallocate state struct members */ - count_free( (*pps)->buf_out ); + count_free( ( *pps )->buf_out ); #endif /* deallocate state struct */ @@ -612,7 +614,7 @@ uint8_t apa_exec( /* avoid buffer overflow: */ /* discard old samples; always keep at least most recent l_frm samples */ #ifdef MC_JBM - if ( ( ps->l_buf_out + l_frm_out ) > ps->buf_out_capacity ) + if ( ( ps->l_buf_out + l_frm_out ) > ps->buf_out_capacity ) #else if ( ( ps->l_buf_out + l_frm_out ) > APA_BUF ) #endif diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 4b2c17ac8c..d10a1df398 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -1769,7 +1769,7 @@ static void store_JbmData( } #endif - return; + return; } -- GitLab From 66ccef83b560c551bddabb80cf5e7c32042e586e Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Thu, 8 Dec 2022 16:38:47 +0100 Subject: [PATCH 08/37] Add CI job voip-be-on-merge-request --- .gitlab-ci.yml | 11 +++++++++++ ci/{jbm_be_test.sh => ivas_voip_be_test.sh} | 0 2 files changed, 11 insertions(+) rename ci/{jbm_be_test.sh => ivas_voip_be_test.sh} (100%) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7a0f5d3385..73edb3361a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -562,6 +562,17 @@ evs-pytest-on-merge-request: junit: - report-junit-evs.xml +voip-be-on-merge-request: + extends: + - .test-job-linux-needs-testv-dir + - .rules-merge-request + stage: compare # Or should it be test? Comparison is done within one git revision + needs: ["build-codec-linux-make", codec-smoke-test] + timeout: "10 minutes" + script: + - *print-common-info + - bash ci/ivas_voip_be_test.sh + clang-format-check: extends: - .test-job-linux diff --git a/ci/jbm_be_test.sh b/ci/ivas_voip_be_test.sh similarity index 100% rename from ci/jbm_be_test.sh rename to ci/ivas_voip_be_test.sh -- GitLab From 987cbdbd272f019f052e735c5444a39168020cba Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 9 Dec 2022 13:54:34 +0100 Subject: [PATCH 09/37] [dbg] check if/where netsim executable is available on the runners --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 73edb3361a..e26af82bb0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -571,6 +571,7 @@ voip-be-on-merge-request: timeout: "10 minutes" script: - *print-common-info + - which networkSimulator_g192 - bash ci/ivas_voip_be_test.sh clang-format-check: -- GitLab From 9f65603a591147839dbcd8a4b326a76a166aa727 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 9 Dec 2022 14:02:24 +0100 Subject: [PATCH 10/37] [dbg] check if/where netsim executable is available on the runners --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e26af82bb0..a4bfa0ab4c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -571,7 +571,7 @@ voip-be-on-merge-request: timeout: "10 minutes" script: - *print-common-info - - which networkSimulator_g192 + - echo $(which networkSimulator_g192) - bash ci/ivas_voip_be_test.sh clang-format-check: -- GitLab From 16f01ea91902997fb62d9ace7017d7a7e8b7caef Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 9 Dec 2022 14:16:19 +0100 Subject: [PATCH 11/37] Try to copy netsim to /tools on runner --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a4bfa0ab4c..f695a1c13f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -571,7 +571,7 @@ voip-be-on-merge-request: timeout: "10 minutes" script: - *print-common-info - - echo $(which networkSimulator_g192) + - cp networkSimulator_g192 /tools/ - bash ci/ivas_voip_be_test.sh clang-format-check: -- GitLab From 5bf20e0533dfe87dbe4f1a603e364c364db7501e Mon Sep 17 00:00:00 2001 From: knj Date: Fri, 9 Dec 2022 15:02:41 +0100 Subject: [PATCH 12/37] add network simulator binary for Linux runners --- scripts/tools/Linux/networkSimulator_g192 | Bin 0 -> 77160 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 scripts/tools/Linux/networkSimulator_g192 diff --git a/scripts/tools/Linux/networkSimulator_g192 b/scripts/tools/Linux/networkSimulator_g192 new file mode 100755 index 0000000000000000000000000000000000000000..1cca5f93056558c064adeff59ec7eef99bd6a26a GIT binary patch literal 77160 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 PArwRq8dq=*0|Ns9d63hs literal 0 HcmV?d00001 -- GitLab From 7b3424ba5f55d7f3ba7a10426a1166f9135cfaa5 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 9 Dec 2022 17:34:32 +0100 Subject: [PATCH 13/37] Add Linux tool dir to PATH before running VoIP BE job (hacky) --- .gitlab-ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f695a1c13f..0a46c7075e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -571,7 +571,11 @@ voip-be-on-merge-request: timeout: "10 minutes" script: - *print-common-info - - cp networkSimulator_g192 /tools/ + + # Hack to make runIvasCode.py find networkSimulator_g192 + - PATH=$PATH:$(pwd)/scripts/tools/Linux + - sed -i 's#"utilPath": "/tools"#"utilPath": ""#' scripts/config/ci_linux.json + - bash ci/ivas_voip_be_test.sh clang-format-check: -- GitLab From 6bb1fde385ece64253e5ddd570c8321de5623669 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 9 Dec 2022 17:59:20 +0100 Subject: [PATCH 14/37] Move setup to bash script --- .gitlab-ci.yml | 5 ----- ci/ivas_voip_be_test.sh | 4 ++++ 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0a46c7075e..73edb3361a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -571,11 +571,6 @@ voip-be-on-merge-request: timeout: "10 minutes" script: - *print-common-info - - # Hack to make runIvasCode.py find networkSimulator_g192 - - PATH=$PATH:$(pwd)/scripts/tools/Linux - - sed -i 's#"utilPath": "/tools"#"utilPath": ""#' scripts/config/ci_linux.json - - bash ci/ivas_voip_be_test.sh clang-format-check: diff --git a/ci/ivas_voip_be_test.sh b/ci/ivas_voip_be_test.sh index 38253a205f..a735b3c22d 100755 --- a/ci/ivas_voip_be_test.sh +++ b/ci/ivas_voip_be_test.sh @@ -38,6 +38,10 @@ network_profile_path="scripts/dly_error_profiles/dly_error_profile_0.dat" output_dir_default="out" output_dir_voip="out_voip" +# Hack to make runIvasCodec.py find networkSimulator_g192 +PATH=$PATH:$(pwd)/scripts/tools/Linux +sed -i 's#"utilPath": "/tools"#"utilPath": ""#' scripts/config/ci_linux.json + # Build IVAS make clean make all -j 8 -- GitLab From 24fcdea63e071608e4b79cbf889fc4aea2a2e4b6 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 9 Dec 2022 18:18:30 +0100 Subject: [PATCH 15/37] Try make executables from /tools available again (again, hacky) --- ci/ivas_voip_be_test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/ivas_voip_be_test.sh b/ci/ivas_voip_be_test.sh index a735b3c22d..54c992e268 100755 --- a/ci/ivas_voip_be_test.sh +++ b/ci/ivas_voip_be_test.sh @@ -38,8 +38,8 @@ network_profile_path="scripts/dly_error_profiles/dly_error_profile_0.dat" output_dir_default="out" output_dir_voip="out_voip" -# Hack to make runIvasCodec.py find networkSimulator_g192 -PATH=$PATH:$(pwd)/scripts/tools/Linux +# Hack to make runIvasCodec.py find networkSimulator_g192 and other executables from /tools +PATH=$PATH:$(pwd)/scripts/tools/Linux:/tools sed -i 's#"utilPath": "/tools"#"utilPath": ""#' scripts/config/ci_linux.json # Build IVAS -- GitLab From 14f1b5e5db0a65e3b7382ee21e60b504cffa2a61 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Sat, 10 Dec 2022 22:51:41 +0100 Subject: [PATCH 16/37] Added ../lib_util to lib_rend.vcxproj to make VS project build --- Workspace_msvc/lib_rend.vcxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Workspace_msvc/lib_rend.vcxproj b/Workspace_msvc/lib_rend.vcxproj index c3a1268694..e0660f54cb 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 -- GitLab From c2f7db2b16f704223f462d3b3369e4cc6f4b0011 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Mon, 12 Dec 2022 12:26:22 +0100 Subject: [PATCH 17/37] Try to copy netsim to /tools --- .gitlab-ci.yml | 1 + ci/ivas_voip_be_test.sh | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 73edb3361a..9f216e2be0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -571,6 +571,7 @@ voip-be-on-merge-request: timeout: "10 minutes" script: - *print-common-info + - cp scripts/tools/Linux/networkSimulator_g192 /tools - bash ci/ivas_voip_be_test.sh clang-format-check: diff --git a/ci/ivas_voip_be_test.sh b/ci/ivas_voip_be_test.sh index 54c992e268..38253a205f 100755 --- a/ci/ivas_voip_be_test.sh +++ b/ci/ivas_voip_be_test.sh @@ -38,10 +38,6 @@ network_profile_path="scripts/dly_error_profiles/dly_error_profile_0.dat" output_dir_default="out" output_dir_voip="out_voip" -# Hack to make runIvasCodec.py find networkSimulator_g192 and other executables from /tools -PATH=$PATH:$(pwd)/scripts/tools/Linux:/tools -sed -i 's#"utilPath": "/tools"#"utilPath": ""#' scripts/config/ci_linux.json - # Build IVAS make clean make all -j 8 -- GitLab From d94bce507106208bc6c965ab37a288b09e2789f6 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Mon, 12 Dec 2022 12:39:14 +0100 Subject: [PATCH 18/37] Try to copy from /tools --- .gitlab-ci.yml | 1 - ci/ivas_voip_be_test.sh | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9f216e2be0..73edb3361a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -571,7 +571,6 @@ voip-be-on-merge-request: timeout: "10 minutes" script: - *print-common-info - - cp scripts/tools/Linux/networkSimulator_g192 /tools - bash ci/ivas_voip_be_test.sh clang-format-check: diff --git a/ci/ivas_voip_be_test.sh b/ci/ivas_voip_be_test.sh index 38253a205f..701cf3d91f 100755 --- a/ci/ivas_voip_be_test.sh +++ b/ci/ivas_voip_be_test.sh @@ -38,6 +38,10 @@ network_profile_path="scripts/dly_error_profiles/dly_error_profile_0.dat" output_dir_default="out" output_dir_voip="out_voip" +# Hack to make runIvasCodec.py find networkSimulator_g192 and other executables from /tools +cp /tools/* scripts/tools/Linux +sed -i 's#"utilPath": "/tools"#"utilPath": "scripts/tools/Linux"#' scripts/config/ci_linux.json + # Build IVAS make clean make all -j 8 -- GitLab From b17c373a1c027cb789127fed6d78f03c2bec8c89 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Mon, 12 Dec 2022 13:01:11 +0100 Subject: [PATCH 19/37] Use absolute path for tools dir --- ci/ivas_voip_be_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/ivas_voip_be_test.sh b/ci/ivas_voip_be_test.sh index 701cf3d91f..28739e4c1d 100755 --- a/ci/ivas_voip_be_test.sh +++ b/ci/ivas_voip_be_test.sh @@ -40,7 +40,7 @@ output_dir_voip="out_voip" # Hack to make runIvasCodec.py find networkSimulator_g192 and other executables from /tools cp /tools/* scripts/tools/Linux -sed -i 's#"utilPath": "/tools"#"utilPath": "scripts/tools/Linux"#' scripts/config/ci_linux.json +sed -i "s#\"utilPath\": \"/tools\"#\"utilPath\": \"$(pwd)/scripts/tools/Linux\"#" scripts/config/ci_linux.json # Build IVAS make clean -- GitLab From 2a714616db869eb58e3609f0709c369f68e449a3 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Mon, 12 Dec 2022 13:09:21 +0100 Subject: [PATCH 20/37] Switch to runner with netsim pre-installed in /tools --- .gitlab-ci.yml | 2 ++ ci/ivas_voip_be_test.sh | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 73edb3361a..61ec80a6d5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -572,6 +572,8 @@ voip-be-on-merge-request: script: - *print-common-info - bash ci/ivas_voip_be_test.sh + tags: + - test-fhg-linux-runner1 clang-format-check: extends: diff --git a/ci/ivas_voip_be_test.sh b/ci/ivas_voip_be_test.sh index 28739e4c1d..38253a205f 100755 --- a/ci/ivas_voip_be_test.sh +++ b/ci/ivas_voip_be_test.sh @@ -38,10 +38,6 @@ network_profile_path="scripts/dly_error_profiles/dly_error_profile_0.dat" output_dir_default="out" output_dir_voip="out_voip" -# Hack to make runIvasCodec.py find networkSimulator_g192 and other executables from /tools -cp /tools/* scripts/tools/Linux -sed -i "s#\"utilPath\": \"/tools\"#\"utilPath\": \"$(pwd)/scripts/tools/Linux\"#" scripts/config/ci_linux.json - # Build IVAS make clean make all -j 8 -- GitLab From 7eedf38110a9eaa26f99f3b19db022a087d279e5 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Mon, 12 Dec 2022 13:17:54 +0100 Subject: [PATCH 21/37] Use a different runner for VoIP BE job --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 61ec80a6d5..c461f2b6b9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -573,7 +573,7 @@ voip-be-on-merge-request: - *print-common-info - bash ci/ivas_voip_be_test.sh tags: - - test-fhg-linux-runner1 + - test-fhg-linux-runner2 clang-format-check: extends: -- GitLab From ab3c02d05617ad90b12a34973d5225575e9564d1 Mon Sep 17 00:00:00 2001 From: knj Date: Mon, 12 Dec 2022 13:32:27 +0100 Subject: [PATCH 22/37] print stderr from thread when processing step fails --- scripts/pyivastest/IvasModeRunner.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/pyivastest/IvasModeRunner.py b/scripts/pyivastest/IvasModeRunner.py index e8ccfa6a0b..bc5f24edaf 100644 --- a/scripts/pyivastest/IvasModeRunner.py +++ b/scripts/pyivastest/IvasModeRunner.py @@ -829,7 +829,7 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): enc_log = open(enc_log_name, "a") enc_log.write(" ".join(proc_cmd)) proc_result = subprocess.run( - proc_cmd, capture_output=True, text=True + proc_cmd, capture_output=True, text=True, encoding="utf8" ) enc_log.write(proc_result.stderr) enc_log.write(proc_result.stdout) @@ -840,9 +840,10 @@ class IvasModeRunner(IvasModeCollector.IvasModeCollector): suffix, enc_file_name ) ) + self.logger.error(proc_result.stderr) raise RuntimeError( - "Processing step {} for {} failed!".format( - suffix, enc_file_name + "Processing step {} for {} failed!\n{}".format( + suffix, enc_file_name, proc_result.stderr ) ) bs_in_file = bs_out_file -- GitLab From f56fb29d71cdee95514d9b1910ed864f04ba1825 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Tue, 13 Dec 2022 10:29:33 +0100 Subject: [PATCH 23/37] Remove JBM test condition failing due to range coder problems The range coder issue is tracked in https://forge.3gpp.org/rep/ivas-codec-pc/ivas-codec/-/issues/245 --- scripts/config/self_test.prm | 5 ----- 1 file changed, 5 deletions(-) diff --git a/scripts/config/self_test.prm b/scripts/config/self_test.prm index 04d7b9c85c..db5c7253cf 100644 --- a/scripts/config/self_test.prm +++ b/scripts/config/self_test.prm @@ -910,8 +910,3 @@ networkSimulator_g192 ../scripts/dly_error_profiles/dly_error_profile_5.dat bit ../IVAS_cod -sba 3 80000 32 testv/stv3OA32c.pcm bit networkSimulator_g192 ../scripts/dly_error_profiles/dly_error_profile_5.dat bit netsimoutput tracefile_sim 2 0 ../IVAS_dec -Tracefile tracefile_dec -VOIP HOA3 32 netsimoutput testv/stv3OA32c.pcm_SBA_80000_32-32_HOA3_JBM5.tst - -// Multi-channel 5_1 at 384 kbps, 48kHz in, 48kHz out, 7_1_4 out, JBM Prof 5 -../IVAS_cod -mc 5_1 384000 48 testv/stv51MC48c.pcm bit -networkSimulator_g192 ../scripts/dly_error_profiles/dly_error_profile_5.dat bit netsimoutput tracefile_sim 2 0 -../IVAS_dec -Tracefile tracefile_dec -VOIP 7_1_4 48 netsimoutput testv/stv51MC48c.pcm_MC51_384000_48-48_7_1_4_JBM5.tst \ No newline at end of file -- GitLab From e821ed7832fd4ecb41fc81a642fedef9e6272339 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Tue, 13 Dec 2022 12:29:19 +0100 Subject: [PATCH 24/37] Fix MSVC warnings --- lib_dec/jbm_pcmdsp_apa.c | 4 ++-- lib_dec/lib_dec.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib_dec/jbm_pcmdsp_apa.c b/lib_dec/jbm_pcmdsp_apa.c index 6aa00344a1..1b37eff902 100644 --- a/lib_dec/jbm_pcmdsp_apa.c +++ b/lib_dec/jbm_pcmdsp_apa.c @@ -170,8 +170,8 @@ uint8_t apa_init( return 2; } #ifdef MC_JBM - ps->num_channels = num_channels; - ps->buf_out_capacity = APA_BUF_PER_CHANNEL * num_channels; + ps->num_channels = (uint16_t) num_channels; + ps->buf_out_capacity = (uint16_t) ( APA_BUF_PER_CHANNEL * num_channels ); ps->buf_out = count_malloc( sizeof( float ) * ps->buf_out_capacity ); if ( !ps->buf_out ) { diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index d10a1df398..c495872359 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -1243,7 +1243,7 @@ static void bsCompactToSerial( const uint8_t *compact, uint16_t *serial, uint16_ /* Bitstream conversion is not counted towards complexity and memory usage */ #define WMC_TOOL_MAN uint32_t i; - uint8_t byte; + uint8_t byte = 0; const uint8_t mask = 0x80; for ( i = 0; i < num_bits; ++i ) -- GitLab From 53d048e6c19dfe5c4cd65495b4b60c09e70c1b30 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Thu, 15 Dec 2022 11:55:04 +0100 Subject: [PATCH 25/37] Fix EVS VoIP mode with MC_JBM disabled --- lib_dec/jbm_pcmdsp_apa.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib_dec/jbm_pcmdsp_apa.c b/lib_dec/jbm_pcmdsp_apa.c index 1b37eff902..7bee5f9b5f 100644 --- a/lib_dec/jbm_pcmdsp_apa.c +++ b/lib_dec/jbm_pcmdsp_apa.c @@ -245,12 +245,14 @@ bool apa_set_rate( /* copy rate to state struct */ ps->rate = (uint16_t) output_Fs; - /* set number of channels */ #ifdef MC_JBM if ( ps->num_channels > APA_MAX_NUM_CHANNELS ) { return 1; } +#else + /* set number of channels */ + ps->num_channels = num_channels; #endif /* -- GitLab From dfbd0e1958450edfed87ac5fdc644655ee2e9caa Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 16 Dec 2022 10:43:15 +0100 Subject: [PATCH 26/37] Include rate switching condition in voip be test --- ci/ivas_voip_be_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/ivas_voip_be_test.sh b/ci/ivas_voip_be_test.sh index 38253a205f..cd16c4b238 100755 --- a/ci/ivas_voip_be_test.sh +++ b/ci/ivas_voip_be_test.sh @@ -29,7 +29,7 @@ # the United Nations Convention on Contracts on the International Sales of Goods. # Configuration -modes=('SBA_b128_wb_cbr' 'MC_7_1_b96_fb_cbr' 'ISM2_b48_fb_cbr') # 'stereo_b32_128_fb_rs') # stereo mode sems broken in decoder +modes=('SBA_b128_wb_cbr' 'MC_7_1_b96_fb_cbr' 'ISM2_b48_fb_cbr' 'stereo_b32_128_fb_rs') output_formats=('STEREO' 'FOA' '7_1' 'HOA3') limit_input_to_x_seconds=30 -- GitLab From bb729b09b03ddea3e48cd88e6d56bb2a1c5a603e Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 16 Dec 2022 17:30:25 +0100 Subject: [PATCH 27/37] Add error check after runIvasCodec --- ci/ivas_voip_be_test.sh | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/ci/ivas_voip_be_test.sh b/ci/ivas_voip_be_test.sh index cd16c4b238..ac59dedcd9 100755 --- a/ci/ivas_voip_be_test.sh +++ b/ci/ivas_voip_be_test.sh @@ -1,4 +1,4 @@ -#! /usr/local/bin/bash +#! /usr/bin/bash # (C) 2022 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., @@ -29,7 +29,7 @@ # the United Nations Convention on Contracts on the International Sales of Goods. # Configuration -modes=('SBA_b128_wb_cbr' 'MC_7_1_b96_fb_cbr' 'ISM2_b48_fb_cbr' 'stereo_b32_128_fb_rs') +modes=('SBA_b128_wb_cbr' 'MC_7_1_b96_fb_cbr' 'ISM2_b48_fb_cbr') output_formats=('STEREO' 'FOA' '7_1' 'HOA3') limit_input_to_x_seconds=30 @@ -46,6 +46,13 @@ make all -j 8 ./scripts/runIvasCodec.py -p ./scripts/config/ci_linux.json -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_default | tee jbm_be_test_output.txt ./scripts/runIvasCodec.py -p ./scripts/config/ci_linux.json -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_voip -J "$network_profile_path" | tee -a jbm_be_test_output.txt +# Check if Python scripts above failed. They return status 0 even when running a mode fails, so we have to parse log file +run_errors=$(grep -i error jbm_be_test_output.txt) || true +if [ "$run_errors" != 0 ] ; then + echo "Run errors in runIvasCodec.py" + exit 1 +fi + # Set up Python path python_audio_module_path=$(pwd)/scripts export PYTHONPATH=$python_audio_module_path:$PYTHONPATH @@ -101,5 +108,5 @@ if [ $all_be -eq 1 ]; then printf "\n\nAll tested conditions are bit-exact\n" | tee -a jbm_be_test_output.txt else printf "\n\nBitexactness problems found!\n" | tee -a jbm_be_test_output.txt - exit 255; + exit 1; fi -- GitLab From 525f185f1ee81e8f351b1a0167bbd0ee9096f802 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 16 Dec 2022 17:31:36 +0100 Subject: [PATCH 28/37] Add missing tag to voip be job --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8a2bcd106a..3dae45b7ee 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -573,6 +573,7 @@ voip-be-on-merge-request: - *print-common-info - bash ci/ivas_voip_be_test.sh tags: + - test-fhg-linux-runner1 - test-fhg-linux-runner2 clang-format-check: -- GitLab From 05f211018b478abb7b91f405f3d1a1fffaf7f21e Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 16 Dec 2022 17:45:09 +0100 Subject: [PATCH 29/37] Revert "Add missing tag to voip be job" This reverts commit 525f185f1ee81e8f351b1a0167bbd0ee9096f802. --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3dae45b7ee..8a2bcd106a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -573,7 +573,6 @@ voip-be-on-merge-request: - *print-common-info - bash ci/ivas_voip_be_test.sh tags: - - test-fhg-linux-runner1 - test-fhg-linux-runner2 clang-format-check: -- GitLab From 591cd2ff6e4f12494660c77fc730447e7af9a1fa Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 16 Dec 2022 17:51:12 +0100 Subject: [PATCH 30/37] Use a different word for determining if runIvasCodec.py failed --- ci/ivas_voip_be_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/ivas_voip_be_test.sh b/ci/ivas_voip_be_test.sh index ac59dedcd9..01065f7f94 100755 --- a/ci/ivas_voip_be_test.sh +++ b/ci/ivas_voip_be_test.sh @@ -47,7 +47,7 @@ make all -j 8 ./scripts/runIvasCodec.py -p ./scripts/config/ci_linux.json -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_voip -J "$network_profile_path" | tee -a jbm_be_test_output.txt # Check if Python scripts above failed. They return status 0 even when running a mode fails, so we have to parse log file -run_errors=$(grep -i error jbm_be_test_output.txt) || true +run_errors=$(grep -i failed jbm_be_test_output.txt) || true if [ "$run_errors" != 0 ] ; then echo "Run errors in runIvasCodec.py" exit 1 -- GitLab From 7bf9c9dffc2a0fd5c4d86c0efac1bd7f25a9f57a Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Mon, 19 Dec 2022 09:29:27 +0100 Subject: [PATCH 31/37] Try to fix parsing of voip be test log --- ci/ivas_voip_be_test.sh | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/ci/ivas_voip_be_test.sh b/ci/ivas_voip_be_test.sh index 01065f7f94..d65677b498 100755 --- a/ci/ivas_voip_be_test.sh +++ b/ci/ivas_voip_be_test.sh @@ -43,12 +43,11 @@ make clean make all -j 8 # Run the same modes in VoIP and non-VoIP mode with a neutral delay profile -./scripts/runIvasCodec.py -p ./scripts/config/ci_linux.json -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_default | tee jbm_be_test_output.txt -./scripts/runIvasCodec.py -p ./scripts/config/ci_linux.json -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_voip -J "$network_profile_path" | tee -a jbm_be_test_output.txt +./scripts/runIvasCodec.py -p ./scripts/config/ci_linux.json -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_default | tee voip_be_test_output.txt +./scripts/runIvasCodec.py -p ./scripts/config/ci_linux.json -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_voip -J "$network_profile_path" | tee -a voip_be_test_output.txt # Check if Python scripts above failed. They return status 0 even when running a mode fails, so we have to parse log file -run_errors=$(grep -i failed jbm_be_test_output.txt) || true -if [ "$run_errors" != 0 ] ; then +if grep -iq failed voip_be_test_output.txt ; then echo "Run errors in runIvasCodec.py" exit 1 fi @@ -69,7 +68,7 @@ fi for cut in "$output_dir_voip_dec"/*.wav; do output_path=${cut/$output_dir_voip_dec/$output_dir_voip_dec_trimmed} output_path=${output_path/".wav"/".raw"} - python3 "$python_audiofile_script_path" pre-trim 60 "$cut" "$output_path" | tee -a jbm_be_test_output.txt + python3 "$python_audiofile_script_path" pre-trim 60 "$cut" "$output_path" | tee -a voip_be_test_output.txt done # Convert non-VoIP output from wav to pcm (comparison script doesn't support wav) @@ -83,7 +82,7 @@ fi for ref in "$output_dir_default_dec"/*.wav; do output_path=${ref/$output_dir_default_dec/$output_dir_default_dec_pcm} output_path=${output_path/".wav"/".raw"} - python3 "$python_audiofile_script_path" convert "$ref" "$output_path" | tee -a jbm_be_test_output.txt + python3 "$python_audiofile_script_path" convert "$ref" "$output_path" | tee -a voip_be_test_output.txt done # Assert BE between non-VoIP and VoIP modes @@ -96,17 +95,17 @@ for ref in "$output_dir_default_dec_pcm"/*; do cut=${cut/".dec."/"_jbm_dly_error_profile_0_dat.dec."} # Print paths of compared files, since the script doesn't do it - printf "\nComparing %s and %s\n" "$ref" "$cut" | tee -a jbm_be_test_output.txt + printf "\nComparing %s and %s\n" "$ref" "$cut" | tee -a voip_be_test_output.txt printout=$($cmp_custom_path "$ref" "$cut" 2 0) if [ $? -ne 0 ]; then all_be=0 fi - printf "%s\n" "$printout" | tee -a jbm_be_test_output.txt + printf "%s\n" "$printout" | tee -a voip_be_test_output.txt done if [ $all_be -eq 1 ]; then - printf "\n\nAll tested conditions are bit-exact\n" | tee -a jbm_be_test_output.txt + printf "\n\nAll tested conditions are bit-exact\n" | tee -a voip_be_test_output.txt else - printf "\n\nBitexactness problems found!\n" | tee -a jbm_be_test_output.txt + printf "\n\nBitexactness problems found!\n" | tee -a voip_be_test_output.txt exit 1; fi -- GitLab From cb62c667e94ca5b812d16ac8040f0d5e5439ac8a Mon Sep 17 00:00:00 2001 From: knj Date: Mon, 19 Dec 2022 11:51:56 +0100 Subject: [PATCH 32/37] add jbm testing to smoke test --- ci/smoke_test.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ci/smoke_test.sh b/ci/smoke_test.sh index 3d7b85fdba..5ba890c443 100755 --- a/ci/smoke_test.sh +++ b/ci/smoke_test.sh @@ -33,8 +33,15 @@ if [ ! -d "lib_com" ]; then exit 1 fi +cfg=./scripts/config/ci_linux.json +dly_profile=./scripts/dly_error_profiles/dly_error_profile_10.dat + make clean make all -j 8 -./scripts/runIvasCodec.py -p ./scripts/config/ci_linux.json -U 1 | tee smoke_test_output.txt -./scripts/runIvasCodec.py -p ./scripts/config/ci_linux.json -U 1 -D="-fec 15" --decoder_only | tee smoke_test_output_plc.txt +./scripts/runIvasCodec.py -p $cfg -U 1 | tee smoke_test_output.txt +./scripts/runIvasCodec.py -p $cfg -U 1 -D="-fec 15" --decoder_only | tee smoke_test_output_plc.txt + +modes_with_no_ext_out=$(./scripts/runIvasCodec.py -l | grep -v MASA | grep -v ISM) +./scripts/runIvasCodec.py -m $modes_with_no_ext_out -p $cfg -U 1 --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 --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 \ No newline at end of file -- GitLab From ced3ed6fafba8fe2c24c10feaede6fa104971552 Mon Sep 17 00:00:00 2001 From: knj Date: Mon, 19 Dec 2022 11:53:05 +0100 Subject: [PATCH 33/37] add artifact to smoke test --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8a2bcd106a..a33daefc2c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -276,6 +276,7 @@ codec-smoke-test: - out/logs/ - smoke_test_output.txt - smoke_test_output_plc.txt + - smoke_test_output_jbm_noEXT.txt expose_as: "Smoke test results" # code selftest testvectors with memory-sanitizer binaries -- GitLab From 04501bbbcf8c694b8d2a304b61f42f37d0158f77 Mon Sep 17 00:00:00 2001 From: knj Date: Mon, 19 Dec 2022 12:00:04 +0100 Subject: [PATCH 34/37] check for failure correctly in smoke test --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a33daefc2c..89e67140ce 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -270,6 +270,7 @@ codec-smoke-test: ### analyze for failures - if cat smoke_test_output.txt | grep -c "failed"; then echo "Smoke test without PLC failed"; exit 1; fi - if cat smoke_test_output_plc.txt | grep -c "failed"; then echo "Smoke test with PLC failed"; exit 1; fi + - if cat smoke_test_output_jbm_noEXT.txt | grep -c "failed"; then echo "Smoke test with PLC failed"; exit 1; fi artifacts: name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" paths: -- GitLab From bfe2e15d2391a2d8c6482c6631881517d5b2afed Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Mon, 19 Dec 2022 17:50:10 +0100 Subject: [PATCH 35/37] Update network simulator executable --- scripts/tools/Linux/networkSimulator_g192 | Bin 77160 -> 89760 bytes 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 scripts/tools/Linux/networkSimulator_g192 diff --git a/scripts/tools/Linux/networkSimulator_g192 b/scripts/tools/Linux/networkSimulator_g192 old mode 100755 new mode 100644 index 1cca5f93056558c064adeff59ec7eef99bd6a26a..8b1a6de4d97a252e16e8ce1993f46ebcaf5a62ea GIT binary patch literal 89760 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

6HcnK;$Aw``lDD5l&FY!3; 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 PArwRq8dq=*0|Ns9d63hs -- GitLab From 2c9bd613d0f48b089ad3084f5c32b52cbb9cdca2 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Tue, 20 Dec 2022 12:15:48 +0100 Subject: [PATCH 36/37] Remove tag from VoIP BE job - all runners should now have netsim available --- .gitlab-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 790e55050e..221c6c2b16 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -574,8 +574,6 @@ voip-be-on-merge-request: script: - *print-common-info - bash ci/ivas_voip_be_test.sh - tags: - - test-fhg-linux-runner2 clang-format-check: extends: -- GitLab From 9ef902c832e6917ceb7484d7a08076bdc674e562 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Tue, 20 Dec 2022 12:14:47 +0100 Subject: [PATCH 37/37] [tmp] remove VoIP self-test conditions before merge to main This commit will be reverted and merged to main separately --- scripts/config/self_test.prm | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/scripts/config/self_test.prm b/scripts/config/self_test.prm index 5e419a04a7..50d8447a06 100644 --- a/scripts/config/self_test.prm +++ b/scripts/config/self_test.prm @@ -898,19 +898,3 @@ // Stereo downmix to bit-exact EVS at 24400 kbps, 48kHz in, 48kHz out ../IVAS_cod -stereo_dmx_evs 24400 48 testv/stvST48c.pcm bit ../IVAS_dec 48 bit testv/stvST48c.pcm_StereoDmxEVS_24400_48-48.tst - - -// MDCT stereo at 48 kbps, 16 kHz in, 16 kHz out, DTX on, JBM Prof 5 -../IVAS_cod -stereo -dtx 48000 16 testv/stvST16n.pcm bit -networkSimulator_g192 ../scripts/dly_error_profiles/dly_error_profile_5.dat bit netsimoutput tracefile_sim 2 0 -../IVAS_dec -Tracefile tracefile_dec -VOIP STEREO 16 netsimoutput testv/stvST16n.pcm_MDCT_48000_16-16_DTX_JBM5.tst - -// 4 ISm with metadata at 32 kbps, 48 kHz in, 48 kHz out, FOA out, JBM Prof 5 -../IVAS_cod -ism 4 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stvISM4.csv 32000 48 testv/stv4ISM48s.pcm bit -networkSimulator_g192 ../scripts/dly_error_profiles/dly_error_profile_5.dat bit netsimoutput tracefile_sim 2 0 -../IVAS_dec -Tracefile tracefile_dec -VOIP FOA 48 netsimoutput testv/stv4ISM48s.pcm_32000_48-48_FOA_JBM5.tst - -// SBA at 80 kbps, 32kHz in, 32kHz out, HOA3 out, JBM Prof 5 -../IVAS_cod -sba 3 80000 32 testv/stv3OA32c.pcm bit -networkSimulator_g192 ../scripts/dly_error_profiles/dly_error_profile_5.dat bit netsimoutput tracefile_sim 2 0 -../IVAS_dec -Tracefile tracefile_dec -VOIP HOA3 32 netsimoutput testv/stv3OA32c.pcm_SBA_80000_32-32_HOA3_JBM5.tst -- GitLab